Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v3.6 218 lines 5.9 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[] = { 29 [0] = { 30 /* .start and .end fields are filled dynamically */ 31 .flags = IORESOURCE_MEM, 32 }, 33 [1] = { 34 .start = ATH79_MISC_IRQ_OHCI, 35 .end = ATH79_MISC_IRQ_OHCI, 36 .flags = IORESOURCE_IRQ, 37 }, 38}; 39 40static u64 ath79_ohci_dmamask = DMA_BIT_MASK(32); 41 42static struct usb_ohci_pdata ath79_ohci_pdata = { 43}; 44 45static struct platform_device ath79_ohci_device = { 46 .name = "ohci-platform", 47 .id = -1, 48 .resource = ath79_ohci_resources, 49 .num_resources = ARRAY_SIZE(ath79_ohci_resources), 50 .dev = { 51 .dma_mask = &ath79_ohci_dmamask, 52 .coherent_dma_mask = DMA_BIT_MASK(32), 53 .platform_data = &ath79_ohci_pdata, 54 }, 55}; 56 57static struct resource ath79_ehci_resources[] = { 58 [0] = { 59 /* .start and .end fields are filled dynamically */ 60 .flags = IORESOURCE_MEM, 61 }, 62 [1] = { 63 .start = ATH79_CPU_IRQ_USB, 64 .end = ATH79_CPU_IRQ_USB, 65 .flags = IORESOURCE_IRQ, 66 }, 67}; 68 69static u64 ath79_ehci_dmamask = DMA_BIT_MASK(32); 70 71static struct usb_ehci_pdata ath79_ehci_pdata_v1 = { 72 .has_synopsys_hc_bug = 1, 73 .port_power_off = 1, 74}; 75 76static struct usb_ehci_pdata ath79_ehci_pdata_v2 = { 77 .caps_offset = 0x100, 78 .has_tt = 1, 79 .port_power_off = 1, 80}; 81 82static struct platform_device ath79_ehci_device = { 83 .name = "ehci-platform", 84 .id = -1, 85 .resource = ath79_ehci_resources, 86 .num_resources = ARRAY_SIZE(ath79_ehci_resources), 87 .dev = { 88 .dma_mask = &ath79_ehci_dmamask, 89 .coherent_dma_mask = DMA_BIT_MASK(32), 90 }, 91}; 92 93#define AR71XX_USB_RESET_MASK (AR71XX_RESET_USB_HOST | \ 94 AR71XX_RESET_USB_PHY | \ 95 AR71XX_RESET_USB_OHCI_DLL) 96 97static void __init ath79_usb_setup(void) 98{ 99 void __iomem *usb_ctrl_base; 100 101 ath79_device_reset_set(AR71XX_USB_RESET_MASK); 102 mdelay(1000); 103 ath79_device_reset_clear(AR71XX_USB_RESET_MASK); 104 105 usb_ctrl_base = ioremap(AR71XX_USB_CTRL_BASE, AR71XX_USB_CTRL_SIZE); 106 107 /* Turning on the Buff and Desc swap bits */ 108 __raw_writel(0xf0000, usb_ctrl_base + AR71XX_USB_CTRL_REG_CONFIG); 109 110 /* WAR for HW bug. Here it adjusts the duration between two SOFS */ 111 __raw_writel(0x20c00, usb_ctrl_base + AR71XX_USB_CTRL_REG_FLADJ); 112 113 iounmap(usb_ctrl_base); 114 115 mdelay(900); 116 117 ath79_ohci_resources[0].start = AR71XX_OHCI_BASE; 118 ath79_ohci_resources[0].end = AR71XX_OHCI_BASE + AR71XX_OHCI_SIZE - 1; 119 platform_device_register(&ath79_ohci_device); 120 121 ath79_ehci_resources[0].start = AR71XX_EHCI_BASE; 122 ath79_ehci_resources[0].end = AR71XX_EHCI_BASE + AR71XX_EHCI_SIZE - 1; 123 ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v1; 124 platform_device_register(&ath79_ehci_device); 125} 126 127static void __init ar7240_usb_setup(void) 128{ 129 void __iomem *usb_ctrl_base; 130 131 ath79_device_reset_clear(AR7240_RESET_OHCI_DLL); 132 ath79_device_reset_set(AR7240_RESET_USB_HOST); 133 134 mdelay(1000); 135 136 ath79_device_reset_set(AR7240_RESET_OHCI_DLL); 137 ath79_device_reset_clear(AR7240_RESET_USB_HOST); 138 139 usb_ctrl_base = ioremap(AR7240_USB_CTRL_BASE, AR7240_USB_CTRL_SIZE); 140 141 /* WAR for HW bug. Here it adjusts the duration between two SOFS */ 142 __raw_writel(0x3, usb_ctrl_base + AR71XX_USB_CTRL_REG_FLADJ); 143 144 iounmap(usb_ctrl_base); 145 146 ath79_ohci_resources[0].start = AR7240_OHCI_BASE; 147 ath79_ohci_resources[0].end = AR7240_OHCI_BASE + AR7240_OHCI_SIZE - 1; 148 ath79_ohci_resources[1].start = ATH79_CPU_IRQ_USB; 149 ath79_ohci_resources[1].end = ATH79_CPU_IRQ_USB; 150 platform_device_register(&ath79_ohci_device); 151} 152 153static void __init ar724x_usb_setup(void) 154{ 155 ath79_device_reset_set(AR724X_RESET_USBSUS_OVERRIDE); 156 mdelay(10); 157 158 ath79_device_reset_clear(AR724X_RESET_USB_HOST); 159 mdelay(10); 160 161 ath79_device_reset_clear(AR724X_RESET_USB_PHY); 162 mdelay(10); 163 164 ath79_ehci_resources[0].start = AR724X_EHCI_BASE; 165 ath79_ehci_resources[0].end = AR724X_EHCI_BASE + AR724X_EHCI_SIZE - 1; 166 ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; 167 platform_device_register(&ath79_ehci_device); 168} 169 170static void __init ar913x_usb_setup(void) 171{ 172 ath79_device_reset_set(AR913X_RESET_USBSUS_OVERRIDE); 173 mdelay(10); 174 175 ath79_device_reset_clear(AR913X_RESET_USB_HOST); 176 mdelay(10); 177 178 ath79_device_reset_clear(AR913X_RESET_USB_PHY); 179 mdelay(10); 180 181 ath79_ehci_resources[0].start = AR913X_EHCI_BASE; 182 ath79_ehci_resources[0].end = AR913X_EHCI_BASE + AR913X_EHCI_SIZE - 1; 183 ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; 184 platform_device_register(&ath79_ehci_device); 185} 186 187static void __init ar933x_usb_setup(void) 188{ 189 ath79_device_reset_set(AR933X_RESET_USBSUS_OVERRIDE); 190 mdelay(10); 191 192 ath79_device_reset_clear(AR933X_RESET_USB_HOST); 193 mdelay(10); 194 195 ath79_device_reset_clear(AR933X_RESET_USB_PHY); 196 mdelay(10); 197 198 ath79_ehci_resources[0].start = AR933X_EHCI_BASE; 199 ath79_ehci_resources[0].end = AR933X_EHCI_BASE + AR933X_EHCI_SIZE - 1; 200 ath79_ehci_device.dev.platform_data = &ath79_ehci_pdata_v2; 201 platform_device_register(&ath79_ehci_device); 202} 203 204void __init ath79_register_usb(void) 205{ 206 if (soc_is_ar71xx()) 207 ath79_usb_setup(); 208 else if (soc_is_ar7240()) 209 ar7240_usb_setup(); 210 else if (soc_is_ar7241() || soc_is_ar7242()) 211 ar724x_usb_setup(); 212 else if (soc_is_ar913x()) 213 ar913x_usb_setup(); 214 else if (soc_is_ar933x()) 215 ar933x_usb_setup(); 216 else 217 BUG(); 218}