From f051557a74512c864a350fd3f835e2dd5e7558a1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 20 Jan 2013 11:04:47 +0100 Subject: [PATCH 1/5] ARM i.MX6 USB phy: Fix phy function names The imx6_usb_phy1* functions are misnamed. It's usb phy2 that is configured here, so rename the functions accordingly. Signed-off-by: Sascha Hauer --- arch/arm/boards/freescale-mx6-sabrelite/board.c | 4 ++-- arch/arm/mach-imx/include/mach/usb.h | 4 ++-- arch/arm/mach-imx/usb-imx6.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boards/freescale-mx6-sabrelite/board.c b/arch/arm/boards/freescale-mx6-sabrelite/board.c index 55087c2bc..2a1278635 100644 --- a/arch/arm/boards/freescale-mx6-sabrelite/board.c +++ b/arch/arm/boards/freescale-mx6-sabrelite/board.c @@ -231,8 +231,8 @@ static struct esdhc_platform_data sabrelite_sd4_data = { static void sabrelite_ehci_init(void) { - imx6_usb_phy1_disable_oc(); - imx6_usb_phy1_enable(); + imx6_usb_phy2_disable_oc(); + imx6_usb_phy2_enable(); /* hub reset */ gpio_direction_output(204, 0); diff --git a/arch/arm/mach-imx/include/mach/usb.h b/arch/arm/mach-imx/include/mach/usb.h index 0a88e7fe2..85528d77e 100644 --- a/arch/arm/mach-imx/include/mach/usb.h +++ b/arch/arm/mach-imx/include/mach/usb.h @@ -11,7 +11,7 @@ #define MX35_H1_USBTE_BIT (1 << 4) #define MXC_EHCI_INTERFACE_SINGLE_UNI (2 << 0) -int imx6_usb_phy1_disable_oc(void); -int imx6_usb_phy1_enable(void); +int imx6_usb_phy2_disable_oc(void); +int imx6_usb_phy2_enable(void); #endif /* __MACH_USB_H_*/ diff --git a/arch/arm/mach-imx/usb-imx6.c b/arch/arm/mach-imx/usb-imx6.c index cd234d208..a3c4304ad 100644 --- a/arch/arm/mach-imx/usb-imx6.c +++ b/arch/arm/mach-imx/usb-imx6.c @@ -46,7 +46,7 @@ #define USBPHY1_PLL_480_CTRL_EN_USB_CLK (1 << 6) #define USBPHY1_PLL_480_CTRL_BYPASS (1 << 16) -int imx6_usb_phy1_disable_oc(void) +int imx6_usb_phy2_disable_oc(void) { int val; @@ -64,7 +64,7 @@ int imx6_usb_phy1_disable_oc(void) return 0; } -int imx6_usb_phy1_enable(void) +int imx6_usb_phy2_enable(void) { int val; From 59a22cb39275917c8455ee54ce71aafd5ecaefe0 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 17 Jan 2013 14:31:00 +0100 Subject: [PATCH 2/5] ARM i.MX6: Fix usb phy base addresses What we had as usb phy1 base address is really usb phy2. Fix the names and add the missing base address definition for usb phy1. Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/include/mach/imx6-regs.h | 3 ++- arch/arm/mach-imx/usb-imx6.c | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-imx/include/mach/imx6-regs.h b/arch/arm/mach-imx/include/mach/imx6-regs.h index 7c72cba83..d947aa6c9 100644 --- a/arch/arm/mach-imx/include/mach/imx6-regs.h +++ b/arch/arm/mach-imx/include/mach/imx6-regs.h @@ -49,7 +49,8 @@ #define MX6_WDOG2_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x40000) #define MX6_CCM_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x44000) #define MX6_ANATOP_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x48000) -#define MX6_USBPHY1_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x4a000) +#define MX6_USBPHY1_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x49000) +#define MX6_USBPHY2_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x4a000) #define MX6_SNVS_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x4C000) #define MX6_EPIT1_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x50000) #define MX6_EPIT2_BASE_ADDR (MX6_AIPS1_OFF_BASE_ADDR + 0x54000) diff --git a/arch/arm/mach-imx/usb-imx6.c b/arch/arm/mach-imx/usb-imx6.c index a3c4304ad..5e3df10e4 100644 --- a/arch/arm/mach-imx/usb-imx6.c +++ b/arch/arm/mach-imx/usb-imx6.c @@ -94,18 +94,18 @@ int imx6_usb_phy2_enable(void) while (readl(MX6_USBOH3_USB_BASE_ADDR + USB_UH1_USBCMD) & USB_CMD_RESET); /* reset usbphy */ - writel(USBPHY_CTRL_SFTRST, MX6_USBPHY1_BASE_ADDR + USBPHY_CTRL + SET); + writel(USBPHY_CTRL_SFTRST, MX6_USBPHY2_BASE_ADDR + USBPHY_CTRL + SET); udelay(10); /* clr reset and clkgate */ - writel(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE, MX6_USBPHY1_BASE_ADDR + USBPHY_CTRL + CLR); + writel(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE, MX6_USBPHY2_BASE_ADDR + USBPHY_CTRL + CLR); /* clr all pwd bits => power up phy */ - writel(0xffffffff, MX6_USBPHY1_BASE_ADDR + CLR); + writel(0xffffffff, MX6_USBPHY2_BASE_ADDR + CLR); /* set utmilvl2/3 */ - val = readl(MX6_USBPHY1_BASE_ADDR + USBPHY_CTRL); + val = readl(MX6_USBPHY2_BASE_ADDR + USBPHY_CTRL); val |= USBPHY_CTRL_ENUTMILEVEL3 | USBPHY_CTRL_ENUTMILEVEL2; - writel(val, MX6_USBPHY1_BASE_ADDR + USBPHY_CTRL + SET); + writel(val, MX6_USBPHY2_BASE_ADDR + USBPHY_CTRL + SET); return 0; } From bb2e752fb64d13f7872a4e50c00d94246bb984d6 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 17 Jan 2013 16:13:11 +0100 Subject: [PATCH 3/5] ARM i.MX6: Add usbphy clocks Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/clk-imx6.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/mach-imx/clk-imx6.c b/arch/arm/mach-imx/clk-imx6.c index f78d3d2bc..f1b167aac 100644 --- a/arch/arm/mach-imx/clk-imx6.c +++ b/arch/arm/mach-imx/clk-imx6.c @@ -205,6 +205,9 @@ static int imx6_ccm_probe(struct device_d *dev) clks[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host","osc", base + 0x20, 0x3); clks[pll6_enet] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3); + clks[usbphy1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 6); + clks[usbphy2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 6); + clks[sata_ref] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5); clks[pcie_ref] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4); clks[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20); @@ -298,6 +301,8 @@ static int imx6_ccm_probe(struct device_d *dev) clkdev_add_physbase(clks[ipg_per], MX6_I2C2_BASE_ADDR, NULL); clkdev_add_physbase(clks[ipg_per], MX6_I2C3_BASE_ADDR, NULL); clkdev_add_physbase(clks[ahb], MX6_SATA_BASE_ADDR, NULL); + clkdev_add_physbase(clks[usbphy1], MX6_USBPHY1_BASE_ADDR, NULL); + clkdev_add_physbase(clks[usbphy2], MX6_USBPHY2_BASE_ADDR, NULL); writel(0xffffffff, ccm_base + CCGR0); writel(0xffffffff, ccm_base + CCGR1); From 75e71639e09d04ec00ef678eed5776f89ea22986 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 17 Jan 2013 16:21:48 +0100 Subject: [PATCH 4/5] USB: Add usb phy driver for i.MX This phy is found on i.MX6 and i.MX23/28. Currently tested only on i.MX6. For now we take the easy way out. The phy is enabled upon registration. More elaborated handling can be added later. Signed-off-by: Sascha Hauer --- drivers/usb/imx/Kconfig | 5 ++ drivers/usb/imx/Makefile | 1 + drivers/usb/imx/imx-usb-phy.c | 105 ++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 drivers/usb/imx/imx-usb-phy.c diff --git a/drivers/usb/imx/Kconfig b/drivers/usb/imx/Kconfig index 2c52e727d..b1ce682f1 100644 --- a/drivers/usb/imx/Kconfig +++ b/drivers/usb/imx/Kconfig @@ -13,3 +13,8 @@ config USB_IMX_CHIPIDEA This driver is recommended for new designs, but it needs board support to work. It's safe to say yes here. Also select EHCI support for USB host. + +config USB_IMX_PHY + bool + depends on ARCH_IMX + default y if ARCH_IMX6 diff --git a/drivers/usb/imx/Makefile b/drivers/usb/imx/Makefile index e37361c00..e15bc711a 100644 --- a/drivers/usb/imx/Makefile +++ b/drivers/usb/imx/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_USB_IMX_CHIPIDEA) += imx-usb-misc.o chipidea-imx.o +obj-$(CONFIG_USB_IMX_PHY) += imx-usb-phy.o diff --git a/drivers/usb/imx/imx-usb-phy.c b/drivers/usb/imx/imx-usb-phy.c new file mode 100644 index 000000000..ce9c93f42 --- /dev/null +++ b/drivers/usb/imx/imx-usb-phy.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2013 Sascha Hauer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define SET 0x4 +#define CLR 0x8 + +#define USBPHY_CTRL 0x30 + +#define USBPHY_CTRL_SFTRST (1 << 31) +#define USBPHY_CTRL_CLKGATE (1 << 30) +#define USBPHY_CTRL_ENUTMILEVEL3 (1 << 15) +#define USBPHY_CTRL_ENUTMILEVEL2 (1 << 14) + +struct imx_usbphy { + void __iomem *base; + struct clk *clk; +}; + +static int imx_usbphy_enable(struct imx_usbphy *imxphy) +{ + u32 val; + + clk_enable(imxphy->clk); + + /* reset usbphy */ + writel(USBPHY_CTRL_SFTRST, imxphy->base + USBPHY_CTRL + SET); + + udelay(10); + + /* clr reset and clkgate */ + writel(USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE, + imxphy->base + USBPHY_CTRL + CLR); + + /* clr all pwd bits => power up phy */ + writel(0xffffffff, imxphy->base + CLR); + + /* set utmilvl2/3 */ + val = readl(imxphy->base + USBPHY_CTRL); + val |= USBPHY_CTRL_ENUTMILEVEL3 | USBPHY_CTRL_ENUTMILEVEL2; + writel(val, imxphy->base + USBPHY_CTRL + SET); + + return 0; +} + +static int imx_usbphy_probe(struct device_d *dev) +{ + int ret; + struct imx_usbphy *imxphy; + + imxphy = xzalloc(sizeof(*imxphy)); + + imxphy->base = dev_request_mem_region(dev, 0); + if (!imxphy->base) { + ret = -ENODEV; + goto err_free; + } + + imxphy->clk = clk_get(dev, NULL); + if (IS_ERR(imxphy->clk)) { + dev_err(dev, "could not get clk: %s\n", strerror(-PTR_ERR(imxphy->clk))); + goto err_clk; + } + + imx_usbphy_enable(imxphy); + + dev_dbg(dev, "phy enabled\n"); + + return 0; + +err_clk: +err_free: + free(imxphy); + + return ret; +}; + +static struct driver_d imx_usbphy_driver = { + .name = "imx-usb-phy", + .probe = imx_usbphy_probe, +}; + +static int imx_usbphy_init(void) +{ + return platform_driver_register(&imx_usbphy_driver); +} +coredevice_initcall(imx_usbphy_init); From fdc5a0cbfcb32dc8978ae5a2470618b6bff20c55 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 17 Jan 2013 14:30:44 +0100 Subject: [PATCH 5/5] ARM i.MX6: Add Chipidea support This allows to register the USB ports for the chipidea driver. For now the otg/h1 register functions also register the corresponding USB phys. Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/imx6.c | 1 + arch/arm/mach-imx/include/mach/devices-imx6.h | 26 +++++++++++++++++++ drivers/usb/imx/imx-usb-misc.c | 12 +++++++++ 3 files changed, 39 insertions(+) diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c index 37ee5d848..b62f4128c 100644 --- a/arch/arm/mach-imx/imx6.c +++ b/arch/arm/mach-imx/imx6.c @@ -68,6 +68,7 @@ static int imx6_init(void) add_generic_device("imx31-gpio", 5, NULL, MX6_GPIO6_BASE_ADDR, 0x4000, IORESOURCE_MEM, NULL); add_generic_device("imx31-gpio", 6, NULL, MX6_GPIO7_BASE_ADDR, 0x4000, IORESOURCE_MEM, NULL); add_generic_device("imx21-wdt", 0, NULL, MX6_WDOG1_BASE_ADDR, 0x4000, IORESOURCE_MEM, NULL); + add_generic_device("imx6-usb-misc", 0, NULL, MX6_USBOH3_USB_BASE_ADDR + 0x800, 0x100, IORESOURCE_MEM, NULL); return 0; } diff --git a/arch/arm/mach-imx/include/mach/devices-imx6.h b/arch/arm/mach-imx/include/mach/devices-imx6.h index 0f1701653..a9c7e8dfe 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx6.h +++ b/arch/arm/mach-imx/include/mach/devices-imx6.h @@ -69,3 +69,29 @@ static inline struct device_d *imx6_add_sata(void) { return add_generic_device("imx6-sata", 0, NULL, MX6_SATA_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); } + +static inline struct device_d *imx6_add_usbotg(void *pdata) +{ + add_generic_device("imx-usb-phy", 0, NULL, MX6_USBPHY1_BASE_ADDR, 0x1000, + IORESOURCE_MEM, NULL); + + return imx_add_usb((void *)MX6_USBOH3_USB_BASE_ADDR, 0, pdata); +} + +static inline struct device_d *imx6_add_usbh1(void *pdata) +{ + add_generic_device("imx-usb-phy", 1, NULL, MX6_USBPHY2_BASE_ADDR, 0x1000, + IORESOURCE_MEM, NULL); + + return imx_add_usb((void *)MX6_USBOH3_USB_BASE_ADDR + 0x200, 1, pdata); +} + +static inline struct device_d *imx6_add_usbh2(void *pdata) +{ + return imx_add_usb((void *)MX6_USBOH3_USB_BASE_ADDR + 0x400, 2, pdata); +} + +static inline struct device_d *imx6_add_usbh3(void *pdata) +{ + return imx_add_usb((void *)MX6_USBOH3_USB_BASE_ADDR + 0x600, 2, pdata); +} diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c index 7c0ba5c5c..4cdf5ab3a 100644 --- a/drivers/usb/imx/imx-usb-misc.c +++ b/drivers/usb/imx/imx-usb-misc.c @@ -324,6 +324,12 @@ static __maybe_unused int mx5_initialize_usb_hw(void __iomem *base, int port, return 0; } +static __maybe_unused int mx6_initialize_usb_hw(void __iomem *base, int port, + unsigned int flags) +{ + return 0; +} + static struct platform_device_id imx_usbmisc_ids[] = { #ifdef CONFIG_ARCH_IMX25 { @@ -360,6 +366,12 @@ static struct platform_device_id imx_usbmisc_ids[] = { .name = "imx53-usb-misc", .driver_data = (unsigned long)&mx5_initialize_usb_hw, }, +#endif +#ifdef CONFIG_ARCH_IMX6 + { + .name = "imx6-usb-misc", + .driver_data = (unsigned long)&mx6_initialize_usb_hw, + }, #endif { /* sentinel */