static void ohci_omap3_tll_config(struct ohci_hcd_omap3 *omap) { u32 reg; int i; /* Program TLL SHARED CONF */ reg = ohci_omap_readl(omap->tll_base, OMAP_TLL_SHARED_CONF); reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN; reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN; reg |= OMAP_TLL_SHARED_CONF_USB_DIVRATION; reg |= OMAP_TLL_SHARED_CONF_FCLK_IS_ON; ohci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); /* Program each TLL channel */ /* * REVISIT: Only the 3-pin and 4-pin PHY modes have * actually been tested. */ for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { /* Enable only those channels that are actually used */ if (omap->port_mode[i] == OMAP_OHCI_PORT_MODE_UNUSED) continue; reg = ohci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); reg |= ohci_omap3_fslsmode(omap->port_mode[i]) << OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT; reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS; reg |= OMAP_TLL_CHANNEL_CONF_CHANEN; ohci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); } }
static void ohci_context_save(void) { int i; if (is_sil_rev_less_than(OMAP3430_REV_ES3_1)) { ohci_context.usbtll_sysconfig = omap_readl(OMAP_USBTLL_SYSCONFIG); ohci_context.usbtll_irqenable = omap_readl(OMAP_USBTLL_IRQENABLE); ohci_context.tll_shared_conf = omap_readl(OMAP_TLL_SHARED_CONF); for (i = 0; i < 3; i++) { ohci_context.tll_channel_conf[i] = omap_readl(OMAP_TLL_CHANNEL_CONF(i)); ohci_context.ulpi_function_ctrl[i] = omap_readb(OMAP_TLL_ULPI_FUNCTION_CTRL(i)); ohci_context.ulpi_interface_ctrl[i] = omap_readb(OMAP_TLL_ULPI_INTERFACE_CTRL(i)); ohci_context.ulpi_otg_ctrl[i] = omap_readb(OMAP_TLL_ULPI_OTG_CTRL(i)); ohci_context.ulpi_usb_int_en_rise[i] = omap_readb(OMAP_TLL_ULPI_INT_EN_RISE(i)); ohci_context.ulpi_usb_int_en_fall[i] = omap_readb(OMAP_TLL_ULPI_INT_EN_FALL(i)); ohci_context.ulpi_usb_int_status[i] = omap_readb(OMAP_TLL_ULPI_INT_STATUS(i)); } } }
static void usbhs_omap_tll_init(struct device *dev, u8 tll_channel_count) { struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); struct usbhs_omap_platform_data *pdata = dev->platform_data; unsigned reg; int i; /* Program Common TLL register */ reg = usbhs_read(omap->tll_base, OMAP_TLL_SHARED_CONF); reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON | OMAP_TLL_SHARED_CONF_USB_DIVRATION); reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN; reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN; usbhs_write(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); /* Enable channels now */ for (i = 0; i < tll_channel_count; i++) { reg = usbhs_read(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); if (is_ohci_port(pdata->port_mode[i])) { reg |= ohci_omap3_fslsmode(pdata->port_mode[i]) << OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT; reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS; } else if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_TLL) { /* Disable AutoIdle, BitStuffing and use SDR Mode */ reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); reg |= (1 << (i + 1)); } else continue; reg |= OMAP_TLL_CHANNEL_CONF_CHANEN; usbhs_write(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); usbhs_writeb(omap->tll_base, OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe); } }
static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask, u8 tll_channel_count) { unsigned reg; int i; /* Program the 3 TLL channels upfront */ for (i = 0; i < tll_channel_count; i++) { reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); /* Disable AutoIdle, BitStuffing and use SDR Mode */ reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); } /* Program Common TLL register */ reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_SHARED_CONF); reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON | OMAP_TLL_SHARED_CONF_USB_DIVRATION | OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN); reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN; ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); /* Enable channels now */ for (i = 0; i < tll_channel_count; i++) { reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); /* Enable only the reg that is needed */ if (!(tll_channel_mask & 1<<i)) continue; reg |= OMAP_TLL_CHANNEL_CONF_CHANEN; ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); ehci_omap_writeb(omap->tll_base, OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe); dev_dbg(omap->dev, "ULPI_SCRATCH_REG[ch=%d]= 0x%02x\n", i+1, ehci_omap_readb(omap->tll_base, OMAP_TLL_ULPI_SCRATCH_REGISTER(i))); } }
static void ohci_context_restore(void) { int i; if (is_sil_rev_less_than(OMAP3430_REV_ES3_1)) { #if 0 /* FIXME: This was reported as not working. Temporarily * disable this infinite loop pending investigation */ /* perform TLL soft reset, and wait until reset is complete */ omap_writel(1 << OMAP_USBTLL_SYSCONFIG_SOFTRESET_SHIFT, OMAP_USBTLL_SYSCONFIG); /* Wait for TLL reset to complete */ while (!(omap_readl(OMAP_USBTLL_SYSSTATUS) & (1 << OMAP_USBTLL_SYSSTATUS_RESETDONE_SHIFT))); #endif omap_writel(ohci_context.usbtll_sysconfig, OMAP_USBTLL_SYSCONFIG); omap_writel(ohci_context.tll_shared_conf, OMAP_TLL_SHARED_CONF); for (i = 0; i < 3; i++) { omap_writel(ohci_context.tll_channel_conf[i], OMAP_TLL_CHANNEL_CONF(i)); omap_writeb(ohci_context.ulpi_interface_ctrl[i], OMAP_TLL_ULPI_INTERFACE_CTRL(i)); omap_writeb(ohci_context.ulpi_function_ctrl[i], OMAP_TLL_ULPI_FUNCTION_CTRL(i)); omap_writeb(ohci_context.ulpi_otg_ctrl[i], OMAP_TLL_ULPI_OTG_CTRL(i)); omap_writeb(ohci_context.ulpi_usb_int_en_rise[i], OMAP_TLL_ULPI_INT_EN_RISE(i)); omap_writeb(ohci_context.ulpi_usb_int_en_fall[i], OMAP_TLL_ULPI_INT_EN_FALL(i)); omap_writeb(ohci_context.ulpi_usb_int_status[i], OMAP_TLL_ULPI_INT_STATUS(i)); } omap_writel(ohci_context.usbtll_irqenable, OMAP_USBTLL_IRQENABLE); } }
static void omap_usb_utmi_init(struct ehci_hcd_omap *omap) { unsigned reg; int i; /* Program the 3 TLL channels upfront */ for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); dev_dbg(&omap->dev->dev, "port %d: OMAP_TTL_CHANNEL_CONF_%d=%08x\n", i, i+1, ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i))); if (omap->port_data[i].flags & EHCI_HCD_OMAP_FLAG_NOBITSTUFF) reg |= OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF; else reg &= ~OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF; if (omap_usb_port_utmi_chanel_config(omap->port_data[i].mode)) { if (omap->port_data[i].flags & EHCI_HCD_OMAP_FLAG_AUTOIDLE) reg |= OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE; else reg &= ~OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE; } else { if (omap->port_data[i].flags & EHCI_HCD_OMAP_FLAG_AUTOIDLE) reg |= OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE; else reg &= ~OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE; } if (omap->port_data[i].mode == EHCI_HCD_OMAP_MODE_ULPI_TLL_DDR) reg |= OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE; else reg &= ~OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE; ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); } /* Program Common TLL register */ ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, OMAP_TLL_SHARED_CONF_FCLK_IS_ON | OMAP_TLL_SHARED_CONF_USB_DIVRATION); /* Enable channels now */ for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { /* Enable only the reg that is needed */ if (!(omap->port_data[i].flags & EHCI_HCD_OMAP_FLAG_ENABLED)) continue; reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); reg |= OMAP_TLL_CHANNEL_CONF_CHANEN; if (omap_usb_port_utmi_chanel_config(omap->port_data[i].mode)) reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE(1); else reg &= ~OMAP_TLL_CHANNEL_CONF_CHANMODE(3); reg &= ~(OMAP_TLL_CHANNEL_CONF_FSLSMODE(0xf)); reg |= OMAP_TLL_CHANNEL_CONF_FSLSMODE( omap_usb_port_fslsmode(omap->port_data[i].mode)); ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); dev_dbg(&omap->dev->dev, "port %d enabled: OMAP_TTL_CHANNEL_CONF_%d=%08x:%08x\n", i, i+1, reg, ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i))); ehci_omap_writeb(omap->tll_base, OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe); dev_dbg(&omap->dev->dev, "ULPI_SCRATCH_REG[ch=%d]= 0x%02x\n", i+1, ehci_omap_readb(omap->tll_base, OMAP_TLL_ULPI_SCRATCH_REGISTER(i))); } }
/** * usb_hcd_omap_probe - initialize OMAP-based HCDs * Context: !in_interrupt() * * Allocates basic resources for this USB host controller, and * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. */ static int usb_hcd_omap_probe(const struct hc_driver *driver, struct platform_device *pdev) { int retval; int i; u32 uhh_hostconfig_value; u8 ohci_port_enable_mask = 0; struct usb_hcd *hcd = 0; struct ohci_hcd *ohci; struct ohci_omap_clock_defs *ohci_clocks; if (pdev->num_resources != 2) { printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", pdev->num_resources); return -ENODEV; } if (pdev->resource[0].flags != IORESOURCE_MEM || pdev->resource[1].flags != IORESOURCE_IRQ) { printk(KERN_ERR "hcd probe: invalid resource type\n"); return -ENODEV; } hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id); if (!hcd) { retval = -ENOMEM; goto err0; } ohci_clocks = (struct ohci_omap_clock_defs *) (((char *)hcd_to_ohci(hcd)) + sizeof(struct ohci_hcd)); /* Enable Clocks for USBHOST */ ohci_clocks->usbhost_ick_clk = clk_get(&pdev->dev, USBHOST_ICLK); if (IS_ERR(ohci_clocks->usbhost_ick_clk)) return PTR_ERR(ohci_clocks->usbhost_ick_clk); clk_enable(ohci_clocks->usbhost_ick_clk); ohci_clocks->usbhost2_120m_fck_clk = clk_get(&pdev->dev, USBHOST_120M_FCLK); if (IS_ERR(ohci_clocks->usbhost2_120m_fck_clk)) { clk_disable(ohci_clocks->usbhost_ick_clk); clk_put(ohci_clocks->usbhost_ick_clk); return PTR_ERR(ohci_clocks->usbhost2_120m_fck_clk); } clk_enable(ohci_clocks->usbhost2_120m_fck_clk); ohci_clocks->usbhost1_48m_fck_clk = clk_get(&pdev->dev, USBHOST_48M_FCLK); if (IS_ERR(ohci_clocks->usbhost1_48m_fck_clk)) { clk_disable(ohci_clocks->usbhost_ick_clk); clk_put(ohci_clocks->usbhost_ick_clk); clk_disable(ohci_clocks->usbhost2_120m_fck_clk); clk_put(ohci_clocks->usbhost2_120m_fck_clk); return PTR_ERR(ohci_clocks->usbhost1_48m_fck_clk); } clk_enable(ohci_clocks->usbhost1_48m_fck_clk); /* Configure TLL for 60Mhz clk for ULPI */ ohci_clocks->usbtll_fck_clk = clk_get(&pdev->dev, USBHOST_TLL_FCLK); if (IS_ERR(ohci_clocks->usbtll_fck_clk)) { clk_disable(ohci_clocks->usbhost_ick_clk); clk_put(ohci_clocks->usbhost_ick_clk); clk_disable(ohci_clocks->usbhost2_120m_fck_clk); clk_put(ohci_clocks->usbhost2_120m_fck_clk); clk_disable(ohci_clocks->usbhost1_48m_fck_clk); clk_put(ohci_clocks->usbhost1_48m_fck_clk); return PTR_ERR(ohci_clocks->usbtll_fck_clk); } clk_enable(ohci_clocks->usbtll_fck_clk); ohci_clocks->usbtll_ick_clk = clk_get(&pdev->dev, USBHOST_TLL_ICLK); if (IS_ERR(ohci_clocks->usbtll_ick_clk)) { clk_disable(ohci_clocks->usbhost_ick_clk); clk_put(ohci_clocks->usbhost_ick_clk); clk_disable(ohci_clocks->usbhost2_120m_fck_clk); clk_put(ohci_clocks->usbhost2_120m_fck_clk); clk_disable(ohci_clocks->usbhost1_48m_fck_clk); clk_put(ohci_clocks->usbhost1_48m_fck_clk); clk_disable(ohci_clocks->usbtll_fck_clk); clk_put(ohci_clocks->usbtll_fck_clk); return PTR_ERR(ohci_clocks->usbtll_ick_clk); } clk_enable(ohci_clocks->usbtll_ick_clk); ohci_clocks->suspended = 0; /* Disable Auto Idle of USBTLL */ cm_write_mod_reg((0 << OMAP3430ES2_AUTO_USBTLL_SHIFT), CORE_MOD, CM_AUTOIDLE3); /* Wait for TLL to be Active */ while ((cm_read_mod_reg(CORE_MOD, OMAP2430_CM_IDLEST3) & (1 << OMAP3430ES2_ST_USBTLL_SHIFT))); /* perform TLL soft reset, and wait until reset is complete */ omap_writel(1 << OMAP_USBTLL_SYSCONFIG_SOFTRESET_SHIFT, OMAP_USBTLL_SYSCONFIG); /* Wait for TLL reset to complete */ while (!(omap_readl(OMAP_USBTLL_SYSSTATUS) & (1 << OMAP_USBTLL_SYSSTATUS_RESETDONE_SHIFT))); /* smart idle mode */ omap_writel((1 << OMAP_USBTLL_SYSCONFIG_ENAWAKEUP_SHIFT) | (2 << OMAP_USBTLL_SYSCONFIG_SIDLEMODE_SHIFT) | (0 << OMAP_USBTLL_SYSCONFIG_CACTIVITY_SHIFT) | (1 << OMAP_USBTLL_SYSCONFIG_AUTOIDLE_SHIFT), OMAP_USBTLL_SYSCONFIG); /* Put UHH in SmartIdle/SmartStandby mode */ omap_writel((1 << OMAP_UHH_SYSCONFIG_AUTOIDLE_SHIFT) | (1 << OMAP_UHH_SYSCONFIG_ENAWAKEUP_SHIFT) | (2 << OMAP_UHH_SYSCONFIG_SIDLEMODE_SHIFT) | (0 << OMAP_UHH_SYSCONFIG_CACTIVITY_SHIFT) | (2 << OMAP_UHH_SYSCONFIG_MIDLEMODE_SHIFT), OMAP_UHH_SYSCONFIG); #ifdef CONFIG_OMAP_OHCI_PHY_MODE /* TLL in FS-PHY mode operation */ uhh_hostconfig_value = (1 << OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN_SHIFT) | (1 << OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN_SHIFT) | (1 << OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN_SHIFT) | (0 << OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN_SHIFT); if (is_sil_rev_greater_than(OMAP3430_REV_ES2_1)) { /* For ES 3, we have per-port control for the ULPI Bypass * The ULPI Bypass needs to be set to 0 only if the EHCI PHY Mode * is selected for that port. * Hence it is easier to make it conditional on EHCI_PHY_MODE * * ES 2 does not have per-port control. Hence it is not possible to have * EHCI in PHY Mode and OHCI both working at the same time * * FIXME: This common code should be moved elsewhere * */ #ifndef CONFIG_OMAP_EHCI_PHY_MODE_PORT1 uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P1_ULPI_BYPASS_SHIFT); #endif #ifndef CONFIG_OMAP_EHCI_PHY_MODE_PORT2 uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P2_ULPI_BYPASS_SHIFT); #endif #ifndef CONFIG_OMAP_EHCI_PHY_MODE_PORT3 uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P3_ULPI_BYPASS_SHIFT); #endif } else { uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P1_ULPI_BYPASS_SHIFT); } omap_writel(uhh_hostconfig_value, OMAP_UHH_HOSTCONFIG); #if 0 /* Ensure BYPASS bit is not set */ while (!(omap_readl(OMAP_UHH_HOSTCONFIG) & (1 << OMAP_UHH_HOSTCONFIG_P3_ULPI_BYPASS_SHIFT))); #endif pr_debug("Entered UTMI PHY MODE: success"); /* Program Common TLL register */ omap_writel((1 << OMAP_TLL_SHARED_CONF_FCLK_IS_ON_SHIFT) | (1 << OMAP_TLL_SHARED_CONF_USB_DIVRATION_SHIFT) | (0 << OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN_SHIFT) | (0 << OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN_SHFT), OMAP_TLL_SHARED_CONF); #if defined(CONFIG_OMAP_OHCI_PHY_MODE_3PIN_PORT1) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_4PIN_PORT1) ohci_port_enable_mask |= (1 << 0); #endif #if defined(CONFIG_OMAP_OHCI_PHY_MODE_3PIN_PORT2) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_4PIN_PORT2) ohci_port_enable_mask |= (1 << 1); #endif #if defined(CONFIG_OMAP_OHCI_PHY_MODE_3PIN_PORT3) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_4PIN_PORT3) ohci_port_enable_mask |= (1 << 2); #endif #ifdef CONFIG_OMAP_OHCI_PHY_MODE_3PIN /* Program the 3 TLL channels upfront */ for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { /* Enable only required ports */ if (!(ohci_port_enable_mask & (1 << i))) continue; /* Disable AutoIdle */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) & ~(1 << OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); /* Disable BitStuffing */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) | (1 << OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); /* SDR Mode */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) & ~(1 << OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); /* CHANMODE: UTMI-to-serial FS/LS mode */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) | (1 << OMAP_TLL_CHANNEL_CONF_CHANMODE_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); #if 0 /* Enable port 3 only. Not enabling ports 1 & 2 */ if (i != 2) continue; #endif #if defined(CONFIG_OMAP_OHCI_PHY_MODE_4PIN_PORT1) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_4PIN_PORT2) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_4PIN_PORT3) /* FSLSMODE: 4-pin bidirectional PHY */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) | (3 << OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); #endif #if defined(CONFIG_OMAP_OHCI_PHY_MODE_3PIN_PORT1) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_3PIN_PORT2) || \ defined(CONFIG_OMAP_OHCI_PHY_MODE_3PIN_PORT3) /* FSLSMODE: 3-pin bidirectional PHY */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) | (2 << OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); #endif omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) | (1<<OMAP_TLL_CHANNEL_CONF_CHANEN_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); } #else pr_debug("\nOnly 3-pin PHY mode is implemented"); #endif /* CONFIG_OMAP_OHCI_PHY_MODE_3PIN */ #else #error "FS-TLL Not implemented" #endif /* CONFIG_OMAP_OHCI_PHY_MODE */ hcd->rsrc_start = pdev->resource[0].start; hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; /* if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { dev_dbg(&pdev->dev, "request_mem_region failed\n"); retval = -EBUSY; goto err1; } */ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_err(&pdev->dev, "can't ioremap OHCI HCD\n"); retval = -ENOMEM; goto err2; } /* pr_debug("\n\n-->VIRT-OHCI-BASE [0x%x], [0x%x] irq[%d]\n\n", hcd->regs, (unsigned int)io_p2v( 0x48064400 ), pdev->resource[1].start); */ ohci = hcd_to_ohci(hcd); ohci_hcd_init(ohci); ohci_clocks->host_enabled = 1; //irq = platform_get_irq(pdev, 0); //if (irq < 0) { // retval = -ENXIO; // goto err3; //} retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_DISABLED); if (retval) goto err3; return 0; err3: iounmap(hcd->regs); err2: // release_mem_region(hcd->rsrc_start, hcd->rsrc_len); //err1: usb_put_hcd(hcd); clk_disable(ohci_clocks->usbhost_ick_clk); clk_put(ohci_clocks->usbhost_ick_clk); clk_disable(ohci_clocks->usbhost2_120m_fck_clk); clk_put(ohci_clocks->usbhost2_120m_fck_clk); clk_disable(ohci_clocks->usbhost1_48m_fck_clk); clk_put(ohci_clocks->usbhost1_48m_fck_clk); clk_disable(ohci_clocks->usbtll_fck_clk); clk_put(ohci_clocks->usbtll_fck_clk); clk_disable(ohci_clocks->usbtll_ick_clk); clk_put(ohci_clocks->usbtll_ick_clk); err0: // clk_put(usb_dc_ck); // clk_put(usb_host_ck); return retval; }
static void omap_usb_utmi_init(struct usb_hcd *hcd, u8 tll_channel_mask) { int i; /* Use UTMI Ports of TLL */ omap_writel((1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)| (1<<OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN_SHIFT)| (1<<OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN_SHIFT)| (1<<OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN_SHIFT)| (0<<OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN_SHIFT), OMAP_UHH_HOSTCONFIG); /* Enusre bit is set */ while (!(omap_readl(OMAP_UHH_HOSTCONFIG) & (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT))) cpu_relax(); dev_dbg(hcd->self.controller, "\nEntered UTMI MODE: success\n"); /* Program the 3 TLL channels upfront */ for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { /* Disable AutoIdle */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) & ~(1<<OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); /* Disable BitStuffing */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) & ~(1<<OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); /* SDR Mode */ omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) & ~(1<<OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); } /* Program Common TLL register */ omap_writel((1 << OMAP_TLL_SHARED_CONF_FCLK_IS_ON_SHIFT) | (1 << OMAP_TLL_SHARED_CONF_USB_DIVRATION_SHIFT) | (0 << OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN_SHIFT) | (0 << OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN_SHFT), OMAP_TLL_SHARED_CONF); /* Enable channels now */ for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { /* Enable only the channel that is needed */ if (!(tll_channel_mask & 1<<i)) continue; omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) | (1<<OMAP_TLL_CHANNEL_CONF_CHANEN_SHIFT), OMAP_TLL_CHANNEL_CONF(i)); omap_writeb(0xBE, OMAP_TLL_ULPI_SCRATCH_REGISTER(i)); dev_dbg(hcd->self.controller, "\nULPI_SCRATCH_REG[ch=%d]" "= 0x%02x\n", i+1, omap_readb(OMAP_TLL_ULPI_SCRATCH_REGISTER(i))); } }
int omap_tll_init(struct usbhs_omap_platform_data *pdata) { int i; bool needs_tll; unsigned reg; struct usbtll_omap *tll; if (!tll_dev) return -ENODEV; pm_runtime_get_sync(tll_dev); spin_lock(&tll_lock); tll = dev_get_drvdata(tll_dev); needs_tll = false; for (i = 0; i < tll->nch; i++) needs_tll |= omap_usb_mode_needs_tll(pdata->port_mode[i]); if (needs_tll) { void __iomem *base = tll->base; /* Program Common TLL register */ reg = usbtll_read(base, OMAP_TLL_SHARED_CONF); reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON | OMAP_TLL_SHARED_CONF_USB_DIVRATION); reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN; reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN; usbtll_write(base, OMAP_TLL_SHARED_CONF, reg); /* Enable channels now */ for (i = 0; i < tll->nch; i++) { reg = usbtll_read(base, OMAP_TLL_CHANNEL_CONF(i)); if (is_ohci_port(pdata->port_mode[i])) { reg |= ohci_omap3_fslsmode(pdata->port_mode[i]) << OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT; reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS; } else if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_TLL) { /* * Disable AutoIdle, BitStuffing * and use SDR Mode */ reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); } else if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_HSIC) { /* * HSIC Mode requires UTMI port configurations */ reg |= OMAP_TLL_CHANNEL_CONF_DRVVBUS | OMAP_TLL_CHANNEL_CONF_CHRGVBUS | OMAP_TLL_CHANNEL_CONF_MODE_TRANSPARENT_UTMI | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF; } else { continue; } reg |= OMAP_TLL_CHANNEL_CONF_CHANEN; usbtll_write(base, OMAP_TLL_CHANNEL_CONF(i), reg); usbtll_writeb(base, OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe); } } spin_unlock(&tll_lock); pm_runtime_put_sync(tll_dev); return 0; }