[U-Boot] [PATCH 0/6] sunxi: usb: Turn the usbc code into a usb-phy driver

Hi,
This is a preparation series for moving the sunxi ehci code over to the driver model and for adding ohci support.
Regards,
Hans

The sunxi "usbc" code is mostly about phy setup, but currently also sets up the host controller clocks, which is something which really belongs in the host controller drivers, so move it there.
This is a preparation patch for moving the sunxi ehci code to the driver model and for adding ohci support.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- arch/arm/cpu/armv7/sunxi/usbc.c | 14 +------------- drivers/usb/host/ehci-sunxi.c | 24 ++++++++++++++++++++++-- drivers/usb/musb-new/sunxi.c | 20 ++++++++++++++++++++ 3 files changed, 43 insertions(+), 15 deletions(-)
diff --git a/arch/arm/cpu/armv7/sunxi/usbc.c b/arch/arm/cpu/armv7/sunxi/usbc.c index 21032aa..6ae6dfa 100644 --- a/arch/arm/cpu/armv7/sunxi/usbc.c +++ b/arch/arm/cpu/armv7/sunxi/usbc.c @@ -11,12 +11,12 @@ * SPDX-License-Identifier: GPL-2.0+ */
+#include <common.h> #include <asm/arch/clock.h> #include <asm/arch/cpu.h> #include <asm/arch/usbc.h> #include <asm/gpio.h> #include <asm/io.h> -#include <common.h> #include <errno.h> #ifdef CONFIG_AXP152_POWER #include <axp152.h> @@ -44,25 +44,21 @@ static struct sunxi_usbc_hcd { struct usb_hcd *hcd; int usb_rst_mask; - int ahb_clk_mask; int gpio_vbus; int gpio_vbus_det; int id; } sunxi_usbc_hcd[] = { { .usb_rst_mask = CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK, - .ahb_clk_mask = 1 << AHB_GATE_OFFSET_USB0, .id = 0, }, { .usb_rst_mask = CCM_USB_CTRL_PHY1_RST | CCM_USB_CTRL_PHY1_CLK, - .ahb_clk_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0, .id = 1, }, #if (CONFIG_USB_MAX_CONTROLLER_COUNT > 1) { .usb_rst_mask = CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK, - .ahb_clk_mask = 1 << AHB_GATE_OFFSET_USB_EHCI1, .id = 2, } #endif @@ -227,10 +223,6 @@ void sunxi_usbc_enable(int index) setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
setbits_le32(&ccm->usb_clk_cfg, sunxi_usbc->usb_rst_mask); - setbits_le32(&ccm->ahb_gate0, sunxi_usbc->ahb_clk_mask); -#ifdef CONFIG_SUNXI_GEN_SUN6I - setbits_le32(&ccm->ahb_reset0_cfg, sunxi_usbc->ahb_clk_mask); -#endif
sunxi_usb_phy_init(sunxi_usbc);
@@ -248,10 +240,6 @@ void sunxi_usbc_disable(int index) if (sunxi_usbc->id != 0) sunxi_usb_passby(sunxi_usbc, !SUNXI_USB_PASSBY_EN);
-#ifdef CONFIG_SUNXI_GEN_SUN6I - clrbits_le32(&ccm->ahb_reset0_cfg, sunxi_usbc->ahb_clk_mask); -#endif - clrbits_le32(&ccm->ahb_gate0, sunxi_usbc->ahb_clk_mask); clrbits_le32(&ccm->usb_clk_cfg, sunxi_usbc->usb_rst_mask);
/* disable common PHY only once, for the last enabled hcd */ diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index eda9f69..41e4d7f 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -9,19 +9,29 @@ * SPDX-License-Identifier: GPL-2.0+ */
-#include <asm/arch/usbc.h> #include <common.h> +#include <asm/arch/clock.h> +#include <asm/arch/usbc.h> +#include <asm/io.h> #include "ehci.h"
int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { - int err; + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + int ahb_gate_offset, err;
err = sunxi_usbc_request_resources(index + 1); if (err) return err;
+ ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 : + AHB_GATE_OFFSET_USB_EHCI0; + setbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset); +#ifdef CONFIG_SUNXI_GEN_SUN6I + setbits_le32(&ccm->ahb_reset0_cfg, 1 << ahb_gate_offset); +#endif + sunxi_usbc_enable(index + 1); sunxi_usbc_vbus_enable(index + 1);
@@ -39,8 +49,18 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr,
int ehci_hcd_stop(int index) { + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + int ahb_gate_offset; + sunxi_usbc_vbus_disable(index + 1); sunxi_usbc_disable(index + 1);
+ ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 : + AHB_GATE_OFFSET_USB_EHCI0; +#ifdef CONFIG_SUNXI_GEN_SUN6I + clrbits_le32(&ccm->ahb_reset0_cfg, 1 << ahb_gate_offset); +#endif + clrbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset); + return sunxi_usbc_free_resources(index + 1); } diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index c9a6a16..e3c6d6a 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -22,6 +22,7 @@ */ #include <common.h> #include <asm/arch/cpu.h> +#include <asm/arch/clock.h> #include <asm/arch/gpio.h> #include <asm/arch/usbc.h> #include <asm-generic/gpio.h> @@ -219,11 +220,24 @@ static void sunxi_musb_enable(struct musb *musb)
static void sunxi_musb_disable(struct musb *musb) { + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + pr_debug("%s():\n", __func__);
/* Put the controller back in a pristane state for "usb reset" */ if (musb->is_active) { sunxi_usbc_disable(0); +#ifdef CONFIG_SUNXI_GEN_SUN6I + clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); +#endif + clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); + + mdelay(10); + + setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); +#ifdef CONFIG_SUNXI_GEN_SUN6I + setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); +#endif sunxi_usbc_enable(0); musb->is_active = 0; } @@ -231,6 +245,7 @@ static void sunxi_musb_disable(struct musb *musb)
static int sunxi_musb_init(struct musb *musb) { + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; int err;
pr_debug("%s():\n", __func__); @@ -249,6 +264,11 @@ static int sunxi_musb_init(struct musb *musb) }
musb->isr = sunxi_musb_interrupt; + + setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); +#ifdef CONFIG_SUNXI_GEN_SUN6I + setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); +#endif sunxi_usbc_enable(0);
USBC_ConfigFIFO_Base();

On Tue, 2015-04-28 at 08:41 +0200, Hans de Goede wrote:
The sunxi "usbc" code is mostly about phy setup, but currently also sets up the host controller clocks, which is something which really belongs in the host controller drivers, so move it there.
This is a preparation patch for moving the sunxi ehci code to the driver model and for adding ohci support.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Ian Campbell ijc@hellion.org.uk

This is the only function left in sunxi/usbc.c which is not phy related, so remove it.
This is a preparation patch for turning the usbc.c code into a proper usb phy driver.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- arch/arm/cpu/armv7/sunxi/usbc.c | 30 ++++++++++-------------------- arch/arm/include/asm/arch-sunxi/usbc.h | 1 - drivers/usb/host/ehci-sunxi.c | 5 ++++- 3 files changed, 14 insertions(+), 22 deletions(-)
diff --git a/arch/arm/cpu/armv7/sunxi/usbc.c b/arch/arm/cpu/armv7/sunxi/usbc.c index 6ae6dfa..131e103 100644 --- a/arch/arm/cpu/armv7/sunxi/usbc.c +++ b/arch/arm/cpu/armv7/sunxi/usbc.c @@ -66,20 +66,6 @@ static struct sunxi_usbc_hcd {
static int enabled_hcd_count;
-void *sunxi_usbc_get_io_base(int index) -{ - switch (index) { - case 0: - return (void *)SUNXI_USB0_BASE; - case 1: - return (void *)SUNXI_USB1_BASE; - case 2: - return (void *)SUNXI_USB2_BASE; - default: - return NULL; - } -} - static int get_vbus_gpio(int index) { switch (index) { @@ -102,7 +88,7 @@ static void usb_phy_write(struct sunxi_usbc_hcd *sunxi_usbc, int addr, int data, int len) { int j = 0, usbc_bit = 0; - void *dest = sunxi_usbc_get_io_base(0) + SUNXI_USB_CSR; + void *dest = (void *)SUNXI_USB0_BASE + SUNXI_USB_CSR;
#ifdef CONFIG_MACH_SUN8I_A33 /* CSR needs to be explicitly initialized to 0 on A33 */ @@ -153,11 +139,15 @@ static void sunxi_usb_phy_init(struct sunxi_usbc_hcd *sunxi_usbc) return; }
-static void sunxi_usb_passby(struct sunxi_usbc_hcd *sunxi_usbc, int enable) +static void sunxi_usb_phy_passby(int index, int enable) { unsigned long bits = 0; - void *addr = sunxi_usbc_get_io_base(sunxi_usbc->id) + - SUNXI_USB_PMU_IRQ_ENABLE; + void *addr; + + if (index == 1) + addr = (void *)SUNXI_USB1_BASE + SUNXI_USB_PMU_IRQ_ENABLE; + else + addr = (void *)SUNXI_USB2_BASE + SUNXI_USB_PMU_IRQ_ENABLE;
bits = SUNXI_EHCI_AHB_ICHR8_EN | SUNXI_EHCI_AHB_INCR4_BURST_EN | @@ -227,7 +217,7 @@ void sunxi_usbc_enable(int index) sunxi_usb_phy_init(sunxi_usbc);
if (sunxi_usbc->id != 0) - sunxi_usb_passby(sunxi_usbc, SUNXI_USB_PASSBY_EN); + sunxi_usb_phy_passby(index, SUNXI_USB_PASSBY_EN);
enabled_hcd_count++; } @@ -238,7 +228,7 @@ void sunxi_usbc_disable(int index) struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
if (sunxi_usbc->id != 0) - sunxi_usb_passby(sunxi_usbc, !SUNXI_USB_PASSBY_EN); + sunxi_usb_phy_passby(index, !SUNXI_USB_PASSBY_EN);
clrbits_le32(&ccm->usb_clk_cfg, sunxi_usbc->usb_rst_mask);
diff --git a/arch/arm/include/asm/arch-sunxi/usbc.h b/arch/arm/include/asm/arch-sunxi/usbc.h index ab0f272..41721f9 100644 --- a/arch/arm/include/asm/arch-sunxi/usbc.h +++ b/arch/arm/include/asm/arch-sunxi/usbc.h @@ -13,7 +13,6 @@
extern const struct musb_platform_ops sunxi_musb_ops;
-void *sunxi_usbc_get_io_base(int index); int sunxi_usbc_request_resources(int index); int sunxi_usbc_free_resources(int index); void sunxi_usbc_enable(int index); diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index 41e4d7f..5de20f9 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -35,7 +35,10 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, sunxi_usbc_enable(index + 1); sunxi_usbc_vbus_enable(index + 1);
- *hccr = sunxi_usbc_get_io_base(index + 1); + if (index == 0) + *hccr = (void *)SUNXI_USB1_BASE; + else + *hccr = (void *)SUNXI_USB2_BASE;
*hcor = (struct ehci_hcor *)((uint32_t) *hccr + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));

On Tue, 2015-04-28 at 08:41 +0200, Hans de Goede wrote:
This is the only function left in sunxi/usbc.c which is not phy related, so remove it.
This is a preparation patch for turning the usbc.c code into a proper usb phy driver.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Ian Campbell ijc@hellion.org.uk

Rename the sunxi_usbc_foo functions to sunxi_usb_phy_bar to make it clear that these are usb-phy functions. Also change the verbs & nouns in the suffix to match the verbs & nouns used in the Linux kernels generic phy framework.
This patch purely renames things, it contains no functional changes.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- arch/arm/cpu/armv7/sunxi/usbc.c | 124 ++++++++++++++++----------------- arch/arm/include/asm/arch-sunxi/usbc.h | 25 +++---- board/sunxi/board.c | 2 + drivers/usb/host/ehci-sunxi.c | 17 ++--- drivers/usb/musb-new/musb_uboot.c | 4 +- drivers/usb/musb-new/sunxi.c | 20 +++--- 6 files changed, 95 insertions(+), 97 deletions(-)
diff --git a/arch/arm/cpu/armv7/sunxi/usbc.c b/arch/arm/cpu/armv7/sunxi/usbc.c index 131e103..71817c1 100644 --- a/arch/arm/cpu/armv7/sunxi/usbc.c +++ b/arch/arm/cpu/armv7/sunxi/usbc.c @@ -1,9 +1,8 @@ /* - * Sunxi usb-controller code shared between the ehci and musb controllers + * Sunxi usb-phy code * - * Copyright (C) 2014 Roman Byshko - * - * Roman Byshko rbyshko@gmail.com + * Copyright (C) 2015 Hans de Goede hdegoede@redhat.com + * Copyright (C) 2014 Roman Byshko rbyshko@gmail.com * * Based on code from * Allwinner Technology Co., Ltd. <www.allwinnertech.com> @@ -41,13 +40,12 @@ #define SUNXI_EHCI_AHB_INCRX_ALIGN_EN (1 << 8) #define SUNXI_EHCI_ULPI_BYPASS_EN (1 << 0)
-static struct sunxi_usbc_hcd { - struct usb_hcd *hcd; +static struct sunxi_usb_phy { int usb_rst_mask; int gpio_vbus; int gpio_vbus_det; int id; -} sunxi_usbc_hcd[] = { +} sunxi_usb_phy[] = { { .usb_rst_mask = CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK, .id = 0, @@ -64,7 +62,7 @@ static struct sunxi_usbc_hcd { #endif };
-static int enabled_hcd_count; +static int sunxi_usb_phy_enabled_count;
static int get_vbus_gpio(int index) { @@ -84,7 +82,7 @@ static int get_vbus_detect_gpio(int index) return -EINVAL; }
-static void usb_phy_write(struct sunxi_usbc_hcd *sunxi_usbc, int addr, +static void usb_phy_write(struct sunxi_usb_phy *phy, int addr, int data, int len) { int j = 0, usbc_bit = 0; @@ -95,7 +93,7 @@ static void usb_phy_write(struct sunxi_usbc_hcd *sunxi_usbc, int addr, writel(0, dest); #endif
- usbc_bit = 1 << (sunxi_usbc->id * 2); + usbc_bit = 1 << (phy->id * 2); for (j = 0; j < len; j++) { /* set the bit address to be written */ clrbits_le32(dest, 0xff << 8); @@ -116,24 +114,24 @@ static void usb_phy_write(struct sunxi_usbc_hcd *sunxi_usbc, int addr, } }
-static void sunxi_usb_phy_init(struct sunxi_usbc_hcd *sunxi_usbc) +static void sunxi_usb_phy_config(struct sunxi_usb_phy *phy) { /* The following comments are machine * translated from Chinese, you have been warned! */
/* Regulation 45 ohms */ - if (sunxi_usbc->id == 0) - usb_phy_write(sunxi_usbc, 0x0c, 0x01, 1); + if (phy->id == 0) + usb_phy_write(phy, 0x0c, 0x01, 1);
/* adjust PHY's magnitude and rate */ - usb_phy_write(sunxi_usbc, 0x20, 0x14, 5); + usb_phy_write(phy, 0x20, 0x14, 5);
/* threshold adjustment disconnect */ #if defined CONFIG_MACH_SUN4I || defined CONFIG_MACH_SUN6I - usb_phy_write(sunxi_usbc, 0x2a, 3, 2); + usb_phy_write(phy, 0x2a, 3, 2); #else - usb_phy_write(sunxi_usbc, 0x2a, 2, 2); + usb_phy_write(phy, 0x2a, 2, 2); #endif
return; @@ -162,110 +160,110 @@ static void sunxi_usb_phy_passby(int index, int enable) return; }
-void sunxi_usbc_enable_squelch_detect(int index, int enable) +void sunxi_usb_phy_enable_squelch_detect(int index, int enable) { - struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index]; + struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
- usb_phy_write(sunxi_usbc, 0x3c, enable ? 0 : 2, 2); + usb_phy_write(phy, 0x3c, enable ? 0 : 2, 2); }
-int sunxi_usbc_request_resources(int index) +int sunxi_usb_phy_probe(int index) { - struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index]; + struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; int ret = 0;
- sunxi_usbc->gpio_vbus = get_vbus_gpio(index); - if (sunxi_usbc->gpio_vbus >= 0) { - ret |= gpio_request(sunxi_usbc->gpio_vbus, "usbc_vbus"); - ret |= gpio_direction_output(sunxi_usbc->gpio_vbus, 0); + phy->gpio_vbus = get_vbus_gpio(index); + if (phy->gpio_vbus >= 0) { + ret |= gpio_request(phy->gpio_vbus, "usbc_vbus"); + ret |= gpio_direction_output(phy->gpio_vbus, 0); }
- sunxi_usbc->gpio_vbus_det = get_vbus_detect_gpio(index); - if (sunxi_usbc->gpio_vbus_det >= 0) { - ret |= gpio_request(sunxi_usbc->gpio_vbus_det, "usbc_vbus_det"); - ret |= gpio_direction_input(sunxi_usbc->gpio_vbus_det); + phy->gpio_vbus_det = get_vbus_detect_gpio(index); + if (phy->gpio_vbus_det >= 0) { + ret |= gpio_request(phy->gpio_vbus_det, "usbc_vbus_det"); + ret |= gpio_direction_input(phy->gpio_vbus_det); }
return ret; }
-int sunxi_usbc_free_resources(int index) +int sunxi_usb_phy_remove(int index) { - struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index]; + struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; int ret = 0;
- if (sunxi_usbc->gpio_vbus >= 0) - ret |= gpio_free(sunxi_usbc->gpio_vbus); + if (phy->gpio_vbus >= 0) + ret |= gpio_free(phy->gpio_vbus);
- if (sunxi_usbc->gpio_vbus_det >= 0) - ret |= gpio_free(sunxi_usbc->gpio_vbus_det); + if (phy->gpio_vbus_det >= 0) + ret |= gpio_free(phy->gpio_vbus_det);
return ret; }
-void sunxi_usbc_enable(int index) +void sunxi_usb_phy_init(int index) { - struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index]; + struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
/* enable common PHY only once */ - if (enabled_hcd_count == 0) + if (sunxi_usb_phy_enabled_count == 0) setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
- setbits_le32(&ccm->usb_clk_cfg, sunxi_usbc->usb_rst_mask); + setbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask);
- sunxi_usb_phy_init(sunxi_usbc); + sunxi_usb_phy_config(phy);
- if (sunxi_usbc->id != 0) + if (phy->id != 0) sunxi_usb_phy_passby(index, SUNXI_USB_PASSBY_EN);
- enabled_hcd_count++; + sunxi_usb_phy_enabled_count++; }
-void sunxi_usbc_disable(int index) +void sunxi_usb_phy_exit(int index) { - struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index]; + struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
- if (sunxi_usbc->id != 0) + if (phy->id != 0) sunxi_usb_phy_passby(index, !SUNXI_USB_PASSBY_EN);
- clrbits_le32(&ccm->usb_clk_cfg, sunxi_usbc->usb_rst_mask); + clrbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask);
- /* disable common PHY only once, for the last enabled hcd */ - if (enabled_hcd_count == 1) + /* disable common PHY only once, for the last enabled phy */ + if (sunxi_usb_phy_enabled_count == 1) clrbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE);
- enabled_hcd_count--; + sunxi_usb_phy_enabled_count--; }
-void sunxi_usbc_vbus_enable(int index) +void sunxi_usb_phy_power_on(int index) { - struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index]; + struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
- if (sunxi_usbc->gpio_vbus >= 0) - gpio_set_value(sunxi_usbc->gpio_vbus, 1); + if (phy->gpio_vbus >= 0) + gpio_set_value(phy->gpio_vbus, 1); }
-void sunxi_usbc_vbus_disable(int index) +void sunxi_usb_phy_power_off(int index) { - struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index]; + struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
- if (sunxi_usbc->gpio_vbus >= 0) - gpio_set_value(sunxi_usbc->gpio_vbus, 0); + if (phy->gpio_vbus >= 0) + gpio_set_value(phy->gpio_vbus, 0); }
-int sunxi_usbc_vbus_detect(int index) +int sunxi_usb_phy_vbus_detect(int index) { - struct sunxi_usbc_hcd *sunxi_usbc = &sunxi_usbc_hcd[index]; + struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; int err, retries = 3;
- if (sunxi_usbc->gpio_vbus_det < 0) { + if (phy->gpio_vbus_det < 0) { eprintf("Error: invalid vbus detection pin\n"); - return sunxi_usbc->gpio_vbus_det; + return phy->gpio_vbus_det; }
- err = gpio_get_value(sunxi_usbc->gpio_vbus_det); + err = gpio_get_value(phy->gpio_vbus_det); /* * Vbus may have been provided by the board and just been turned of * some milliseconds ago on reset, what we're measuring then is a @@ -273,7 +271,7 @@ int sunxi_usbc_vbus_detect(int index) */ while (err > 0 && retries--) { mdelay(100); - err = gpio_get_value(sunxi_usbc->gpio_vbus_det); + err = gpio_get_value(phy->gpio_vbus_det); }
return err; diff --git a/arch/arm/include/asm/arch-sunxi/usbc.h b/arch/arm/include/asm/arch-sunxi/usbc.h index 41721f9..14ed081 100644 --- a/arch/arm/include/asm/arch-sunxi/usbc.h +++ b/arch/arm/include/asm/arch-sunxi/usbc.h @@ -1,9 +1,8 @@ /* - * Sunxi usb-controller code shared between the ehci and musb controllers + * Sunxi usb-phy code * - * Copyright (C) 2014 Roman Byshko - * - * Roman Byshko rbyshko@gmail.com + * Copyright (C) 2015 Hans de Goede hdegoede@redhat.com + * Copyright (C) 2014 Roman Byshko rbyshko@gmail.com * * Based on code from * Allwinner Technology Co., Ltd. <www.allwinnertech.com> @@ -11,13 +10,11 @@ * SPDX-License-Identifier: GPL-2.0+ */
-extern const struct musb_platform_ops sunxi_musb_ops; - -int sunxi_usbc_request_resources(int index); -int sunxi_usbc_free_resources(int index); -void sunxi_usbc_enable(int index); -void sunxi_usbc_disable(int index); -void sunxi_usbc_vbus_enable(int index); -void sunxi_usbc_vbus_disable(int index); -int sunxi_usbc_vbus_detect(int index); -void sunxi_usbc_enable_squelch_detect(int index, int enable); +int sunxi_usb_phy_probe(int index); +int sunxi_usb_phy_remove(int index); +void sunxi_usb_phy_init(int index); +void sunxi_usb_phy_exit(int index); +void sunxi_usb_phy_power_on(int index); +void sunxi_usb_phy_power_off(int index); +int sunxi_usb_phy_vbus_detect(int index); +void sunxi_usb_phy_enable_squelch_detect(int index, int enable); diff --git a/board/sunxi/board.c b/board/sunxi/board.c index ee66f98..4ddd848 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -452,6 +452,8 @@ void sunxi_board_init(void) #endif
#if defined(CONFIG_MUSB_HOST) || defined(CONFIG_MUSB_GADGET) +extern const struct musb_platform_ops sunxi_musb_ops; + static struct musb_hdrc_config musb_config = { .multipoint = 1, .dyn_fifo = 1, diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index 5de20f9..b6fa538 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -1,7 +1,8 @@ /* - * Copyright (C) 2014 Roman Byshko + * Sunxi ehci glue * - * Roman Byshko rbyshko@gmail.com + * Copyright (C) 2015 Hans de Goede hdegoede@redhat.com + * Copyright (C) 2014 Roman Byshko rbyshko@gmail.com * * Based on code from * Allwinner Technology Co., Ltd. <www.allwinnertech.com> @@ -21,7 +22,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; int ahb_gate_offset, err;
- err = sunxi_usbc_request_resources(index + 1); + err = sunxi_usb_phy_probe(index + 1); if (err) return err;
@@ -32,8 +33,8 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, setbits_le32(&ccm->ahb_reset0_cfg, 1 << ahb_gate_offset); #endif
- sunxi_usbc_enable(index + 1); - sunxi_usbc_vbus_enable(index + 1); + sunxi_usb_phy_init(index + 1); + sunxi_usb_phy_power_on(index + 1);
if (index == 0) *hccr = (void *)SUNXI_USB1_BASE; @@ -55,8 +56,8 @@ int ehci_hcd_stop(int index) struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; int ahb_gate_offset;
- sunxi_usbc_vbus_disable(index + 1); - sunxi_usbc_disable(index + 1); + sunxi_usb_phy_power_off(index + 1); + sunxi_usb_phy_exit(index + 1);
ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 : AHB_GATE_OFFSET_USB_EHCI0; @@ -65,5 +66,5 @@ int ehci_hcd_stop(int index) #endif clrbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset);
- return sunxi_usbc_free_resources(index + 1); + return sunxi_usb_phy_remove(index + 1); } diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c index 7d90ebc..4d0213a 100644 --- a/drivers/usb/musb-new/musb_uboot.c +++ b/drivers/usb/musb-new/musb_uboot.c @@ -195,12 +195,12 @@ int usb_reset_root_port(void) * when clearing reset on low-speed devices, temporary disable * squelch detection to work around this. */ - sunxi_usbc_enable_squelch_detect(0, 0); + sunxi_usb_phy_enable_squelch_detect(0, 0); #endif power = musb_readb(mbase, MUSB_POWER); musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power); #ifdef CONFIG_ARCH_SUNXI - sunxi_usbc_enable_squelch_detect(0, 1); + sunxi_usb_phy_enable_squelch_detect(0, 1); #endif host->isr(0, host); host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ? diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index e3c6d6a..5a9d39c 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -214,7 +214,7 @@ static void sunxi_musb_enable(struct musb *musb)
if (is_host_enabled(musb)) { /* port power on */ - sunxi_usbc_vbus_enable(0); + sunxi_usb_phy_power_on(0); } }
@@ -226,7 +226,7 @@ static void sunxi_musb_disable(struct musb *musb)
/* Put the controller back in a pristane state for "usb reset" */ if (musb->is_active) { - sunxi_usbc_disable(0); + sunxi_usb_phy_exit(0); #ifdef CONFIG_SUNXI_GEN_SUN6I clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); #endif @@ -238,7 +238,7 @@ static void sunxi_musb_disable(struct musb *musb) #ifdef CONFIG_SUNXI_GEN_SUN6I setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); #endif - sunxi_usbc_enable(0); + sunxi_usb_phy_init(0); musb->is_active = 0; } } @@ -250,15 +250,15 @@ static int sunxi_musb_init(struct musb *musb)
pr_debug("%s():\n", __func__);
- err = sunxi_usbc_request_resources(0); + err = sunxi_usb_phy_probe(0); if (err) return err;
if (is_host_enabled(musb)) { - err = sunxi_usbc_vbus_detect(0); + err = sunxi_usb_phy_vbus_detect(0); if (err) { eprintf("Error: A charger is plugged into the OTG\n"); - sunxi_usbc_free_resources(0); + sunxi_usb_phy_remove(0); return -EIO; } } @@ -269,7 +269,7 @@ static int sunxi_musb_init(struct musb *musb) #ifdef CONFIG_SUNXI_GEN_SUN6I setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); #endif - sunxi_usbc_enable(0); + sunxi_usb_phy_init(0);
USBC_ConfigFIFO_Base(); USBC_EnableDpDmPullUp(musb->mregs); @@ -293,10 +293,10 @@ static int sunxi_musb_exit(struct musb *musb)
USBC_DisableDpDmPullUp(musb->mregs); USBC_DisableIdPullUp(musb->mregs); - sunxi_usbc_vbus_disable(0); - sunxi_usbc_disable(0); + sunxi_usb_phy_power_off(0); + sunxi_usb_phy_exit(0);
- return sunxi_usbc_free_resources(0); + return sunxi_usb_phy_remove(0); }
const struct musb_platform_ops sunxi_musb_ops = {

On Tue, 2015-04-28 at 08:41 +0200, Hans de Goede wrote:
Rename the sunxi_usbc_foo functions to sunxi_usb_phy_bar to make it clear that these are usb-phy functions. Also change the verbs & nouns in the suffix to match the verbs & nouns used in the Linux kernels generic phy framework.
This patch purely renames things, it contains no functional changes.
That being the case, without reading:
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Ian Campbell ijc@hellion.org.uk

The usbc.? files now only contain usb-phy related code, rename them to make this clear.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- arch/arm/cpu/armv7/sunxi/Makefile | 2 +- arch/arm/cpu/armv7/sunxi/{usbc.c => usb_phy.c} | 2 +- arch/arm/include/asm/arch-sunxi/{usbc.h => usb_phy.h} | 0 board/sunxi/board.c | 2 +- drivers/usb/host/ehci-sunxi.c | 2 +- drivers/usb/musb-new/musb_uboot.c | 2 +- drivers/usb/musb-new/sunxi.c | 2 +- 7 files changed, 6 insertions(+), 6 deletions(-) rename arch/arm/cpu/armv7/sunxi/{usbc.c => usb_phy.c} (99%) rename arch/arm/include/asm/arch-sunxi/{usbc.h => usb_phy.h} (100%)
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index 5221902..406a866 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -14,7 +14,7 @@ obj-y += cpu_info.o obj-y += dram_helpers.o obj-y += pinmux.o ifndef CONFIG_MACH_SUN9I -obj-y += usbc.o +obj-y += usb_phy.o endif obj-$(CONFIG_MACH_SUN6I) += prcm.o obj-$(CONFIG_MACH_SUN8I_A23) += prcm.o diff --git a/arch/arm/cpu/armv7/sunxi/usbc.c b/arch/arm/cpu/armv7/sunxi/usb_phy.c similarity index 99% rename from arch/arm/cpu/armv7/sunxi/usbc.c rename to arch/arm/cpu/armv7/sunxi/usb_phy.c index 71817c1..c238d38 100644 --- a/arch/arm/cpu/armv7/sunxi/usbc.c +++ b/arch/arm/cpu/armv7/sunxi/usb_phy.c @@ -13,7 +13,7 @@ #include <common.h> #include <asm/arch/clock.h> #include <asm/arch/cpu.h> -#include <asm/arch/usbc.h> +#include <asm/arch/usb_phy.h> #include <asm/gpio.h> #include <asm/io.h> #include <errno.h> diff --git a/arch/arm/include/asm/arch-sunxi/usbc.h b/arch/arm/include/asm/arch-sunxi/usb_phy.h similarity index 100% rename from arch/arm/include/asm/arch-sunxi/usbc.h rename to arch/arm/include/asm/arch-sunxi/usb_phy.h diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 4ddd848..7333946 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -28,7 +28,7 @@ #include <asm/arch/dram.h> #include <asm/arch/gpio.h> #include <asm/arch/mmc.h> -#include <asm/arch/usbc.h> +#include <asm/arch/usb_phy.h> #include <asm/gpio.h> #include <asm/io.h> #include <linux/usb/musb.h> diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index b6fa538..9e74a0b 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -12,7 +12,7 @@
#include <common.h> #include <asm/arch/clock.h> -#include <asm/arch/usbc.h> +#include <asm/arch/usb_phy.h> #include <asm/io.h> #include "ehci.h"
diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c index 4d0213a..d1ee5f8 100644 --- a/drivers/usb/musb-new/musb_uboot.c +++ b/drivers/usb/musb-new/musb_uboot.c @@ -1,7 +1,7 @@ #include <common.h> #include <watchdog.h> #ifdef CONFIG_ARCH_SUNXI -#include <asm/arch/usbc.h> +#include <asm/arch/usb_phy.h> #endif #include <asm/errno.h> #include <linux/usb/ch9.h> diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 5a9d39c..4f08f9f 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -24,7 +24,7 @@ #include <asm/arch/cpu.h> #include <asm/arch/clock.h> #include <asm/arch/gpio.h> -#include <asm/arch/usbc.h> +#include <asm/arch/usb_phy.h> #include <asm-generic/gpio.h> #include "linux-compat.h" #include "musb_core.h"

On Tue, 2015-04-28 at 08:41 +0200, Hans de Goede wrote:
The usbc.? files now only contain usb-phy related code, rename them to make this clear.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Ian Campbell ijc@hellion.org.uk

The 2/3 usb-phys on the sunxi SoCs are really a single separate functional block, and are modelled as such in devicetree. So once we've moved all the sunxi usb code to the driver-model then phy_probe will be called once for the entire block from the driver-model enumeration code.
Move to this now as this also avoids problems with phy_probe being called multiple times once we introduce ohci support. This allows us to get rid of the sunxi_usb_phy_enabled_count variable as phy_probe now is guaranteed to be called only once.
Since we're effectively rewriting the probe / remove functions, move them to the end of the file while we are at it, as that is the most logical place for them.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- arch/arm/cpu/armv7/sunxi/usb_phy.c | 106 ++++++++++++++++-------------- arch/arm/include/asm/arch-sunxi/usb_phy.h | 4 +- board/sunxi/board.c | 4 ++ drivers/usb/host/ehci-sunxi.c | 8 +-- drivers/usb/musb-new/sunxi.c | 7 +- include/configs/sun4i.h | 2 + include/configs/sun5i.h | 2 + include/configs/sun6i.h | 2 + include/configs/sun7i.h | 2 + include/configs/sun8i.h | 2 + 10 files changed, 76 insertions(+), 63 deletions(-)
diff --git a/arch/arm/cpu/armv7/sunxi/usb_phy.c b/arch/arm/cpu/armv7/sunxi/usb_phy.c index c238d38..1f85dec 100644 --- a/arch/arm/cpu/armv7/sunxi/usb_phy.c +++ b/arch/arm/cpu/armv7/sunxi/usb_phy.c @@ -54,7 +54,7 @@ static struct sunxi_usb_phy { .usb_rst_mask = CCM_USB_CTRL_PHY1_RST | CCM_USB_CTRL_PHY1_CLK, .id = 1, }, -#if (CONFIG_USB_MAX_CONTROLLER_COUNT > 1) +#if CONFIG_SUNXI_USB_PHYS >= 3 { .usb_rst_mask = CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK, .id = 2, @@ -62,8 +62,6 @@ static struct sunxi_usb_phy { #endif };
-static int sunxi_usb_phy_enabled_count; - static int get_vbus_gpio(int index) { switch (index) { @@ -167,57 +165,17 @@ void sunxi_usb_phy_enable_squelch_detect(int index, int enable) usb_phy_write(phy, 0x3c, enable ? 0 : 2, 2); }
-int sunxi_usb_phy_probe(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - int ret = 0; - - phy->gpio_vbus = get_vbus_gpio(index); - if (phy->gpio_vbus >= 0) { - ret |= gpio_request(phy->gpio_vbus, "usbc_vbus"); - ret |= gpio_direction_output(phy->gpio_vbus, 0); - } - - phy->gpio_vbus_det = get_vbus_detect_gpio(index); - if (phy->gpio_vbus_det >= 0) { - ret |= gpio_request(phy->gpio_vbus_det, "usbc_vbus_det"); - ret |= gpio_direction_input(phy->gpio_vbus_det); - } - - return ret; -} - -int sunxi_usb_phy_remove(int index) -{ - struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; - int ret = 0; - - if (phy->gpio_vbus >= 0) - ret |= gpio_free(phy->gpio_vbus); - - if (phy->gpio_vbus_det >= 0) - ret |= gpio_free(phy->gpio_vbus_det); - - return ret; -} - void sunxi_usb_phy_init(int index) { struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
- /* enable common PHY only once */ - if (sunxi_usb_phy_enabled_count == 0) - setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE); - setbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask);
sunxi_usb_phy_config(phy);
if (phy->id != 0) sunxi_usb_phy_passby(index, SUNXI_USB_PASSBY_EN); - - sunxi_usb_phy_enabled_count++; }
void sunxi_usb_phy_exit(int index) @@ -229,12 +187,6 @@ void sunxi_usb_phy_exit(int index) sunxi_usb_phy_passby(index, !SUNXI_USB_PASSBY_EN);
clrbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask); - - /* disable common PHY only once, for the last enabled phy */ - if (sunxi_usb_phy_enabled_count == 1) - clrbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE); - - sunxi_usb_phy_enabled_count--; }
void sunxi_usb_phy_power_on(int index) @@ -276,3 +228,59 @@ int sunxi_usb_phy_vbus_detect(int index)
return err; } + +int sunxi_usb_phy_probe(void) +{ + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + struct sunxi_usb_phy *phy; + int i, ret = 0; + + for (i = 0; i < CONFIG_SUNXI_USB_PHYS; i++) { + phy = &sunxi_usb_phy[i]; + + phy->gpio_vbus = get_vbus_gpio(i); + if (phy->gpio_vbus >= 0) { + ret = gpio_request(phy->gpio_vbus, "usb_vbus"); + if (ret) + return ret; + ret = gpio_direction_output(phy->gpio_vbus, 0); + if (ret) + return ret; + } + + phy->gpio_vbus_det = get_vbus_detect_gpio(i); + if (phy->gpio_vbus_det >= 0) { + ret = gpio_request(phy->gpio_vbus_det, "usb_vbus_det"); + if (ret) + return ret; + ret = gpio_direction_input(phy->gpio_vbus_det); + if (ret) + return ret; + } + } + + setbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE); + + return 0; +} + +int sunxi_usb_phy_remove(void) +{ + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + struct sunxi_usb_phy *phy; + int i; + + clrbits_le32(&ccm->usb_clk_cfg, CCM_USB_CTRL_PHYGATE); + + for (i = 0; i < CONFIG_SUNXI_USB_PHYS; i++) { + phy = &sunxi_usb_phy[i]; + + if (phy->gpio_vbus >= 0) + gpio_free(phy->gpio_vbus); + + if (phy->gpio_vbus_det >= 0) + gpio_free(phy->gpio_vbus_det); + } + + return 0; +} diff --git a/arch/arm/include/asm/arch-sunxi/usb_phy.h b/arch/arm/include/asm/arch-sunxi/usb_phy.h index 14ed081..b7b831e 100644 --- a/arch/arm/include/asm/arch-sunxi/usb_phy.h +++ b/arch/arm/include/asm/arch-sunxi/usb_phy.h @@ -10,8 +10,8 @@ * SPDX-License-Identifier: GPL-2.0+ */
-int sunxi_usb_phy_probe(int index); -int sunxi_usb_phy_remove(int index); +int sunxi_usb_phy_probe(void); +int sunxi_usb_phy_remove(void); void sunxi_usb_phy_init(int index); void sunxi_usb_phy_exit(int index); void sunxi_usb_phy_power_on(int index); diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 7333946..bbe67a6 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -530,6 +530,10 @@ int misc_init_r(void) } }
+ ret = sunxi_usb_phy_probe(); + if (ret) + return ret; + #if defined(CONFIG_MUSB_HOST) || defined(CONFIG_MUSB_GADGET) musb_register(&musb_plat, NULL, (void *)SUNXI_USB0_BASE); #endif diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index 9e74a0b..0edb643 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -20,11 +20,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - int ahb_gate_offset, err; - - err = sunxi_usb_phy_probe(index + 1); - if (err) - return err; + int ahb_gate_offset;
ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 : AHB_GATE_OFFSET_USB_EHCI0; @@ -66,5 +62,5 @@ int ehci_hcd_stop(int index) #endif clrbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset);
- return sunxi_usb_phy_remove(index + 1); + return 0; } diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 4f08f9f..e8a3a23 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -250,15 +250,10 @@ static int sunxi_musb_init(struct musb *musb)
pr_debug("%s():\n", __func__);
- err = sunxi_usb_phy_probe(0); - if (err) - return err; - if (is_host_enabled(musb)) { err = sunxi_usb_phy_vbus_detect(0); if (err) { eprintf("Error: A charger is plugged into the OTG\n"); - sunxi_usb_phy_remove(0); return -EIO; } } @@ -296,7 +291,7 @@ static int sunxi_musb_exit(struct musb *musb) sunxi_usb_phy_power_off(0); sunxi_usb_phy_exit(0);
- return sunxi_usb_phy_remove(0); + return 0; }
const struct musb_platform_ops sunxi_musb_ops = { diff --git a/include/configs/sun4i.h b/include/configs/sun4i.h index 7cd5c69..ea079eb 100644 --- a/include/configs/sun4i.h +++ b/include/configs/sun4i.h @@ -17,6 +17,8 @@ #define CONFIG_USB_MAX_CONTROLLER_COUNT 2 #endif
+#define CONFIG_SUNXI_USB_PHYS 3 + /* * Include common sunxi configuration where most the settings are */ diff --git a/include/configs/sun5i.h b/include/configs/sun5i.h index e0470d4..d257659 100644 --- a/include/configs/sun5i.h +++ b/include/configs/sun5i.h @@ -17,6 +17,8 @@ #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 #endif
+#define CONFIG_SUNXI_USB_PHYS 2 + /* * Include common sunxi configuration where most the settings are */ diff --git a/include/configs/sun6i.h b/include/configs/sun6i.h index 617c1cd..2c24bd2 100644 --- a/include/configs/sun6i.h +++ b/include/configs/sun6i.h @@ -20,6 +20,8 @@ #define CONFIG_USB_MAX_CONTROLLER_COUNT 2 #endif
+#define CONFIG_SUNXI_USB_PHYS 3 + /* * Include common sunxi configuration where most the settings are */ diff --git a/include/configs/sun7i.h b/include/configs/sun7i.h index 7fa7cec..56101a9 100644 --- a/include/configs/sun7i.h +++ b/include/configs/sun7i.h @@ -18,6 +18,8 @@ #define CONFIG_USB_MAX_CONTROLLER_COUNT 2 #endif
+#define CONFIG_SUNXI_USB_PHYS 3 + #define CONFIG_ARMV7_PSCI 1 #define CONFIG_ARMV7_SECURE_BASE SUNXI_SRAM_B_BASE #define CONFIG_TIMER_CLK_FREQ 24000000 diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h index 79796d7..7111c63 100644 --- a/include/configs/sun8i.h +++ b/include/configs/sun8i.h @@ -18,6 +18,8 @@ #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 #endif
+#define CONFIG_SUNXI_USB_PHYS 2 + /* * Include common sunxi configuration where most the settings are */

On Tue, 2015-04-28 at 08:41 +0200, Hans de Goede wrote:
The 2/3 usb-phys on the sunxi SoCs are really a single separate functional block, and are modelled as such in devicetree. So once we've moved all the sunxi usb code to the driver-model then phy_probe will be called once for the entire block from the driver-model enumeration code.
Move to this now as this also avoids problems with phy_probe being called multiple times once we introduce ohci support. This allows us to get rid of the sunxi_usb_phy_enabled_count variable as phy_probe now is guaranteed to be called only once.
Since we're effectively rewriting the probe / remove functions, move them to the end of the file while we are at it, as that is the most logical place for them.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Ian Campbell ijc@hellion.org.uk

Once we add support for the ohci controller the phy-init and phy-power-on functions may be called twice (once by the ehci code and once by the ohci code) protect them against this.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- arch/arm/cpu/armv7/sunxi/usb_phy.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/arch/arm/cpu/armv7/sunxi/usb_phy.c b/arch/arm/cpu/armv7/sunxi/usb_phy.c index 1f85dec..410669e 100644 --- a/arch/arm/cpu/armv7/sunxi/usb_phy.c +++ b/arch/arm/cpu/armv7/sunxi/usb_phy.c @@ -45,6 +45,8 @@ static struct sunxi_usb_phy { int gpio_vbus; int gpio_vbus_det; int id; + int init_count; + int power_on_count; } sunxi_usb_phy[] = { { .usb_rst_mask = CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK, @@ -170,6 +172,10 @@ void sunxi_usb_phy_init(int index) struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ phy->init_count++; + if (phy->init_count != 1) + return; + setbits_le32(&ccm->usb_clk_cfg, phy->usb_rst_mask);
sunxi_usb_phy_config(phy); @@ -183,6 +189,10 @@ void sunxi_usb_phy_exit(int index) struct sunxi_usb_phy *phy = &sunxi_usb_phy[index]; struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ phy->init_count--; + if (phy->init_count != 0) + return; + if (phy->id != 0) sunxi_usb_phy_passby(index, !SUNXI_USB_PASSBY_EN);
@@ -193,6 +203,10 @@ void sunxi_usb_phy_power_on(int index) { struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
+ phy->power_on_count++; + if (phy->power_on_count != 1) + return; + if (phy->gpio_vbus >= 0) gpio_set_value(phy->gpio_vbus, 1); } @@ -201,6 +215,10 @@ void sunxi_usb_phy_power_off(int index) { struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
+ phy->power_on_count--; + if (phy->power_on_count != 0) + return; + if (phy->gpio_vbus >= 0) gpio_set_value(phy->gpio_vbus, 0); }

On Tue, 2015-04-28 at 08:41 +0200, Hans de Goede wrote:
Once we add support for the ohci controller the phy-init and phy-power-on functions may be called twice (once by the ehci code and once by the ohci code) protect them against this.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Ian Campbell ijc@hellion.org.uk
participants (2)
-
Hans de Goede
-
Ian Campbell