diff mbox

[U-Boot,4/6] mips: ath79: Add support for ungating USB and ethernet on qca953x

Message ID BLU436-SMTP240D823286F8E3B0E37ECB6FF450@phx.gbl
State Accepted
Commit cdeb68e292358f9dedeaea167f6eba894c58823e
Delegated to: Daniel Schwierzeck
Headers show

Commit Message

Wills Wang May 30, 2016, 2:54 p.m. UTC
Add code to ungate USB and ethernet controller on qca953x

Signed-off-by: Wills Wang <wills.wang@live.com>
---

 arch/mips/mach-ath79/reset.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

Comments

Marek Vasut May 30, 2016, 3:18 p.m. UTC | #1
On 05/30/2016 04:54 PM, Wills Wang wrote:
> Add code to ungate USB and ethernet controller on qca953x

Is this code coming from mainline Linux ?

> Signed-off-by: Wills Wang <wills.wang@live.com>
> ---
> 
>  arch/mips/mach-ath79/reset.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 50 insertions(+)
> 
> diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c
> index 33bf979..a5ee141 100644
> --- a/arch/mips/mach-ath79/reset.c
> +++ b/arch/mips/mach-ath79/reset.c
> @@ -136,6 +136,23 @@ static int eth_init_ar934x(void)
>  	return 0;
>  }
>  
> +static int eth_init_qca953x(void)
> +{
> +	void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
> +					  MAP_NOCACHE);
> +	const u32 mask = QCA953X_RESET_GE0_MAC | QCA953X_RESET_GE0_MDIO |
> +			 QCA953X_RESET_GE1_MAC | QCA953X_RESET_GE1_MDIO |
> +			 QCA953X_RESET_ETH_SWITCH_ANALOG |
> +			 QCA953X_RESET_ETH_SWITCH;
> +
> +	setbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask);
> +	mdelay(1);
> +	clrbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask);
> +	mdelay(1);
> +
> +	return 0;
> +}
> +
>  int ath79_eth_reset(void)
>  {
>  	/*
> @@ -146,6 +163,8 @@ int ath79_eth_reset(void)
>  		return eth_init_ar933x();
>  	if (soc_is_ar934x())
>  		return eth_init_ar934x();
> +	if (soc_is_qca953x())
> +		return eth_init_qca953x();
>  
>  	return -EINVAL;
>  }
> @@ -185,6 +204,35 @@ static int usb_reset_ar934x(void __iomem *reset_regs)
>  	return 0;
>  }
>  
> +static int usb_reset_qca953x(void __iomem *reset_regs)
> +{
> +	void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
> +					  MAP_NOCACHE);
> +
> +	clrsetbits_be32(pregs + QCA953X_PLL_SWITCH_CLOCK_CONTROL_REG,
> +			0xf00, 0x200);
> +	mdelay(10);
> +
> +	/* Ungate the USB block */
> +	setbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
> +		     QCA953X_RESET_USBSUS_OVERRIDE);
> +	mdelay(1);
> +	clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
> +		     QCA953X_RESET_USB_PHY);
> +	mdelay(1);
> +	clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
> +		     QCA953X_RESET_USB_PHY_ANALOG);
> +	mdelay(1);
> +	clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
> +		     QCA953X_RESET_USB_HOST);
> +	mdelay(1);
> +	clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
> +		     QCA953X_RESET_USB_PHY_PLL_PWD_EXT);
> +	mdelay(1);
> +
> +	return 0;
> +}
> +
>  int ath79_usb_reset(void)
>  {
>  	void __iomem *usbc_regs = map_physmem(AR71XX_USB_CTRL_BASE,
> @@ -204,6 +252,8 @@ int ath79_usb_reset(void)
>  		return usb_reset_ar933x(reset_regs);
>  	if (soc_is_ar934x())
>  		return usb_reset_ar934x(reset_regs);
> +	if (soc_is_qca953x())
> +		return usb_reset_qca953x(reset_regs);
>  
>  	return -EINVAL;
>  }
>
Wills Wang May 31, 2016, 12:35 a.m. UTC | #2
On 05/30/2016 11:18 PM, Marek Vasut wrote:
> On 05/30/2016 04:54 PM, Wills Wang wrote:
>> Add code to ungate USB and ethernet controller on qca953x
> Is this code coming from mainline Linux ?

No, i refer to u-boot code from QSDK.
>> Signed-off-by: Wills Wang <wills.wang@live.com>
>> ---
>>
>>   arch/mips/mach-ath79/reset.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 50 insertions(+)
>>
>> diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c
>> index 33bf979..a5ee141 100644
>> --- a/arch/mips/mach-ath79/reset.c
>> +++ b/arch/mips/mach-ath79/reset.c
>> @@ -136,6 +136,23 @@ static int eth_init_ar934x(void)
>>   	return 0;
>>   }
>>   
>> +static int eth_init_qca953x(void)
>> +{
>> +	void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
>> +					  MAP_NOCACHE);
>> +	const u32 mask = QCA953X_RESET_GE0_MAC | QCA953X_RESET_GE0_MDIO |
>> +			 QCA953X_RESET_GE1_MAC | QCA953X_RESET_GE1_MDIO |
>> +			 QCA953X_RESET_ETH_SWITCH_ANALOG |
>> +			 QCA953X_RESET_ETH_SWITCH;
>> +
>> +	setbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask);
>> +	mdelay(1);
>> +	clrbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask);
>> +	mdelay(1);
>> +
>> +	return 0;
>> +}
>> +
>>   int ath79_eth_reset(void)
>>   {
>>   	/*
>> @@ -146,6 +163,8 @@ int ath79_eth_reset(void)
>>   		return eth_init_ar933x();
>>   	if (soc_is_ar934x())
>>   		return eth_init_ar934x();
>> +	if (soc_is_qca953x())
>> +		return eth_init_qca953x();
>>   
>>   	return -EINVAL;
>>   }
>> @@ -185,6 +204,35 @@ static int usb_reset_ar934x(void __iomem *reset_regs)
>>   	return 0;
>>   }
>>   
>> +static int usb_reset_qca953x(void __iomem *reset_regs)
>> +{
>> +	void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
>> +					  MAP_NOCACHE);
>> +
>> +	clrsetbits_be32(pregs + QCA953X_PLL_SWITCH_CLOCK_CONTROL_REG,
>> +			0xf00, 0x200);
>> +	mdelay(10);
>> +
>> +	/* Ungate the USB block */
>> +	setbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>> +		     QCA953X_RESET_USBSUS_OVERRIDE);
>> +	mdelay(1);
>> +	clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>> +		     QCA953X_RESET_USB_PHY);
>> +	mdelay(1);
>> +	clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>> +		     QCA953X_RESET_USB_PHY_ANALOG);
>> +	mdelay(1);
>> +	clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>> +		     QCA953X_RESET_USB_HOST);
>> +	mdelay(1);
>> +	clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>> +		     QCA953X_RESET_USB_PHY_PLL_PWD_EXT);
>> +	mdelay(1);
>> +
>> +	return 0;
>> +}
>> +
>>   int ath79_usb_reset(void)
>>   {
>>   	void __iomem *usbc_regs = map_physmem(AR71XX_USB_CTRL_BASE,
>> @@ -204,6 +252,8 @@ int ath79_usb_reset(void)
>>   		return usb_reset_ar933x(reset_regs);
>>   	if (soc_is_ar934x())
>>   		return usb_reset_ar934x(reset_regs);
>> +	if (soc_is_qca953x())
>> +		return usb_reset_qca953x(reset_regs);
>>   
>>   	return -EINVAL;
>>   }
>>
>
Marek Vasut May 31, 2016, 12:51 a.m. UTC | #3
On 05/31/2016 02:35 AM, Wills Wang wrote:
> 
> 
> On 05/30/2016 11:18 PM, Marek Vasut wrote:
>> On 05/30/2016 04:54 PM, Wills Wang wrote:
>>> Add code to ungate USB and ethernet controller on qca953x
>> Is this code coming from mainline Linux ?
> 
> No, i refer to u-boot code from QSDK.

Oh ok. I'd suggest to pick the code from mainline Linux when possible,
it's far more maintained than the ancient LSDK/QSDK.

>>> Signed-off-by: Wills Wang <wills.wang@live.com>
>>> ---
>>>
>>>   arch/mips/mach-ath79/reset.c | 50
>>> ++++++++++++++++++++++++++++++++++++++++++++
>>>   1 file changed, 50 insertions(+)
>>>
>>> diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c
>>> index 33bf979..a5ee141 100644
>>> --- a/arch/mips/mach-ath79/reset.c
>>> +++ b/arch/mips/mach-ath79/reset.c
>>> @@ -136,6 +136,23 @@ static int eth_init_ar934x(void)
>>>       return 0;
>>>   }
>>>   +static int eth_init_qca953x(void)
>>> +{
>>> +    void __iomem *rregs = map_physmem(AR71XX_RESET_BASE,
>>> AR71XX_RESET_SIZE,
>>> +                      MAP_NOCACHE);
>>> +    const u32 mask = QCA953X_RESET_GE0_MAC | QCA953X_RESET_GE0_MDIO |
>>> +             QCA953X_RESET_GE1_MAC | QCA953X_RESET_GE1_MDIO |
>>> +             QCA953X_RESET_ETH_SWITCH_ANALOG |
>>> +             QCA953X_RESET_ETH_SWITCH;
>>> +
>>> +    setbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask);
>>> +    mdelay(1);
>>> +    clrbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask);
>>> +    mdelay(1);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>>   int ath79_eth_reset(void)
>>>   {
>>>       /*
>>> @@ -146,6 +163,8 @@ int ath79_eth_reset(void)
>>>           return eth_init_ar933x();
>>>       if (soc_is_ar934x())
>>>           return eth_init_ar934x();
>>> +    if (soc_is_qca953x())
>>> +        return eth_init_qca953x();
>>>         return -EINVAL;
>>>   }
>>> @@ -185,6 +204,35 @@ static int usb_reset_ar934x(void __iomem
>>> *reset_regs)
>>>       return 0;
>>>   }
>>>   +static int usb_reset_qca953x(void __iomem *reset_regs)
>>> +{
>>> +    void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
>>> +                      MAP_NOCACHE);
>>> +
>>> +    clrsetbits_be32(pregs + QCA953X_PLL_SWITCH_CLOCK_CONTROL_REG,
>>> +            0xf00, 0x200);

Do you know what these magic numbers mean ?

>>> +    mdelay(10);
>>> +
>>> +    /* Ungate the USB block */
>>> +    setbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>> +             QCA953X_RESET_USBSUS_OVERRIDE);
>>> +    mdelay(1);
>>> +    clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>> +             QCA953X_RESET_USB_PHY);
>>> +    mdelay(1);
>>> +    clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>> +             QCA953X_RESET_USB_PHY_ANALOG);
>>> +    mdelay(1);
>>> +    clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>> +             QCA953X_RESET_USB_HOST);
>>> +    mdelay(1);
>>> +    clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>> +             QCA953X_RESET_USB_PHY_PLL_PWD_EXT);
>>> +    mdelay(1);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>>   int ath79_usb_reset(void)
>>>   {
>>>       void __iomem *usbc_regs = map_physmem(AR71XX_USB_CTRL_BASE,
>>> @@ -204,6 +252,8 @@ int ath79_usb_reset(void)
>>>           return usb_reset_ar933x(reset_regs);
>>>       if (soc_is_ar934x())
>>>           return usb_reset_ar934x(reset_regs);
>>> +    if (soc_is_qca953x())
>>> +        return usb_reset_qca953x(reset_regs);
>>>         return -EINVAL;
>>>   }
>>>
>>
>
Piotr Dymacz May 31, 2016, 8:50 a.m. UTC | #4
Hello,

2016-05-31 2:51 GMT+02:00 Marek Vasut <marex@denx.de>:
> On 05/31/2016 02:35 AM, Wills Wang wrote:

[snip]

>>>>   +static int usb_reset_qca953x(void __iomem *reset_regs)
>>>> +{
>>>> +    void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
>>>> +                      MAP_NOCACHE);
>>>> +
>>>> +    clrsetbits_be32(pregs + QCA953X_PLL_SWITCH_CLOCK_CONTROL_REG,
>>>> +            0xf00, 0x200);
>
> Do you know what these magic numbers mean ?

I can help here.

This register is common for (almost) all modern QC/A WiSOCs, with
similar structure, at least for AR934x, QCA953x, QCA955x and QCA956x
(please take a look at [1]).
I have seen it (SDK, datasheets) under two different names:
SWITCH_CLOCK_SPARE and SWITCH_CLOCK_CONTROL, on different addresses
(offset +/- 1), depending on the SOC.

The bit field [8:11] is "USB_REFCLK_FREQ_SEL" and it's the same for
all above SOCs. Value (dec) 2 is for 25 MHz, value 5 for 40 MHz.

I'm going to provide some patches for ath79 in future, which will make
code more universal for all QC/A WiSOCs.

--
Regards,
Piotr Dymacz

[1] http://postimg.org/image/tyrkhkw57/full/

>>>> +    mdelay(10);
>>>> +
>>>> +    /* Ungate the USB block */
>>>> +    setbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>>> +             QCA953X_RESET_USBSUS_OVERRIDE);
>>>> +    mdelay(1);
>>>> +    clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>>> +             QCA953X_RESET_USB_PHY);
>>>> +    mdelay(1);
>>>> +    clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>>> +             QCA953X_RESET_USB_PHY_ANALOG);
>>>> +    mdelay(1);
>>>> +    clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>>> +             QCA953X_RESET_USB_HOST);
>>>> +    mdelay(1);
>>>> +    clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>>> +             QCA953X_RESET_USB_PHY_PLL_PWD_EXT);
>>>> +    mdelay(1);
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>>   int ath79_usb_reset(void)
>>>>   {
>>>>       void __iomem *usbc_regs = map_physmem(AR71XX_USB_CTRL_BASE,
>>>> @@ -204,6 +252,8 @@ int ath79_usb_reset(void)
>>>>           return usb_reset_ar933x(reset_regs);
>>>>       if (soc_is_ar934x())
>>>>           return usb_reset_ar934x(reset_regs);
>>>> +    if (soc_is_qca953x())
>>>> +        return usb_reset_qca953x(reset_regs);
>>>>         return -EINVAL;
>>>>   }
>>>>
>>>
>>
>
>
> --
> Best regards,
> Marek Vasut
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
Daniel Schwierzeck May 31, 2016, 9:40 a.m. UTC | #5
Am 30.05.2016 um 16:54 schrieb Wills Wang:
> Add code to ungate USB and ethernet controller on qca953x
> 
> Signed-off-by: Wills Wang <wills.wang@live.com>
> ---
> 
>  arch/mips/mach-ath79/reset.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 50 insertions(+)

applied to u-boot-mips, thanks!
Marek Vasut May 31, 2016, 11:38 a.m. UTC | #6
On 05/31/2016 10:50 AM, Piotr Dymacz wrote:
> Hello,
> 
> 2016-05-31 2:51 GMT+02:00 Marek Vasut <marex@denx.de>:
>> On 05/31/2016 02:35 AM, Wills Wang wrote:
> 
> [snip]
> 
>>>>>   +static int usb_reset_qca953x(void __iomem *reset_regs)
>>>>> +{
>>>>> +    void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
>>>>> +                      MAP_NOCACHE);
>>>>> +
>>>>> +    clrsetbits_be32(pregs + QCA953X_PLL_SWITCH_CLOCK_CONTROL_REG,
>>>>> +            0xf00, 0x200);
>>
>> Do you know what these magic numbers mean ?
> 
> I can help here.
> 
> This register is common for (almost) all modern QC/A WiSOCs, with
> similar structure, at least for AR934x, QCA953x, QCA955x and QCA956x
> (please take a look at [1]).
> I have seen it (SDK, datasheets) under two different names:
> SWITCH_CLOCK_SPARE and SWITCH_CLOCK_CONTROL, on different addresses
> (offset +/- 1), depending on the SOC.
> 
> The bit field [8:11] is "USB_REFCLK_FREQ_SEL" and it's the same for
> all above SOCs. Value (dec) 2 is for 25 MHz, value 5 for 40 MHz.
> 
> I'm going to provide some patches for ath79 in future, which will make
> code more universal for all QC/A WiSOCs.

Oh, very cool, thanks!
Wills Wang May 31, 2016, 2:24 p.m. UTC | #7
On 05/31/2016 04:50 PM, Piotr Dymacz wrote:
> Hello,
>
> 2016-05-31 2:51 GMT+02:00 Marek Vasut <marex@denx.de>:
>> On 05/31/2016 02:35 AM, Wills Wang wrote:
> [snip]
>
>>>>>    +static int usb_reset_qca953x(void __iomem *reset_regs)
>>>>> +{
>>>>> +    void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
>>>>> +                      MAP_NOCACHE);
>>>>> +
>>>>> +    clrsetbits_be32(pregs + QCA953X_PLL_SWITCH_CLOCK_CONTROL_REG,
>>>>> +            0xf00, 0x200);
>> Do you know what these magic numbers mean ?
> I can help here.
>
> This register is common for (almost) all modern QC/A WiSOCs, with
> similar structure, at least for AR934x, QCA953x, QCA955x and QCA956x
> (please take a look at [1]).
> I have seen it (SDK, datasheets) under two different names:
> SWITCH_CLOCK_SPARE and SWITCH_CLOCK_CONTROL, on different addresses
> (offset +/- 1), depending on the SOC.
>
> The bit field [8:11] is "USB_REFCLK_FREQ_SEL" and it's the same for
> all above SOCs. Value (dec) 2 is for 25 MHz, value 5 for 40 MHz.
You are right, i found the same description in ar9341 data sheet.
> I'm going to provide some patches for ath79 in future, which will make
> code more universal for all QC/A WiSOCs.
You are always welcome.
> --
> Regards,
> Piotr Dymacz
>
> [1] http://postimg.org/image/tyrkhkw57/full/
>
>>>>> +    mdelay(10);
>>>>> +
>>>>> +    /* Ungate the USB block */
>>>>> +    setbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>>>> +             QCA953X_RESET_USBSUS_OVERRIDE);
>>>>> +    mdelay(1);
>>>>> +    clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>>>> +             QCA953X_RESET_USB_PHY);
>>>>> +    mdelay(1);
>>>>> +    clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>>>> +             QCA953X_RESET_USB_PHY_ANALOG);
>>>>> +    mdelay(1);
>>>>> +    clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>>>> +             QCA953X_RESET_USB_HOST);
>>>>> +    mdelay(1);
>>>>> +    clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
>>>>> +             QCA953X_RESET_USB_PHY_PLL_PWD_EXT);
>>>>> +    mdelay(1);
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +
>>>>>    int ath79_usb_reset(void)
>>>>>    {
>>>>>        void __iomem *usbc_regs = map_physmem(AR71XX_USB_CTRL_BASE,
>>>>> @@ -204,6 +252,8 @@ int ath79_usb_reset(void)
>>>>>            return usb_reset_ar933x(reset_regs);
>>>>>        if (soc_is_ar934x())
>>>>>            return usb_reset_ar934x(reset_regs);
>>>>> +    if (soc_is_qca953x())
>>>>> +        return usb_reset_qca953x(reset_regs);
>>>>>          return -EINVAL;
>>>>>    }
>>>>>
>>
>> --
>> Best regards,
>> Marek Vasut
>> _______________________________________________
>> U-Boot mailing list
>> U-Boot@lists.denx.de
>> http://lists.denx.de/mailman/listinfo/u-boot
diff mbox

Patch

diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c
index 33bf979..a5ee141 100644
--- a/arch/mips/mach-ath79/reset.c
+++ b/arch/mips/mach-ath79/reset.c
@@ -136,6 +136,23 @@  static int eth_init_ar934x(void)
 	return 0;
 }
 
+static int eth_init_qca953x(void)
+{
+	void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+					  MAP_NOCACHE);
+	const u32 mask = QCA953X_RESET_GE0_MAC | QCA953X_RESET_GE0_MDIO |
+			 QCA953X_RESET_GE1_MAC | QCA953X_RESET_GE1_MDIO |
+			 QCA953X_RESET_ETH_SWITCH_ANALOG |
+			 QCA953X_RESET_ETH_SWITCH;
+
+	setbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask);
+	mdelay(1);
+	clrbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask);
+	mdelay(1);
+
+	return 0;
+}
+
 int ath79_eth_reset(void)
 {
 	/*
@@ -146,6 +163,8 @@  int ath79_eth_reset(void)
 		return eth_init_ar933x();
 	if (soc_is_ar934x())
 		return eth_init_ar934x();
+	if (soc_is_qca953x())
+		return eth_init_qca953x();
 
 	return -EINVAL;
 }
@@ -185,6 +204,35 @@  static int usb_reset_ar934x(void __iomem *reset_regs)
 	return 0;
 }
 
+static int usb_reset_qca953x(void __iomem *reset_regs)
+{
+	void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
+					  MAP_NOCACHE);
+
+	clrsetbits_be32(pregs + QCA953X_PLL_SWITCH_CLOCK_CONTROL_REG,
+			0xf00, 0x200);
+	mdelay(10);
+
+	/* Ungate the USB block */
+	setbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
+		     QCA953X_RESET_USBSUS_OVERRIDE);
+	mdelay(1);
+	clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
+		     QCA953X_RESET_USB_PHY);
+	mdelay(1);
+	clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
+		     QCA953X_RESET_USB_PHY_ANALOG);
+	mdelay(1);
+	clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
+		     QCA953X_RESET_USB_HOST);
+	mdelay(1);
+	clrbits_be32(reset_regs + QCA953X_RESET_REG_RESET_MODULE,
+		     QCA953X_RESET_USB_PHY_PLL_PWD_EXT);
+	mdelay(1);
+
+	return 0;
+}
+
 int ath79_usb_reset(void)
 {
 	void __iomem *usbc_regs = map_physmem(AR71XX_USB_CTRL_BASE,
@@ -204,6 +252,8 @@  int ath79_usb_reset(void)
 		return usb_reset_ar933x(reset_regs);
 	if (soc_is_ar934x())
 		return usb_reset_ar934x(reset_regs);
+	if (soc_is_qca953x())
+		return usb_reset_qca953x(reset_regs);
 
 	return -EINVAL;
 }