Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v3.8 236 lines 6.2 kB view raw
1/* 2 * Atheros AR7XXX/AR9XXX USB Host Controller device 3 * 4 * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 6 * 7 * Parts of this file are based on Atheros' 2.6.15 BSP 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License version 2 as published 11 * by the Free Software Foundation. 12 */ 13 14#include <linux/kernel.h> 15#include <linux/init.h> 16#include <linux/delay.h> 17#include <linux/irq.h> 18#include <linux/dma-mapping.h> 19#include <linux/platform_device.h> 20#include <linux/usb/ehci_pdriver.h> 21#include <linux/usb/ohci_pdriver.h> 22 23#include <asm/mach-ath79/ath79.h> 24#include <asm/mach-ath79/ar71xx_regs.h> 25#include "common.h" 26#include "dev-usb.h" 27 28static struct resource ath79_ohci_resources[2]; 29 30static u64 ath79_ohci_dmamask = DMA_BIT_MASK(32); 31 32static struct usb_ohci_pdata ath79_ohci_pdata = { 33}; 34 35static struct platform_device ath79_ohci_device = { 36 .name = "ohci-platform", 37 .id = -1, 38 .resource = ath79_ohci_resources, 39 .num_resources = ARRAY_SIZE(ath79_ohci_resources), 40 .dev = { 41 .dma_mask = &ath79_ohci_dmamask, 42 .coherent_dma_mask = DMA_BIT_MASK(32), 43 .platform_data = &ath79_ohci_pdata, 44 }, 45}; 46 47static struct resource ath79_ehci_resources[2]; 48 49static u64 ath79_ehci_dmamask = DMA_BIT_MASK(32); 50 51static struct usb_ehci_pdata ath79_ehci_pdata_v1 = { 52 .has_synopsys_hc_bug = 1, 53}; 54 55static struct usb_ehci_pdata ath79_ehci_pdata_v2 = { 56 .caps_offset = 0x100, 57 .has_tt = 1, 58}; 59 60static struct platform_device ath79_ehci_device = { 61 .name = "ehci-platform", 62 .id = -1, 63 .resource = ath79_ehci_resources, 64 .num_resources = ARRAY_SIZE(ath79_ehci_resources), 65 .dev = { 66 .dma_mask = &ath79_ehci_dmamask, 67 .coherent_dma_mask = DMA_BIT_MASK(32), 68 }, 69}; 70 71static void __init ath79_usb_init_resource(struct resource res[2], 72 unsigned long base, 73 unsigned long size, 74 int irq) 75{ 76 res[0].flags = IORESOURCE_MEM; 77 res[0].start = base; 78 res[0].end = base + size - 1; 79 80 res[1].flags = IORESOURCE_IRQ; 81 res[1].start = irq; 82 res[1].end = irq; 83} 84 85#define AR71XX_USB_RESET_MASK (AR71XX_RESET_USB_HOST | \ 86 AR71XX_RESET_USB_PHY | \ 87 AR71XX_RESET_USB_OHCI_DLL) 88 89static void __init ath79_usb_setup(void) 90{ 91 void __iomem *usb_ctrl_base; 92 93 ath79_device_reset_set(AR71XX_USB_RESET_MASK); 94 mdelay(1000); 95 ath79_device_reset_clear(AR71XX_USB_RESET_MASK); 96 97 usb_ctrl_base = ioremap(AR71XX_USB_CTRL_BASE, AR71XX_USB_CTRL_SIZE); 98 99 /* Turning on the Buff and Desc swap bits */ 100 __raw_writel(0xf0000, usb_ctrl_base + AR71XX_USB_CTRL_REG_CONFIG); 101 102 /* WAR for HW bug. Here it adjusts the duration between two SOFS */ 103 __raw_writel(0x20c00, usb_ctrl_base + AR71XX_USB_CTRL_REG_FLADJ); 104 105 iounmap(usb_ctrl_base); 106 107 mdelay(900); 108 109 ath79_usb_init_resource(ath79_ohci_resources, AR71XX_OHCI_BASE, 110 AR71XX_OHCI_SIZE, ATH79_MISC_IRQ_OHCI); 111 platform_device_register(&ath79_ohci_device); 112 113 ath79_usb_init_resource(ath79_ehci_resources, AR71XX_EHCI_BASE, 114 AR71XX_EHCI_SIZE, ATH79_CPU_IRQ_USB); 115 ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v1; 116 platform_device_register(&ath79_ehci_device); 117} 118 119static void __init ar7240_usb_setup(void) 120{ 121 void __iomem *usb_ctrl_base; 122 123 ath79_device_reset_clear(AR7240_RESET_OHCI_DLL); 124 ath79_device_reset_set(AR7240_RESET_USB_HOST); 125 126 mdelay(1000); 127 128 ath79_device_reset_set(AR7240_RESET_OHCI_DLL); 129 ath79_device_reset_clear(AR7240_RESET_USB_HOST); 130 131 usb_ctrl_base = ioremap(AR7240_USB_CTRL_BASE, AR7240_USB_CTRL_SIZE); 132 133 /* WAR for HW bug. Here it adjusts the duration between two SOFS */ 134 __raw_writel(0x3, usb_ctrl_base + AR71XX_USB_CTRL_REG_FLADJ); 135 136 iounmap(usb_ctrl_base); 137 138 ath79_usb_init_resource(ath79_ohci_resources, AR7240_OHCI_BASE, 139 AR7240_OHCI_SIZE, ATH79_CPU_IRQ_USB); 140 platform_device_register(&ath79_ohci_device); 141} 142 143static void __init ar724x_usb_setup(void) 144{ 145 ath79_device_reset_set(AR724X_RESET_USBSUS_OVERRIDE); 146 mdelay(10); 147 148 ath79_device_reset_clear(AR724X_RESET_USB_HOST); 149 mdelay(10); 150 151 ath79_device_reset_clear(AR724X_RESET_USB_PHY); 152 mdelay(10); 153 154 ath79_usb_init_resource(ath79_ehci_resources, AR724X_EHCI_BASE, 155 AR724X_EHCI_SIZE, ATH79_CPU_IRQ_USB); 156 ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; 157 platform_device_register(&ath79_ehci_device); 158} 159 160static void __init ar913x_usb_setup(void) 161{ 162 ath79_device_reset_set(AR913X_RESET_USBSUS_OVERRIDE); 163 mdelay(10); 164 165 ath79_device_reset_clear(AR913X_RESET_USB_HOST); 166 mdelay(10); 167 168 ath79_device_reset_clear(AR913X_RESET_USB_PHY); 169 mdelay(10); 170 171 ath79_usb_init_resource(ath79_ehci_resources, AR913X_EHCI_BASE, 172 AR913X_EHCI_SIZE, ATH79_CPU_IRQ_USB); 173 ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; 174 platform_device_register(&ath79_ehci_device); 175} 176 177static void __init ar933x_usb_setup(void) 178{ 179 ath79_device_reset_set(AR933X_RESET_USBSUS_OVERRIDE); 180 mdelay(10); 181 182 ath79_device_reset_clear(AR933X_RESET_USB_HOST); 183 mdelay(10); 184 185 ath79_device_reset_clear(AR933X_RESET_USB_PHY); 186 mdelay(10); 187 188 ath79_usb_init_resource(ath79_ehci_resources, AR933X_EHCI_BASE, 189 AR933X_EHCI_SIZE, ATH79_CPU_IRQ_USB); 190 ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; 191 platform_device_register(&ath79_ehci_device); 192} 193 194static void __init ar934x_usb_setup(void) 195{ 196 u32 bootstrap; 197 198 bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP); 199 if (bootstrap & AR934X_BOOTSTRAP_USB_MODE_DEVICE) 200 return; 201 202 ath79_device_reset_set(AR934X_RESET_USBSUS_OVERRIDE); 203 udelay(1000); 204 205 ath79_device_reset_clear(AR934X_RESET_USB_PHY); 206 udelay(1000); 207 208 ath79_device_reset_clear(AR934X_RESET_USB_PHY_ANALOG); 209 udelay(1000); 210 211 ath79_device_reset_clear(AR934X_RESET_USB_HOST); 212 udelay(1000); 213 214 ath79_usb_init_resource(ath79_ehci_resources, AR934X_EHCI_BASE, 215 AR934X_EHCI_SIZE, ATH79_CPU_IRQ_USB); 216 ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; 217 platform_device_register(&ath79_ehci_device); 218} 219 220void __init ath79_register_usb(void) 221{ 222 if (soc_is_ar71xx()) 223 ath79_usb_setup(); 224 else if (soc_is_ar7240()) 225 ar7240_usb_setup(); 226 else if (soc_is_ar7241() || soc_is_ar7242()) 227 ar724x_usb_setup(); 228 else if (soc_is_ar913x()) 229 ar913x_usb_setup(); 230 else if (soc_is_ar933x()) 231 ar933x_usb_setup(); 232 else if (soc_is_ar934x()) 233 ar934x_usb_setup(); 234 else 235 BUG(); 236}