sunxi: usb: Turn the usbc code into a usb-phy driver
Subsystems (4)
cover 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
PATCH 1/6 sunxi: usb: Move setup of host controller clocks to the host controller drivers
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.
--- 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(-)
arch/arm/cpu/armv7/sunxi/usbc.c +1 -13
@@ -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 */
drivers/usb/host/ehci-sunxi.c +22 -2
@@ -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 ); }
drivers/usb/musb-new/sunxi.c +20 -0
@@ -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 ();
Signature · 1 line
2.3.5
PATCH 1/6 sunxi: usb: Move setup of host controller clocks to the host controller drivers
Quoted 8 lines · Hans de Goede
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 <[email protected]>
PATCH 2/6 sunxi: usb: Remove sunxi_usbc_get_io_base function
In reply to Hans de GoedeThis 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.
--- 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(-)
arch/arm/cpu/armv7/sunxi/usbc.c +10 -20
@@ -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);
arch/arm/include/asm/arch-sunxi/usbc.h +0 -1
@@ -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);
drivers/usb/host/ehci-sunxi.c +4 -1
@@ -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)));
Signature · 1 line
2.3.5
PATCH 2/6 sunxi: usb: Remove sunxi_usbc_get_io_base function
Quoted 7 lines · Hans de Goede
This is the only function left in
sunxi/usbc.cwhich is not phy related, so remove it.This is a preparation patch for turning the
usbc.ccode into a proper usb phy driver.Signed-off-by Hans de Goede <[email protected]>
PATCH 3/6 sunxi: usb: Rename sunxi_usbc_foo functions to sunxi_usb_phy_bar
In reply to Hans de GoedeRename 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.
--- 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(-)
arch/arm/cpu/armv7/sunxi/usbc.c +61 -63
@@ -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 <[email protected]> +* Copyright (C) 2015 Hans de Goede <[email protected]> +* Copyright (C) 2014 Roman Byshko <[email protected]> * * 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 definedCONFIG_MACH_SUN4I || definedCONFIG_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;
arch/arm/include/asm/arch-sunxi/usbc.h +11 -14
@@ -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 <[email protected]> +* Copyright (C) 2015 Hans de Goede <[email protected]> +* Copyright (C) 2014 Roman Byshko <[email protected]> * * 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);
board/sunxi/board.c +2 -0
@@ -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,
drivers/usb/host/ehci-sunxi.c +9 -8
@@ -1,7 +1,8 @@/* -* Copyright (C) 2014 Roman Byshko +* Sunxi ehci glue * -* Roman Byshko <[email protected]> +* Copyright (C) 2015 Hans de Goede <[email protected]> +* Copyright (C) 2014 Roman Byshko <[email protected]> * * 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 ); }
drivers/usb/musb-new/musb_uboot.c +2 -2
@@ -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) ?
drivers/usb/musb-new/sunxi.c +10 -10
@@ -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 = {
Signature · 1 line
2.3.5
PATCH 3/6 sunxi: usb: Rename sunxi_usbc_foo functions to sunxi_usb_phy_bar
Quoted 5 lines · Hans de Goede
Rename the
sunxi_usbc_foofunctions tosunxi_usb_phy_barto 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:
Quoted 1 line
Signed-off-by Hans de Goede <[email protected]>
PATCH 4/6 sunxi: usb: Rename the usbc.? files to usb_phy.?
In reply to Hans de GoedeThe usbc.? files now only contain usb-phy related code, rename them to make this clear.
---
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%)arch/arm/cpu/armv7/sunxi/Makefile +1 -1
@@ -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
arch/arm/cpu/armv7/sunxi/usb_phy.c renamed from arch/arm/cpu/armv7/sunxi/usbc.c +1 -1
@@ -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>
arch/arm/include/asm/arch-sunxi/usb_phy.h renamed from arch/arm/include/asm/arch-sunxi/usbc.h +0 -0
board/sunxi/board.c +1 -1
@@ -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>
drivers/usb/host/ehci-sunxi.c +1 -1
@@ -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"
drivers/usb/musb-new/musb_uboot.c +1 -1
@@ -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>
drivers/usb/musb-new/sunxi.c +1 -1
@@ -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"
Signature · 1 line
2.3.5
PATCH 4/6 sunxi: usb: Rename the usbc.? files to usb_phy.?
Quoted 4 lines · Hans de Goede
The usbc.? files now only contain usb-phy related code, rename them to make this clear.
Signed-off-by Hans de Goede <[email protected]>
PATCH 5/6 sunxi: usb: Do not call phy_probe from hcd code
In reply to Hans de GoedeThe 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.
--- 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(-)
arch/arm/cpu/armv7/sunxi/usb_phy.c +57 -49
@@ -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 ; +}
arch/arm/include/asm/arch-sunxi/usb_phy.h +2 -2
@@ -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);
board/sunxi/board.c +4 -0
@@ -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
drivers/usb/host/ehci-sunxi.c +2 -6
@@ -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 ; }
drivers/usb/musb-new/sunxi.c +1 -6
@@ -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 = {
include/configs/sun4i.h +2 -0
@@ -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 */
include/configs/sun5i.h +2 -0
@@ -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 */
include/configs/sun6i.h +2 -0
@@ -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 */
include/configs/sun7i.h +2 -0
@@ -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
include/configs/sun8i.h +2 -0
@@ -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 */
Signature · 1 line
2.3.5
PATCH 5/6 sunxi: usb: Do not call phy_probe from hcd code
Quoted 10 lines · Hans de Goede
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_probewill be called once for the entire block from the driver-model enumeration code.Move to this now as this also avoids problems with
phy_probebeing called multiple times once we introduce ohci support. This allows us to get rid of thesunxi_usb_phy_enabled_countvariable asphy_probenow is guaranteed to be called only once.
Quoted 5 lines
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 <[email protected]>
PATCH 6/6 sunxi: usb: Protect phy-init and phy-power-on against multiple calls
In reply to Hans de GoedeOnce 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.
--- arch/arm/cpu/armv7/sunxi/usb_phy.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
arch/arm/cpu/armv7/sunxi/usb_phy.c +18 -0
@@ -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 ); }
Signature · 1 line
2.3.5
PATCH 6/6 sunxi: usb: Protect phy-init and phy-power-on against multiple calls
Quoted 5 lines · Hans de Goede
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 <[email protected]>