|
@@ -569,3 +569,100 @@ out:
|
|
|
if (!IS_ERR(hdmi_ick))
|
|
|
clk_put(hdmi_ick);
|
|
|
}
|
|
|
+
|
|
|
+/* USBHS0 is connected to CN22 which takes a USB Mini-B plug
|
|
|
+ *
|
|
|
+ * The sh7372 SoC has IRQ7 set aside for USBHS0 hotplug,
|
|
|
+ * but on this particular board IRQ7 is already used by
|
|
|
+ * the touch screen. This leaves us with software polling.
|
|
|
+ */
|
|
|
+#define USBHS0_POLL_INTERVAL (HZ * 5)
|
|
|
+
|
|
|
+struct usbhs_private {
|
|
|
+ void __iomem *usbphyaddr;
|
|
|
+ void __iomem *usbcrcaddr;
|
|
|
+ struct renesas_usbhs_platform_info info;
|
|
|
+ struct delayed_work work;
|
|
|
+ struct platform_device *pdev;
|
|
|
+};
|
|
|
+
|
|
|
+#define usbhs_get_priv(pdev) \
|
|
|
+ container_of(renesas_usbhs_get_info(pdev), \
|
|
|
+ struct usbhs_private, info)
|
|
|
+
|
|
|
+#define usbhs_is_connected(priv) \
|
|
|
+ (!((1 << 7) & __raw_readw(priv->usbcrcaddr)))
|
|
|
+
|
|
|
+static int usbhs_get_vbus(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ return usbhs_is_connected(usbhs_get_priv(pdev));
|
|
|
+}
|
|
|
+
|
|
|
+static void usbhs_phy_reset(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ struct usbhs_private *priv = usbhs_get_priv(pdev);
|
|
|
+
|
|
|
+ /* init phy */
|
|
|
+ __raw_writew(0x8a0a, priv->usbcrcaddr);
|
|
|
+}
|
|
|
+
|
|
|
+static int usbhs0_get_id(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ return USBHS_GADGET;
|
|
|
+}
|
|
|
+
|
|
|
+static void usbhs0_work_function(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct usbhs_private *priv = container_of(work, struct usbhs_private,
|
|
|
+ work.work);
|
|
|
+
|
|
|
+ renesas_usbhs_call_notify_hotplug(priv->pdev);
|
|
|
+ schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL);
|
|
|
+}
|
|
|
+
|
|
|
+static int usbhs0_hardware_init(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ struct usbhs_private *priv = usbhs_get_priv(pdev);
|
|
|
+
|
|
|
+ priv->pdev = pdev;
|
|
|
+ INIT_DELAYED_WORK(&priv->work, usbhs0_work_function);
|
|
|
+ schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void usbhs0_hardware_exit(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ struct usbhs_private *priv = usbhs_get_priv(pdev);
|
|
|
+
|
|
|
+ cancel_delayed_work_sync(&priv->work);
|
|
|
+}
|
|
|
+
|
|
|
+static struct usbhs_private usbhs0_private = {
|
|
|
+ .usbcrcaddr = IOMEM(0xe605810c), /* USBCR2 */
|
|
|
+ .info = {
|
|
|
+ .platform_callback = {
|
|
|
+ .hardware_init = usbhs0_hardware_init,
|
|
|
+ .hardware_exit = usbhs0_hardware_exit,
|
|
|
+ .phy_reset = usbhs_phy_reset,
|
|
|
+ .get_id = usbhs0_get_id,
|
|
|
+ .get_vbus = usbhs_get_vbus,
|
|
|
+ },
|
|
|
+ .driver_param = {
|
|
|
+ .buswait_bwait = 4,
|
|
|
+ .d0_tx_id = SHDMA_SLAVE_USB0_TX,
|
|
|
+ .d1_rx_id = SHDMA_SLAVE_USB0_RX,
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+static struct resource usbhs0_resources[] = {
|
|
|
+ [0] = {
|
|
|
+ .name = "USBHS0",
|
|
|
+ .start = 0xe6890000,
|
|
|
+ .end = 0xe68900e6 - 1,
|
|
|
+ .flags = IORESOURCE_MEM,
|
|
|
+ },
|
|
|
+ [1] = {
|
|
|
+ .start = evt2irq(0x1ca0) /* USB0_USB0I0 */,
|
|
|
+ .flags = IORESOURCE_IRQ,
|
|
|
+ },
|