18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2005-2006 by Texas Instruments 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This file is part of the Inventra Controller Driver for Linux. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/sched.h> 118c2ecf20Sopenharmony_ci#include <linux/list.h> 128c2ecf20Sopenharmony_ci#include <linux/delay.h> 138c2ecf20Sopenharmony_ci#include <linux/clk.h> 148c2ecf20Sopenharmony_ci#include <linux/err.h> 158c2ecf20Sopenharmony_ci#include <linux/io.h> 168c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h> 178c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 188c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 198c2ecf20Sopenharmony_ci#include <linux/usb/usb_phy_generic.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <mach/cputype.h> 228c2ecf20Sopenharmony_ci#include <mach/hardware.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <asm/mach-types.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include "musb_core.h" 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include "davinci.h" 298c2ecf20Sopenharmony_ci#include "cppi_dma.h" 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR) 338c2ecf20Sopenharmony_ci#define DM355_DEEPSLEEP IO_ADDRESS(DM355_DEEPSLEEP_PADDR) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistruct davinci_glue { 368c2ecf20Sopenharmony_ci struct device *dev; 378c2ecf20Sopenharmony_ci struct platform_device *musb; 388c2ecf20Sopenharmony_ci struct clk *clk; 398c2ecf20Sopenharmony_ci bool vbus_state; 408c2ecf20Sopenharmony_ci struct gpio_desc *vbus; 418c2ecf20Sopenharmony_ci struct work_struct vbus_work; 428c2ecf20Sopenharmony_ci}; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* REVISIT (PM) we should be able to keep the PHY in low power mode most 458c2ecf20Sopenharmony_ci * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0 468c2ecf20Sopenharmony_ci * and, when in host mode, autosuspending idle root ports... PHYPLLON 478c2ecf20Sopenharmony_ci * (overriding SUSPENDM?) then likely needs to stay off. 488c2ecf20Sopenharmony_ci */ 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic inline void phy_on(void) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* power everything up; start the on-chip PHY and its PLL */ 558c2ecf20Sopenharmony_ci phy_ctrl &= ~(USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN); 568c2ecf20Sopenharmony_ci phy_ctrl |= USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON; 578c2ecf20Sopenharmony_ci __raw_writel(phy_ctrl, USB_PHY_CTRL); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /* wait for PLL to lock before proceeding */ 608c2ecf20Sopenharmony_ci while ((__raw_readl(USB_PHY_CTRL) & USBPHY_PHYCLKGD) == 0) 618c2ecf20Sopenharmony_ci cpu_relax(); 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic inline void phy_off(void) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci /* powerdown the on-chip PHY, its PLL, and the OTG block */ 698c2ecf20Sopenharmony_ci phy_ctrl &= ~(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON); 708c2ecf20Sopenharmony_ci phy_ctrl |= USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN; 718c2ecf20Sopenharmony_ci __raw_writel(phy_ctrl, USB_PHY_CTRL); 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic int dma_off = 1; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic void davinci_musb_enable(struct musb *musb) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci u32 tmp, old, val; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci /* workaround: setup irqs through both register sets */ 818c2ecf20Sopenharmony_ci tmp = (musb->epmask & DAVINCI_USB_TX_ENDPTS_MASK) 828c2ecf20Sopenharmony_ci << DAVINCI_USB_TXINT_SHIFT; 838c2ecf20Sopenharmony_ci musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp); 848c2ecf20Sopenharmony_ci old = tmp; 858c2ecf20Sopenharmony_ci tmp = (musb->epmask & (0xfffe & DAVINCI_USB_RX_ENDPTS_MASK)) 868c2ecf20Sopenharmony_ci << DAVINCI_USB_RXINT_SHIFT; 878c2ecf20Sopenharmony_ci musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp); 888c2ecf20Sopenharmony_ci tmp |= old; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci val = ~MUSB_INTR_SOF; 918c2ecf20Sopenharmony_ci tmp |= ((val & 0x01ff) << DAVINCI_USB_USBINT_SHIFT); 928c2ecf20Sopenharmony_ci musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_SET_REG, tmp); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (is_dma_capable() && !dma_off) 958c2ecf20Sopenharmony_ci printk(KERN_WARNING "%s %s: dma not reactivated\n", 968c2ecf20Sopenharmony_ci __FILE__, __func__); 978c2ecf20Sopenharmony_ci else 988c2ecf20Sopenharmony_ci dma_off = 0; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* force a DRVVBUS irq so we can start polling for ID change */ 1018c2ecf20Sopenharmony_ci musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG, 1028c2ecf20Sopenharmony_ci DAVINCI_INTR_DRVVBUS << DAVINCI_USB_USBINT_SHIFT); 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci/* 1068c2ecf20Sopenharmony_ci * Disable the HDRC and flush interrupts 1078c2ecf20Sopenharmony_ci */ 1088c2ecf20Sopenharmony_cistatic void davinci_musb_disable(struct musb *musb) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci /* because we don't set CTRLR.UINT, "important" to: 1118c2ecf20Sopenharmony_ci * - not read/write INTRUSB/INTRUSBE 1128c2ecf20Sopenharmony_ci * - (except during initial setup, as workaround) 1138c2ecf20Sopenharmony_ci * - use INTSETR/INTCLRR instead 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci musb_writel(musb->ctrl_base, DAVINCI_USB_INT_MASK_CLR_REG, 1168c2ecf20Sopenharmony_ci DAVINCI_USB_USBINT_MASK 1178c2ecf20Sopenharmony_ci | DAVINCI_USB_TXINT_MASK 1188c2ecf20Sopenharmony_ci | DAVINCI_USB_RXINT_MASK); 1198c2ecf20Sopenharmony_ci musb_writel(musb->ctrl_base, DAVINCI_USB_EOI_REG, 0); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (is_dma_capable() && !dma_off) 1228c2ecf20Sopenharmony_ci WARNING("dma still active\n"); 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci#define portstate(stmt) stmt 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci/* 1298c2ecf20Sopenharmony_ci * VBUS SWITCHING IS BOARD-SPECIFIC ... at least for the DM6446 EVM, 1308c2ecf20Sopenharmony_ci * which doesn't wire DRVVBUS to the FET that switches it. Unclear 1318c2ecf20Sopenharmony_ci * if that's a problem with the DM6446 chip or just with that board. 1328c2ecf20Sopenharmony_ci * 1338c2ecf20Sopenharmony_ci * In either case, the DM355 EVM automates DRVVBUS the normal way, 1348c2ecf20Sopenharmony_ci * when J10 is out, and TI documents it as handling OTG. 1358c2ecf20Sopenharmony_ci */ 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/* I2C operations are always synchronous, and require a task context. 1388c2ecf20Sopenharmony_ci * With unloaded systems, using the shared workqueue seems to suffice 1398c2ecf20Sopenharmony_ci * to satisfy the 100msec A_WAIT_VRISE timeout... 1408c2ecf20Sopenharmony_ci */ 1418c2ecf20Sopenharmony_cistatic void evm_deferred_drvvbus(struct work_struct *work) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci struct davinci_glue *glue = container_of(work, struct davinci_glue, 1448c2ecf20Sopenharmony_ci vbus_work); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci gpiod_set_value_cansleep(glue->vbus, glue->vbus_state); 1478c2ecf20Sopenharmony_ci glue->vbus_state = !glue->vbus_state; 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistatic void davinci_musb_source_power(struct musb *musb, int is_on, 1518c2ecf20Sopenharmony_ci int immediate) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci struct davinci_glue *glue = dev_get_drvdata(musb->controller->parent); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci /* This GPIO handling is entirely optional */ 1568c2ecf20Sopenharmony_ci if (!glue->vbus) 1578c2ecf20Sopenharmony_ci return; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci if (is_on) 1608c2ecf20Sopenharmony_ci is_on = 1; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (glue->vbus_state == is_on) 1638c2ecf20Sopenharmony_ci return; 1648c2ecf20Sopenharmony_ci /* 0/1 vs "-1 == unknown/init" */ 1658c2ecf20Sopenharmony_ci glue->vbus_state = !is_on; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci if (machine_is_davinci_evm()) { 1688c2ecf20Sopenharmony_ci if (immediate) 1698c2ecf20Sopenharmony_ci gpiod_set_value_cansleep(glue->vbus, glue->vbus_state); 1708c2ecf20Sopenharmony_ci else 1718c2ecf20Sopenharmony_ci schedule_work(&glue->vbus_work); 1728c2ecf20Sopenharmony_ci } 1738c2ecf20Sopenharmony_ci if (immediate) 1748c2ecf20Sopenharmony_ci glue->vbus_state = is_on; 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic void davinci_musb_set_vbus(struct musb *musb, int is_on) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci WARN_ON(is_on && is_peripheral_active(musb)); 1808c2ecf20Sopenharmony_ci davinci_musb_source_power(musb, is_on, 0); 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci#define POLL_SECONDS 2 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic void otg_timer(struct timer_list *t) 1878c2ecf20Sopenharmony_ci{ 1888c2ecf20Sopenharmony_ci struct musb *musb = from_timer(musb, t, dev_timer); 1898c2ecf20Sopenharmony_ci void __iomem *mregs = musb->mregs; 1908c2ecf20Sopenharmony_ci u8 devctl; 1918c2ecf20Sopenharmony_ci unsigned long flags; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci /* We poll because DaVinci's won't expose several OTG-critical 1948c2ecf20Sopenharmony_ci * status change events (from the transceiver) otherwise. 1958c2ecf20Sopenharmony_ci */ 1968c2ecf20Sopenharmony_ci devctl = musb_readb(mregs, MUSB_DEVCTL); 1978c2ecf20Sopenharmony_ci dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl, 1988c2ecf20Sopenharmony_ci usb_otg_state_string(musb->xceiv->otg->state)); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci spin_lock_irqsave(&musb->lock, flags); 2018c2ecf20Sopenharmony_ci switch (musb->xceiv->otg->state) { 2028c2ecf20Sopenharmony_ci case OTG_STATE_A_WAIT_VFALL: 2038c2ecf20Sopenharmony_ci /* Wait till VBUS falls below SessionEnd (~0.2V); the 1.3 RTL 2048c2ecf20Sopenharmony_ci * seems to mis-handle session "start" otherwise (or in our 2058c2ecf20Sopenharmony_ci * case "recover"), in routine "VBUS was valid by the time 2068c2ecf20Sopenharmony_ci * VBUSERR got reported during enumeration" cases. 2078c2ecf20Sopenharmony_ci */ 2088c2ecf20Sopenharmony_ci if (devctl & MUSB_DEVCTL_VBUS) { 2098c2ecf20Sopenharmony_ci mod_timer(&musb->dev_timer, jiffies + POLL_SECONDS * HZ); 2108c2ecf20Sopenharmony_ci break; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; 2138c2ecf20Sopenharmony_ci musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG, 2148c2ecf20Sopenharmony_ci MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT); 2158c2ecf20Sopenharmony_ci break; 2168c2ecf20Sopenharmony_ci case OTG_STATE_B_IDLE: 2178c2ecf20Sopenharmony_ci /* 2188c2ecf20Sopenharmony_ci * There's no ID-changed IRQ, so we have no good way to tell 2198c2ecf20Sopenharmony_ci * when to switch to the A-Default state machine (by setting 2208c2ecf20Sopenharmony_ci * the DEVCTL.SESSION flag). 2218c2ecf20Sopenharmony_ci * 2228c2ecf20Sopenharmony_ci * Workaround: whenever we're in B_IDLE, try setting the 2238c2ecf20Sopenharmony_ci * session flag every few seconds. If it works, ID was 2248c2ecf20Sopenharmony_ci * grounded and we're now in the A-Default state machine. 2258c2ecf20Sopenharmony_ci * 2268c2ecf20Sopenharmony_ci * NOTE setting the session flag is _supposed_ to trigger 2278c2ecf20Sopenharmony_ci * SRP, but clearly it doesn't. 2288c2ecf20Sopenharmony_ci */ 2298c2ecf20Sopenharmony_ci musb_writeb(mregs, MUSB_DEVCTL, 2308c2ecf20Sopenharmony_ci devctl | MUSB_DEVCTL_SESSION); 2318c2ecf20Sopenharmony_ci devctl = musb_readb(mregs, MUSB_DEVCTL); 2328c2ecf20Sopenharmony_ci if (devctl & MUSB_DEVCTL_BDEVICE) 2338c2ecf20Sopenharmony_ci mod_timer(&musb->dev_timer, jiffies + POLL_SECONDS * HZ); 2348c2ecf20Sopenharmony_ci else 2358c2ecf20Sopenharmony_ci musb->xceiv->otg->state = OTG_STATE_A_IDLE; 2368c2ecf20Sopenharmony_ci break; 2378c2ecf20Sopenharmony_ci default: 2388c2ecf20Sopenharmony_ci break; 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&musb->lock, flags); 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic irqreturn_t davinci_musb_interrupt(int irq, void *__hci) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci unsigned long flags; 2468c2ecf20Sopenharmony_ci irqreturn_t retval = IRQ_NONE; 2478c2ecf20Sopenharmony_ci struct musb *musb = __hci; 2488c2ecf20Sopenharmony_ci struct usb_otg *otg = musb->xceiv->otg; 2498c2ecf20Sopenharmony_ci void __iomem *tibase = musb->ctrl_base; 2508c2ecf20Sopenharmony_ci struct cppi *cppi; 2518c2ecf20Sopenharmony_ci u32 tmp; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci spin_lock_irqsave(&musb->lock, flags); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* NOTE: DaVinci shadows the Mentor IRQs. Don't manage them through 2568c2ecf20Sopenharmony_ci * the Mentor registers (except for setup), use the TI ones and EOI. 2578c2ecf20Sopenharmony_ci * 2588c2ecf20Sopenharmony_ci * Docs describe irq "vector" registers associated with the CPPI and 2598c2ecf20Sopenharmony_ci * USB EOI registers. These hold a bitmask corresponding to the 2608c2ecf20Sopenharmony_ci * current IRQ, not an irq handler address. Would using those bits 2618c2ecf20Sopenharmony_ci * resolve some of the races observed in this dispatch code?? 2628c2ecf20Sopenharmony_ci */ 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci /* CPPI interrupts share the same IRQ line, but have their own 2658c2ecf20Sopenharmony_ci * mask, state, "vector", and EOI registers. 2668c2ecf20Sopenharmony_ci */ 2678c2ecf20Sopenharmony_ci cppi = container_of(musb->dma_controller, struct cppi, controller); 2688c2ecf20Sopenharmony_ci if (is_cppi_enabled(musb) && musb->dma_controller && !cppi->irq) 2698c2ecf20Sopenharmony_ci retval = cppi_interrupt(irq, __hci); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /* ack and handle non-CPPI interrupts */ 2728c2ecf20Sopenharmony_ci tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG); 2738c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_USB_INT_SRC_CLR_REG, tmp); 2748c2ecf20Sopenharmony_ci dev_dbg(musb->controller, "IRQ %08x\n", tmp); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci musb->int_rx = (tmp & DAVINCI_USB_RXINT_MASK) 2778c2ecf20Sopenharmony_ci >> DAVINCI_USB_RXINT_SHIFT; 2788c2ecf20Sopenharmony_ci musb->int_tx = (tmp & DAVINCI_USB_TXINT_MASK) 2798c2ecf20Sopenharmony_ci >> DAVINCI_USB_TXINT_SHIFT; 2808c2ecf20Sopenharmony_ci musb->int_usb = (tmp & DAVINCI_USB_USBINT_MASK) 2818c2ecf20Sopenharmony_ci >> DAVINCI_USB_USBINT_SHIFT; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /* DRVVBUS irqs are the only proxy we have (a very poor one!) for 2848c2ecf20Sopenharmony_ci * DaVinci's missing ID change IRQ. We need an ID change IRQ to 2858c2ecf20Sopenharmony_ci * switch appropriately between halves of the OTG state machine. 2868c2ecf20Sopenharmony_ci * Managing DEVCTL.SESSION per Mentor docs requires we know its 2878c2ecf20Sopenharmony_ci * value, but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set. 2888c2ecf20Sopenharmony_ci * Also, DRVVBUS pulses for SRP (but not at 5V) ... 2898c2ecf20Sopenharmony_ci */ 2908c2ecf20Sopenharmony_ci if (tmp & (DAVINCI_INTR_DRVVBUS << DAVINCI_USB_USBINT_SHIFT)) { 2918c2ecf20Sopenharmony_ci int drvvbus = musb_readl(tibase, DAVINCI_USB_STAT_REG); 2928c2ecf20Sopenharmony_ci void __iomem *mregs = musb->mregs; 2938c2ecf20Sopenharmony_ci u8 devctl = musb_readb(mregs, MUSB_DEVCTL); 2948c2ecf20Sopenharmony_ci int err = musb->int_usb & MUSB_INTR_VBUSERROR; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci err = musb->int_usb & MUSB_INTR_VBUSERROR; 2978c2ecf20Sopenharmony_ci if (err) { 2988c2ecf20Sopenharmony_ci /* The Mentor core doesn't debounce VBUS as needed 2998c2ecf20Sopenharmony_ci * to cope with device connect current spikes. This 3008c2ecf20Sopenharmony_ci * means it's not uncommon for bus-powered devices 3018c2ecf20Sopenharmony_ci * to get VBUS errors during enumeration. 3028c2ecf20Sopenharmony_ci * 3038c2ecf20Sopenharmony_ci * This is a workaround, but newer RTL from Mentor 3048c2ecf20Sopenharmony_ci * seems to allow a better one: "re"starting sessions 3058c2ecf20Sopenharmony_ci * without waiting (on EVM, a **long** time) for VBUS 3068c2ecf20Sopenharmony_ci * to stop registering in devctl. 3078c2ecf20Sopenharmony_ci */ 3088c2ecf20Sopenharmony_ci musb->int_usb &= ~MUSB_INTR_VBUSERROR; 3098c2ecf20Sopenharmony_ci musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL; 3108c2ecf20Sopenharmony_ci mod_timer(&musb->dev_timer, jiffies + POLL_SECONDS * HZ); 3118c2ecf20Sopenharmony_ci WARNING("VBUS error workaround (delay coming)\n"); 3128c2ecf20Sopenharmony_ci } else if (drvvbus) { 3138c2ecf20Sopenharmony_ci MUSB_HST_MODE(musb); 3148c2ecf20Sopenharmony_ci musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; 3158c2ecf20Sopenharmony_ci portstate(musb->port1_status |= USB_PORT_STAT_POWER); 3168c2ecf20Sopenharmony_ci del_timer(&musb->dev_timer); 3178c2ecf20Sopenharmony_ci } else { 3188c2ecf20Sopenharmony_ci musb->is_active = 0; 3198c2ecf20Sopenharmony_ci MUSB_DEV_MODE(musb); 3208c2ecf20Sopenharmony_ci musb->xceiv->otg->state = OTG_STATE_B_IDLE; 3218c2ecf20Sopenharmony_ci portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci /* NOTE: this must complete poweron within 100 msec 3258c2ecf20Sopenharmony_ci * (OTG_TIME_A_WAIT_VRISE) but we don't check for that. 3268c2ecf20Sopenharmony_ci */ 3278c2ecf20Sopenharmony_ci davinci_musb_source_power(musb, drvvbus, 0); 3288c2ecf20Sopenharmony_ci dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n", 3298c2ecf20Sopenharmony_ci drvvbus ? "on" : "off", 3308c2ecf20Sopenharmony_ci usb_otg_state_string(musb->xceiv->otg->state), 3318c2ecf20Sopenharmony_ci err ? " ERROR" : "", 3328c2ecf20Sopenharmony_ci devctl); 3338c2ecf20Sopenharmony_ci retval = IRQ_HANDLED; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci if (musb->int_tx || musb->int_rx || musb->int_usb) 3378c2ecf20Sopenharmony_ci retval |= musb_interrupt(musb); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci /* irq stays asserted until EOI is written */ 3408c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_USB_EOI_REG, 0); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci /* poll for ID change */ 3438c2ecf20Sopenharmony_ci if (musb->xceiv->otg->state == OTG_STATE_B_IDLE) 3448c2ecf20Sopenharmony_ci mod_timer(&musb->dev_timer, jiffies + POLL_SECONDS * HZ); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&musb->lock, flags); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci return retval; 3498c2ecf20Sopenharmony_ci} 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_cistatic int davinci_musb_set_mode(struct musb *musb, u8 mode) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci /* EVM can't do this (right?) */ 3548c2ecf20Sopenharmony_ci return -EIO; 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_cistatic int davinci_musb_init(struct musb *musb) 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci void __iomem *tibase = musb->ctrl_base; 3608c2ecf20Sopenharmony_ci u32 revision; 3618c2ecf20Sopenharmony_ci int ret = -ENODEV; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); 3648c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(musb->xceiv)) { 3658c2ecf20Sopenharmony_ci ret = -EPROBE_DEFER; 3668c2ecf20Sopenharmony_ci goto unregister; 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci musb->mregs += DAVINCI_BASE_OFFSET; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci /* returns zero if e.g. not clocked */ 3728c2ecf20Sopenharmony_ci revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); 3738c2ecf20Sopenharmony_ci if (revision == 0) 3748c2ecf20Sopenharmony_ci goto fail; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci timer_setup(&musb->dev_timer, otg_timer, 0); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci davinci_musb_source_power(musb, 0, 1); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci /* dm355 EVM swaps D+/D- for signal integrity, and 3818c2ecf20Sopenharmony_ci * is clocked from the main 24 MHz crystal. 3828c2ecf20Sopenharmony_ci */ 3838c2ecf20Sopenharmony_ci if (machine_is_davinci_dm355_evm()) { 3848c2ecf20Sopenharmony_ci u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci phy_ctrl &= ~(3 << 9); 3878c2ecf20Sopenharmony_ci phy_ctrl |= USBPHY_DATAPOL; 3888c2ecf20Sopenharmony_ci __raw_writel(phy_ctrl, USB_PHY_CTRL); 3898c2ecf20Sopenharmony_ci } 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci /* On dm355, the default-A state machine needs DRVVBUS control. 3928c2ecf20Sopenharmony_ci * If we won't be a host, there's no need to turn it on. 3938c2ecf20Sopenharmony_ci */ 3948c2ecf20Sopenharmony_ci if (cpu_is_davinci_dm355()) { 3958c2ecf20Sopenharmony_ci u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci deepsleep &= ~DRVVBUS_FORCE; 3988c2ecf20Sopenharmony_ci __raw_writel(deepsleep, DM355_DEEPSLEEP); 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci /* reset the controller */ 4028c2ecf20Sopenharmony_ci musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci /* start the on-chip PHY and its PLL */ 4058c2ecf20Sopenharmony_ci phy_on(); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci msleep(5); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci /* NOTE: irqs are in mixed mode, not bypass to pure-musb */ 4108c2ecf20Sopenharmony_ci pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n", 4118c2ecf20Sopenharmony_ci revision, __raw_readl(USB_PHY_CTRL), 4128c2ecf20Sopenharmony_ci musb_readb(tibase, DAVINCI_USB_CTRL_REG)); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci musb->isr = davinci_musb_interrupt; 4158c2ecf20Sopenharmony_ci return 0; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_cifail: 4188c2ecf20Sopenharmony_ci usb_put_phy(musb->xceiv); 4198c2ecf20Sopenharmony_ciunregister: 4208c2ecf20Sopenharmony_ci usb_phy_generic_unregister(); 4218c2ecf20Sopenharmony_ci return ret; 4228c2ecf20Sopenharmony_ci} 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_cistatic int davinci_musb_exit(struct musb *musb) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci int maxdelay = 30; 4278c2ecf20Sopenharmony_ci u8 devctl, warn = 0; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci del_timer_sync(&musb->dev_timer); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci /* force VBUS off */ 4328c2ecf20Sopenharmony_ci if (cpu_is_davinci_dm355()) { 4338c2ecf20Sopenharmony_ci u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci deepsleep &= ~DRVVBUS_FORCE; 4368c2ecf20Sopenharmony_ci deepsleep |= DRVVBUS_OVERRIDE; 4378c2ecf20Sopenharmony_ci __raw_writel(deepsleep, DM355_DEEPSLEEP); 4388c2ecf20Sopenharmony_ci } 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci davinci_musb_source_power(musb, 0 /*off*/, 1); 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci /* 4438c2ecf20Sopenharmony_ci * delay, to avoid problems with module reload. 4448c2ecf20Sopenharmony_ci * if there's no peripheral connected, this can take a 4458c2ecf20Sopenharmony_ci * long time to fall, especially on EVM with huge C133. 4468c2ecf20Sopenharmony_ci */ 4478c2ecf20Sopenharmony_ci do { 4488c2ecf20Sopenharmony_ci devctl = musb_readb(musb->mregs, MUSB_DEVCTL); 4498c2ecf20Sopenharmony_ci if (!(devctl & MUSB_DEVCTL_VBUS)) 4508c2ecf20Sopenharmony_ci break; 4518c2ecf20Sopenharmony_ci if ((devctl & MUSB_DEVCTL_VBUS) != warn) { 4528c2ecf20Sopenharmony_ci warn = devctl & MUSB_DEVCTL_VBUS; 4538c2ecf20Sopenharmony_ci dev_dbg(musb->controller, "VBUS %d\n", 4548c2ecf20Sopenharmony_ci warn >> MUSB_DEVCTL_VBUS_SHIFT); 4558c2ecf20Sopenharmony_ci } 4568c2ecf20Sopenharmony_ci msleep(1000); 4578c2ecf20Sopenharmony_ci maxdelay--; 4588c2ecf20Sopenharmony_ci } while (maxdelay > 0); 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci /* in OTG mode, another host might be connected */ 4618c2ecf20Sopenharmony_ci if (devctl & MUSB_DEVCTL_VBUS) 4628c2ecf20Sopenharmony_ci dev_dbg(musb->controller, "VBUS off timeout (devctl %02x)\n", devctl); 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci phy_off(); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci usb_put_phy(musb->xceiv); 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci return 0; 4698c2ecf20Sopenharmony_ci} 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_cistatic const struct musb_platform_ops davinci_ops = { 4728c2ecf20Sopenharmony_ci .quirks = MUSB_DMA_CPPI, 4738c2ecf20Sopenharmony_ci .init = davinci_musb_init, 4748c2ecf20Sopenharmony_ci .exit = davinci_musb_exit, 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci#ifdef CONFIG_USB_TI_CPPI_DMA 4778c2ecf20Sopenharmony_ci .dma_init = cppi_dma_controller_create, 4788c2ecf20Sopenharmony_ci .dma_exit = cppi_dma_controller_destroy, 4798c2ecf20Sopenharmony_ci#endif 4808c2ecf20Sopenharmony_ci .enable = davinci_musb_enable, 4818c2ecf20Sopenharmony_ci .disable = davinci_musb_disable, 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci .set_mode = davinci_musb_set_mode, 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci .set_vbus = davinci_musb_set_vbus, 4868c2ecf20Sopenharmony_ci}; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_cistatic const struct platform_device_info davinci_dev_info = { 4898c2ecf20Sopenharmony_ci .name = "musb-hdrc", 4908c2ecf20Sopenharmony_ci .id = PLATFORM_DEVID_AUTO, 4918c2ecf20Sopenharmony_ci .dma_mask = DMA_BIT_MASK(32), 4928c2ecf20Sopenharmony_ci}; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_cistatic int davinci_probe(struct platform_device *pdev) 4958c2ecf20Sopenharmony_ci{ 4968c2ecf20Sopenharmony_ci struct resource musb_resources[3]; 4978c2ecf20Sopenharmony_ci struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); 4988c2ecf20Sopenharmony_ci struct platform_device *musb; 4998c2ecf20Sopenharmony_ci struct davinci_glue *glue; 5008c2ecf20Sopenharmony_ci struct platform_device_info pinfo; 5018c2ecf20Sopenharmony_ci struct clk *clk; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci int ret = -ENOMEM; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); 5068c2ecf20Sopenharmony_ci if (!glue) 5078c2ecf20Sopenharmony_ci goto err0; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci clk = devm_clk_get(&pdev->dev, "usb"); 5108c2ecf20Sopenharmony_ci if (IS_ERR(clk)) { 5118c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to get clock\n"); 5128c2ecf20Sopenharmony_ci ret = PTR_ERR(clk); 5138c2ecf20Sopenharmony_ci goto err0; 5148c2ecf20Sopenharmony_ci } 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci ret = clk_enable(clk); 5178c2ecf20Sopenharmony_ci if (ret) { 5188c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to enable clock\n"); 5198c2ecf20Sopenharmony_ci goto err0; 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci glue->dev = &pdev->dev; 5238c2ecf20Sopenharmony_ci glue->clk = clk; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci pdata->platform_ops = &davinci_ops; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci glue->vbus = devm_gpiod_get_optional(&pdev->dev, NULL, GPIOD_OUT_LOW); 5288c2ecf20Sopenharmony_ci if (IS_ERR(glue->vbus)) { 5298c2ecf20Sopenharmony_ci ret = PTR_ERR(glue->vbus); 5308c2ecf20Sopenharmony_ci goto err0; 5318c2ecf20Sopenharmony_ci } else { 5328c2ecf20Sopenharmony_ci glue->vbus_state = -1; 5338c2ecf20Sopenharmony_ci INIT_WORK(&glue->vbus_work, evm_deferred_drvvbus); 5348c2ecf20Sopenharmony_ci } 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci usb_phy_generic_register(); 5378c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, glue); 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci memset(musb_resources, 0x00, sizeof(*musb_resources) * 5408c2ecf20Sopenharmony_ci ARRAY_SIZE(musb_resources)); 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci musb_resources[0].name = pdev->resource[0].name; 5438c2ecf20Sopenharmony_ci musb_resources[0].start = pdev->resource[0].start; 5448c2ecf20Sopenharmony_ci musb_resources[0].end = pdev->resource[0].end; 5458c2ecf20Sopenharmony_ci musb_resources[0].flags = pdev->resource[0].flags; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci musb_resources[1].name = pdev->resource[1].name; 5488c2ecf20Sopenharmony_ci musb_resources[1].start = pdev->resource[1].start; 5498c2ecf20Sopenharmony_ci musb_resources[1].end = pdev->resource[1].end; 5508c2ecf20Sopenharmony_ci musb_resources[1].flags = pdev->resource[1].flags; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci /* 5538c2ecf20Sopenharmony_ci * For DM6467 3 resources are passed. A placeholder for the 3rd 5548c2ecf20Sopenharmony_ci * resource is always there, so it's safe to always copy it... 5558c2ecf20Sopenharmony_ci */ 5568c2ecf20Sopenharmony_ci musb_resources[2].name = pdev->resource[2].name; 5578c2ecf20Sopenharmony_ci musb_resources[2].start = pdev->resource[2].start; 5588c2ecf20Sopenharmony_ci musb_resources[2].end = pdev->resource[2].end; 5598c2ecf20Sopenharmony_ci musb_resources[2].flags = pdev->resource[2].flags; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci pinfo = davinci_dev_info; 5628c2ecf20Sopenharmony_ci pinfo.parent = &pdev->dev; 5638c2ecf20Sopenharmony_ci pinfo.res = musb_resources; 5648c2ecf20Sopenharmony_ci pinfo.num_res = ARRAY_SIZE(musb_resources); 5658c2ecf20Sopenharmony_ci pinfo.data = pdata; 5668c2ecf20Sopenharmony_ci pinfo.size_data = sizeof(*pdata); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci glue->musb = musb = platform_device_register_full(&pinfo); 5698c2ecf20Sopenharmony_ci if (IS_ERR(musb)) { 5708c2ecf20Sopenharmony_ci ret = PTR_ERR(musb); 5718c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to register musb device: %d\n", ret); 5728c2ecf20Sopenharmony_ci goto err1; 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci return 0; 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_cierr1: 5788c2ecf20Sopenharmony_ci clk_disable(clk); 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_cierr0: 5818c2ecf20Sopenharmony_ci return ret; 5828c2ecf20Sopenharmony_ci} 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_cistatic int davinci_remove(struct platform_device *pdev) 5858c2ecf20Sopenharmony_ci{ 5868c2ecf20Sopenharmony_ci struct davinci_glue *glue = platform_get_drvdata(pdev); 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci platform_device_unregister(glue->musb); 5898c2ecf20Sopenharmony_ci usb_phy_generic_unregister(); 5908c2ecf20Sopenharmony_ci clk_disable(glue->clk); 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci return 0; 5938c2ecf20Sopenharmony_ci} 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_cistatic struct platform_driver davinci_driver = { 5968c2ecf20Sopenharmony_ci .probe = davinci_probe, 5978c2ecf20Sopenharmony_ci .remove = davinci_remove, 5988c2ecf20Sopenharmony_ci .driver = { 5998c2ecf20Sopenharmony_ci .name = "musb-davinci", 6008c2ecf20Sopenharmony_ci }, 6018c2ecf20Sopenharmony_ci}; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("DaVinci MUSB Glue Layer"); 6048c2ecf20Sopenharmony_ciMODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 6058c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 6068c2ecf20Sopenharmony_cimodule_platform_driver(davinci_driver); 607