1a94bb7a4SSanchayan Maity /* 2a94bb7a4SSanchayan Maity * Copyright (c) 2015 Sanchayan Maity <sanchayan.maity@toradex.com> 3a94bb7a4SSanchayan Maity * Copyright (C) 2015 Toradex AG 4a94bb7a4SSanchayan Maity * 5a94bb7a4SSanchayan Maity * Based on ehci-mx6 driver 6a94bb7a4SSanchayan Maity * 7a94bb7a4SSanchayan Maity * SPDX-License-Identifier: GPL-2.0+ 8a94bb7a4SSanchayan Maity */ 9a94bb7a4SSanchayan Maity 10a94bb7a4SSanchayan Maity #include <common.h> 11a94bb7a4SSanchayan Maity #include <usb.h> 12a94bb7a4SSanchayan Maity #include <errno.h> 13a94bb7a4SSanchayan Maity #include <linux/compiler.h> 14a94bb7a4SSanchayan Maity #include <asm/io.h> 15a94bb7a4SSanchayan Maity #include <asm/arch/clock.h> 16a94bb7a4SSanchayan Maity #include <asm/arch/imx-regs.h> 17a94bb7a4SSanchayan Maity #include <asm/arch/crm_regs.h> 18a94bb7a4SSanchayan Maity #include <asm/imx-common/iomux-v3.h> 19a94bb7a4SSanchayan Maity #include <asm/imx-common/regs-usbphy.h> 20a94bb7a4SSanchayan Maity #include <usb/ehci-fsl.h> 21a94bb7a4SSanchayan Maity 22a94bb7a4SSanchayan Maity #include "ehci.h" 23a94bb7a4SSanchayan Maity 24a94bb7a4SSanchayan Maity #define USB_NC_REG_OFFSET 0x00000800 25a94bb7a4SSanchayan Maity 26a94bb7a4SSanchayan Maity #define ANADIG_PLL_CTRL_EN_USB_CLKS (1 << 6) 27a94bb7a4SSanchayan Maity 28a94bb7a4SSanchayan Maity #define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */ 29a94bb7a4SSanchayan Maity #define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */ 30a94bb7a4SSanchayan Maity 31a94bb7a4SSanchayan Maity /* USBCMD */ 32a94bb7a4SSanchayan Maity #define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ 33a94bb7a4SSanchayan Maity #define UCMD_RESET (1 << 1) /* controller reset */ 34a94bb7a4SSanchayan Maity 35a94bb7a4SSanchayan Maity static const unsigned phy_bases[] = { 36a94bb7a4SSanchayan Maity USB_PHY0_BASE_ADDR, 37a94bb7a4SSanchayan Maity USB_PHY1_BASE_ADDR, 38a94bb7a4SSanchayan Maity }; 39a94bb7a4SSanchayan Maity 40a94bb7a4SSanchayan Maity static const unsigned nc_reg_bases[] = { 41a94bb7a4SSanchayan Maity USBC0_BASE_ADDR, 42a94bb7a4SSanchayan Maity USBC1_BASE_ADDR, 43a94bb7a4SSanchayan Maity }; 44a94bb7a4SSanchayan Maity 45a94bb7a4SSanchayan Maity static void usb_internal_phy_clock_gate(int index) 46a94bb7a4SSanchayan Maity { 47a94bb7a4SSanchayan Maity void __iomem *phy_reg; 48a94bb7a4SSanchayan Maity 49a94bb7a4SSanchayan Maity phy_reg = (void __iomem *)phy_bases[index]; 50a94bb7a4SSanchayan Maity clrbits_le32(phy_reg + USBPHY_CTRL, USBPHY_CTRL_CLKGATE); 51a94bb7a4SSanchayan Maity } 52a94bb7a4SSanchayan Maity 53a94bb7a4SSanchayan Maity static void usb_power_config(int index) 54a94bb7a4SSanchayan Maity { 55a94bb7a4SSanchayan Maity struct anadig_reg __iomem *anadig = 56a94bb7a4SSanchayan Maity (struct anadig_reg __iomem *)ANADIG_BASE_ADDR; 57a94bb7a4SSanchayan Maity void __iomem *pll_ctrl; 58a94bb7a4SSanchayan Maity 59a94bb7a4SSanchayan Maity switch (index) { 60a94bb7a4SSanchayan Maity case 0: 61a94bb7a4SSanchayan Maity pll_ctrl = &anadig->pll3_ctrl; 62a94bb7a4SSanchayan Maity clrbits_le32(pll_ctrl, ANADIG_PLL3_CTRL_BYPASS); 63a94bb7a4SSanchayan Maity setbits_le32(pll_ctrl, ANADIG_PLL3_CTRL_ENABLE 64a94bb7a4SSanchayan Maity | ANADIG_PLL3_CTRL_POWERDOWN 65a94bb7a4SSanchayan Maity | ANADIG_PLL_CTRL_EN_USB_CLKS); 66a94bb7a4SSanchayan Maity break; 67a94bb7a4SSanchayan Maity case 1: 68a94bb7a4SSanchayan Maity pll_ctrl = &anadig->pll7_ctrl; 69a94bb7a4SSanchayan Maity clrbits_le32(pll_ctrl, ANADIG_PLL7_CTRL_BYPASS); 70a94bb7a4SSanchayan Maity setbits_le32(pll_ctrl, ANADIG_PLL7_CTRL_ENABLE 71a94bb7a4SSanchayan Maity | ANADIG_PLL7_CTRL_POWERDOWN 72a94bb7a4SSanchayan Maity | ANADIG_PLL_CTRL_EN_USB_CLKS); 73a94bb7a4SSanchayan Maity break; 74a94bb7a4SSanchayan Maity default: 75a94bb7a4SSanchayan Maity return; 76a94bb7a4SSanchayan Maity } 77a94bb7a4SSanchayan Maity } 78a94bb7a4SSanchayan Maity 79a94bb7a4SSanchayan Maity static void usb_phy_enable(int index, struct usb_ehci *ehci) 80a94bb7a4SSanchayan Maity { 81a94bb7a4SSanchayan Maity void __iomem *phy_reg; 82a94bb7a4SSanchayan Maity void __iomem *phy_ctrl; 83a94bb7a4SSanchayan Maity void __iomem *usb_cmd; 84a94bb7a4SSanchayan Maity 85a94bb7a4SSanchayan Maity phy_reg = (void __iomem *)phy_bases[index]; 86a94bb7a4SSanchayan Maity phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); 87a94bb7a4SSanchayan Maity usb_cmd = (void __iomem *)&ehci->usbcmd; 88a94bb7a4SSanchayan Maity 89a94bb7a4SSanchayan Maity /* Stop then Reset */ 90a94bb7a4SSanchayan Maity clrbits_le32(usb_cmd, UCMD_RUN_STOP); 91a94bb7a4SSanchayan Maity while (readl(usb_cmd) & UCMD_RUN_STOP) 92a94bb7a4SSanchayan Maity ; 93a94bb7a4SSanchayan Maity 94a94bb7a4SSanchayan Maity setbits_le32(usb_cmd, UCMD_RESET); 95a94bb7a4SSanchayan Maity while (readl(usb_cmd) & UCMD_RESET) 96a94bb7a4SSanchayan Maity ; 97a94bb7a4SSanchayan Maity 98a94bb7a4SSanchayan Maity /* Reset USBPHY module */ 99a94bb7a4SSanchayan Maity setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST); 100a94bb7a4SSanchayan Maity udelay(10); 101a94bb7a4SSanchayan Maity 102a94bb7a4SSanchayan Maity /* Remove CLKGATE and SFTRST */ 103a94bb7a4SSanchayan Maity clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); 104a94bb7a4SSanchayan Maity udelay(10); 105a94bb7a4SSanchayan Maity 106a94bb7a4SSanchayan Maity /* Power up the PHY */ 107a94bb7a4SSanchayan Maity writel(0, phy_reg + USBPHY_PWD); 108a94bb7a4SSanchayan Maity 109a94bb7a4SSanchayan Maity /* Enable FS/LS device */ 110a94bb7a4SSanchayan Maity setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 | 111a94bb7a4SSanchayan Maity USBPHY_CTRL_ENUTMILEVEL3); 112a94bb7a4SSanchayan Maity } 113a94bb7a4SSanchayan Maity 114a94bb7a4SSanchayan Maity static void usb_oc_config(int index) 115a94bb7a4SSanchayan Maity { 116a94bb7a4SSanchayan Maity void __iomem *ctrl; 117a94bb7a4SSanchayan Maity 118a94bb7a4SSanchayan Maity ctrl = (void __iomem *)(nc_reg_bases[index] + USB_NC_REG_OFFSET); 119a94bb7a4SSanchayan Maity 120a94bb7a4SSanchayan Maity setbits_le32(ctrl, UCTRL_OVER_CUR_POL); 121a94bb7a4SSanchayan Maity setbits_le32(ctrl, UCTRL_OVER_CUR_DIS); 122a94bb7a4SSanchayan Maity } 123a94bb7a4SSanchayan Maity 124*60ed2864SSanchayan Maity int __weak board_ehci_hcd_init(int port) 125*60ed2864SSanchayan Maity { 126*60ed2864SSanchayan Maity return 0; 127*60ed2864SSanchayan Maity } 128*60ed2864SSanchayan Maity 129a94bb7a4SSanchayan Maity int ehci_hcd_init(int index, enum usb_init_type init, 130a94bb7a4SSanchayan Maity struct ehci_hccr **hccr, struct ehci_hcor **hcor) 131a94bb7a4SSanchayan Maity { 132a94bb7a4SSanchayan Maity struct usb_ehci *ehci; 133a94bb7a4SSanchayan Maity 134a94bb7a4SSanchayan Maity if (index >= ARRAY_SIZE(nc_reg_bases)) 135a94bb7a4SSanchayan Maity return -EINVAL; 136a94bb7a4SSanchayan Maity 137a94bb7a4SSanchayan Maity if (init == USB_INIT_DEVICE && index == 1) 138a94bb7a4SSanchayan Maity return -ENODEV; 139a94bb7a4SSanchayan Maity if (init == USB_INIT_HOST && index == 0) 140a94bb7a4SSanchayan Maity return -ENODEV; 141a94bb7a4SSanchayan Maity 142a94bb7a4SSanchayan Maity ehci = (struct usb_ehci *)nc_reg_bases[index]; 143a94bb7a4SSanchayan Maity 144*60ed2864SSanchayan Maity /* Do board specific initialisation */ 145*60ed2864SSanchayan Maity board_ehci_hcd_init(index); 146*60ed2864SSanchayan Maity 147a94bb7a4SSanchayan Maity usb_power_config(index); 148a94bb7a4SSanchayan Maity usb_oc_config(index); 149a94bb7a4SSanchayan Maity usb_internal_phy_clock_gate(index); 150a94bb7a4SSanchayan Maity usb_phy_enable(index, ehci); 151a94bb7a4SSanchayan Maity 152a94bb7a4SSanchayan Maity *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); 153a94bb7a4SSanchayan Maity *hcor = (struct ehci_hcor *)((uint32_t)*hccr + 154a94bb7a4SSanchayan Maity HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); 155a94bb7a4SSanchayan Maity 156a94bb7a4SSanchayan Maity if (init == USB_INIT_DEVICE) { 157a94bb7a4SSanchayan Maity setbits_le32(&ehci->usbmode, CM_DEVICE); 158a94bb7a4SSanchayan Maity writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc); 159a94bb7a4SSanchayan Maity setbits_le32(&ehci->portsc, USB_EN); 160a94bb7a4SSanchayan Maity } else if (init == USB_INIT_HOST) { 161a94bb7a4SSanchayan Maity setbits_le32(&ehci->usbmode, CM_HOST); 162a94bb7a4SSanchayan Maity writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc); 163a94bb7a4SSanchayan Maity setbits_le32(&ehci->portsc, USB_EN); 164a94bb7a4SSanchayan Maity } 165a94bb7a4SSanchayan Maity 166a94bb7a4SSanchayan Maity return 0; 167a94bb7a4SSanchayan Maity } 168a94bb7a4SSanchayan Maity 169a94bb7a4SSanchayan Maity int ehci_hcd_stop(int index) 170a94bb7a4SSanchayan Maity { 171a94bb7a4SSanchayan Maity return 0; 172a94bb7a4SSanchayan Maity } 173