mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 21:44:27 -04:00 
			
		
		
		
	ar71xx: add USB workarounds for AR934x/QCA955x SoCs
Signed-off-by: Gabor Juhos <juhosg@openwrt.org> SVN-Revision: 36787
This commit is contained in:
		
							parent
							
								
									6ff976a87a
								
							
						
					
					
						commit
						f02765086d
					
				| @ -0,0 +1,101 @@ | ||||
| --- a/drivers/usb/host/ehci-hcd.c
 | ||||
| +++ b/drivers/usb/host/ehci-hcd.c
 | ||||
| @@ -249,6 +249,37 @@ static int ehci_reset (struct ehci_hcd *
 | ||||
|  	command |= CMD_RESET; | ||||
|  	dbg_cmd (ehci, "reset", command); | ||||
|  	ehci_writel(ehci, command, &ehci->regs->command); | ||||
| +
 | ||||
| +	if (ehci->qca_force_host_mode) {
 | ||||
| +		u32 usbmode;
 | ||||
| +
 | ||||
| +		udelay(1000);
 | ||||
| +
 | ||||
| +		usbmode = ehci_readl(ehci, &ehci->regs->usbmode);
 | ||||
| +		usbmode |= USBMODE_CM_HC | (1 << 4);
 | ||||
| +		ehci_writel(ehci, usbmode, &ehci->regs->usbmode);
 | ||||
| +
 | ||||
| +		ehci_dbg(ehci, "forced host mode, usbmode: %08x\n",
 | ||||
| +			 ehci_readl(ehci, &ehci->regs->usbmode));
 | ||||
| +	}
 | ||||
| +
 | ||||
| +	if (ehci->qca_force_16bit_ptw) {
 | ||||
| +		u32 port_status;
 | ||||
| +
 | ||||
| +		udelay(1000);
 | ||||
| +
 | ||||
| +		/* enable 16-bit UTMI interface */
 | ||||
| +		port_status = ehci_readl(ehci, &ehci->regs->port_status[0]);
 | ||||
| +		port_status |= BIT(28);
 | ||||
| +		ehci_writel(ehci, port_status, &ehci->regs->port_status[0]);
 | ||||
| +
 | ||||
| +		ehci_dbg(ehci, "16-bit UTMI interface enabled, status: %08x\n",
 | ||||
| +			 ehci_readl(ehci, &ehci->regs->port_status[0]));
 | ||||
| +	}
 | ||||
| +
 | ||||
| +	if (ehci->reset_notifier)
 | ||||
| +		ehci->reset_notifier(ehci_to_hcd(ehci));
 | ||||
| +
 | ||||
|  	ehci->rh_state = EHCI_RH_HALTED; | ||||
|  	ehci->next_statechange = jiffies; | ||||
|  	retval = handshake (ehci, &ehci->regs->command, | ||||
| --- a/drivers/usb/host/ehci.h
 | ||||
| +++ b/drivers/usb/host/ehci.h
 | ||||
| @@ -201,6 +201,10 @@ struct ehci_hcd {			/* one per controlle
 | ||||
|  	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */ | ||||
|  	unsigned		frame_index_bug:1; /* MosChip (AKA NetMos) */ | ||||
|  	unsigned		ignore_oc:1; | ||||
| +	unsigned		qca_force_host_mode:1;
 | ||||
| +	unsigned		qca_force_16bit_ptw:1; /* force 16 bit UTMI */
 | ||||
| +
 | ||||
| +	void (*reset_notifier)(struct usb_hcd *hcd);
 | ||||
|   | ||||
|  	/* required for usb32 quirk */ | ||||
|  	#define OHCI_CTRL_HCFS          (3 << 6) | ||||
| --- a/include/linux/usb/ehci_pdriver.h
 | ||||
| +++ b/include/linux/usb/ehci_pdriver.h
 | ||||
| @@ -43,6 +43,8 @@ struct usb_ehci_pdata {
 | ||||
|  	unsigned	big_endian_mmio:1; | ||||
|  	unsigned	no_io_watchdog:1; | ||||
|  	unsigned	ignore_oc:1; | ||||
| +	unsigned	qca_force_host_mode:1;
 | ||||
| +	unsigned	qca_force_16bit_ptw:1;
 | ||||
|   | ||||
|  	/* Turn on all power and clocks */ | ||||
|  	int (*power_on)(struct platform_device *pdev); | ||||
| @@ -51,6 +53,7 @@ struct usb_ehci_pdata {
 | ||||
|  	/* Turn on only VBUS suspend power and hotplug detection, | ||||
|  	 * turn off everything else */ | ||||
|  	void (*power_suspend)(struct platform_device *pdev); | ||||
| +	void (*reset_notifier)(struct platform_device *pdev);
 | ||||
|  }; | ||||
|   | ||||
|  #endif /* __USB_CORE_EHCI_PDRIVER_H */ | ||||
| --- a/drivers/usb/host/ehci-platform.c
 | ||||
| +++ b/drivers/usb/host/ehci-platform.c
 | ||||
| @@ -33,6 +33,14 @@
 | ||||
|   | ||||
|  static const char hcd_name[] = "ehci-platform"; | ||||
|   | ||||
| +static void ehci_platform_reset_notifier(struct usb_hcd *hcd)
 | ||||
| +{
 | ||||
| +	struct platform_device *pdev = to_platform_device(hcd->self.controller);
 | ||||
| +	struct usb_ehci_pdata *pdata = pdev->dev.platform_data;
 | ||||
| +
 | ||||
| +	pdata->reset_notifier(pdev);
 | ||||
| +}
 | ||||
| +
 | ||||
|  static int ehci_platform_reset(struct usb_hcd *hcd) | ||||
|  { | ||||
|  	struct platform_device *pdev = to_platform_device(hcd->self.controller); | ||||
| @@ -45,6 +53,11 @@ static int ehci_platform_reset(struct us
 | ||||
|  	ehci->big_endian_desc = pdata->big_endian_desc; | ||||
|  	ehci->big_endian_mmio = pdata->big_endian_mmio; | ||||
|  	ehci->ignore_oc = pdata->ignore_oc; | ||||
| +	ehci->qca_force_host_mode = pdata->qca_force_host_mode;
 | ||||
| +	ehci->qca_force_16bit_ptw = pdata->qca_force_16bit_ptw;
 | ||||
| +
 | ||||
| +	if (pdata->reset_notifier)
 | ||||
| +		ehci->reset_notifier = ehci_platform_reset_notifier;
 | ||||
|   | ||||
|  	ehci->caps = hcd->regs + pdata->caps_offset; | ||||
|  	retval = ehci_setup(hcd); | ||||
| @ -0,0 +1,86 @@ | ||||
| --- a/arch/mips/ath79/dev-usb.c
 | ||||
| +++ b/arch/mips/ath79/dev-usb.c
 | ||||
| @@ -182,14 +182,34 @@ static void __init ar933x_usb_setup(void
 | ||||
|  			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); | ||||
|  } | ||||
|   | ||||
| -static void __init ar934x_usb_setup(void)
 | ||||
| +static void enable_tx_tx_idp_violation_fix(unsigned base)
 | ||||
|  { | ||||
| -	u32 bootstrap;
 | ||||
| +	void __iomem *phy_reg;
 | ||||
| +	u32 t;
 | ||||
| +
 | ||||
| +	phy_reg = ioremap(base, 4);
 | ||||
| +	if (!phy_reg)
 | ||||
| +		return;
 | ||||
| +
 | ||||
| +	t = ioread32(phy_reg);
 | ||||
| +	t &= ~0xff;
 | ||||
| +	t |= 0x58;
 | ||||
| +	iowrite32(t, phy_reg);
 | ||||
| +
 | ||||
| +	iounmap(phy_reg);
 | ||||
| +}
 | ||||
|   | ||||
| -	bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
 | ||||
| -	if (bootstrap & AR934X_BOOTSTRAP_USB_MODE_DEVICE)
 | ||||
| +static void ar934x_usb_reset_notifier(struct platform_device *pdev)
 | ||||
| +{
 | ||||
| +	if (pdev->id != -1)
 | ||||
|  		return; | ||||
|   | ||||
| +	enable_tx_tx_idp_violation_fix(0x18116c94);
 | ||||
| +	dev_info(&pdev->dev, "TX-TX IDP fix enabled\n");
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void __init ar934x_usb_setup(void)
 | ||||
| +{
 | ||||
|  	ath79_device_reset_set(AR934X_RESET_USBSUS_OVERRIDE); | ||||
|  	udelay(1000); | ||||
|   | ||||
| @@ -202,14 +222,44 @@ static void __init ar934x_usb_setup(void
 | ||||
|  	ath79_device_reset_clear(AR934X_RESET_USB_HOST); | ||||
|  	udelay(1000); | ||||
|   | ||||
| +	ath79_ehci_pdata_v2.qca_force_host_mode = 1;
 | ||||
| +	ath79_ehci_pdata_v2.qca_force_16bit_ptw = 1;
 | ||||
| +	if (ath79_soc_rev >= 3)
 | ||||
| +		ath79_ehci_pdata_v2.reset_notifier = ar934x_usb_reset_notifier;
 | ||||
| +
 | ||||
|  	ath79_usb_register("ehci-platform", -1, | ||||
|  			   AR934X_EHCI_BASE, AR934X_EHCI_SIZE, | ||||
|  			   ATH79_CPU_IRQ(3), | ||||
|  			   &ath79_ehci_pdata_v2, sizeof(ath79_ehci_pdata_v2)); | ||||
|  } | ||||
|   | ||||
| +static void qca955x_usb_reset_notifier(struct platform_device *pdev)
 | ||||
| +{
 | ||||
| +	u32 base;
 | ||||
| +
 | ||||
| +	switch (pdev->id) {
 | ||||
| +	case 0:
 | ||||
| +		base = 0x18116c94;
 | ||||
| +		break;
 | ||||
| +
 | ||||
| +	case 1:
 | ||||
| +		base = 0x18116e54;
 | ||||
| +		break;
 | ||||
| +
 | ||||
| +	default:
 | ||||
| +		return;
 | ||||
| +	}
 | ||||
| +
 | ||||
| +	enable_tx_tx_idp_violation_fix(base);
 | ||||
| +	dev_info(&pdev->dev, "TX-TX IDP fix enabled\n");
 | ||||
| +}
 | ||||
| +
 | ||||
|  static void __init qca955x_usb_setup(void) | ||||
|  { | ||||
| +	ath79_ehci_pdata_v2.qca_force_host_mode = 1;
 | ||||
| +	ath79_ehci_pdata_v2.qca_force_16bit_ptw = 1;
 | ||||
| +	ath79_ehci_pdata_v2.reset_notifier = qca955x_usb_reset_notifier;
 | ||||
| +
 | ||||
|  	ath79_usb_register("ehci-platform", 0, | ||||
|  			   QCA955X_EHCI0_BASE, QCA955X_EHCI_SIZE, | ||||
|  			   ATH79_IP3_IRQ(0), | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user