Root/target/linux/ar71xx/files/arch/mips/ar71xx/dev-usb.c

1/*
2 * Atheros AR71xx USB host device support
3 *
4 * Copyright (C) 2008-2009 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/dma-mapping.h>
18#include <linux/platform_device.h>
19
20#include <asm/mach-ar71xx/ar71xx.h>
21#include <asm/mach-ar71xx/platform.h>
22
23#include "dev-usb.h"
24
25/*
26 * OHCI (USB full speed host controller)
27 */
28static struct resource ar71xx_ohci_resources[] = {
29    [0] = {
30        .start = AR71XX_OHCI_BASE,
31        .end = AR71XX_OHCI_BASE + AR71XX_OHCI_SIZE - 1,
32        .flags = IORESOURCE_MEM,
33    },
34    [1] = {
35        .start = AR71XX_MISC_IRQ_OHCI,
36        .end = AR71XX_MISC_IRQ_OHCI,
37        .flags = IORESOURCE_IRQ,
38    },
39};
40
41static struct resource ar7240_ohci_resources[] = {
42    [0] = {
43        .start = AR7240_OHCI_BASE,
44        .end = AR7240_OHCI_BASE + AR7240_OHCI_SIZE - 1,
45        .flags = IORESOURCE_MEM,
46    },
47    [1] = {
48        .start = AR71XX_CPU_IRQ_USB,
49        .end = AR71XX_CPU_IRQ_USB,
50        .flags = IORESOURCE_IRQ,
51    },
52};
53
54static u64 ar71xx_ohci_dmamask = DMA_BIT_MASK(32);
55static struct platform_device ar71xx_ohci_device = {
56    .name = "ar71xx-ohci",
57    .id = -1,
58    .resource = ar71xx_ohci_resources,
59    .num_resources = ARRAY_SIZE(ar71xx_ohci_resources),
60    .dev = {
61        .dma_mask = &ar71xx_ohci_dmamask,
62        .coherent_dma_mask = DMA_BIT_MASK(32),
63    },
64};
65
66/*
67 * EHCI (USB full speed host controller)
68 */
69static struct resource ar71xx_ehci_resources[] = {
70    [0] = {
71        .start = AR71XX_EHCI_BASE,
72        .end = AR71XX_EHCI_BASE + AR71XX_EHCI_SIZE - 1,
73        .flags = IORESOURCE_MEM,
74    },
75    [1] = {
76        .start = AR71XX_CPU_IRQ_USB,
77        .end = AR71XX_CPU_IRQ_USB,
78        .flags = IORESOURCE_IRQ,
79    },
80};
81
82static u64 ar71xx_ehci_dmamask = DMA_BIT_MASK(32);
83static struct ar71xx_ehci_platform_data ar71xx_ehci_data;
84
85static struct platform_device ar71xx_ehci_device = {
86    .name = "ar71xx-ehci",
87    .id = -1,
88    .resource = ar71xx_ehci_resources,
89    .num_resources = ARRAY_SIZE(ar71xx_ehci_resources),
90    .dev = {
91        .dma_mask = &ar71xx_ehci_dmamask,
92        .coherent_dma_mask = DMA_BIT_MASK(32),
93        .platform_data = &ar71xx_ehci_data,
94    },
95};
96
97#define AR71XX_USB_RESET_MASK \
98    (RESET_MODULE_USB_HOST | RESET_MODULE_USB_PHY \
99    | RESET_MODULE_USB_OHCI_DLL)
100
101#define AR7240_USB_RESET_MASK \
102    (RESET_MODULE_USB_HOST | RESET_MODULE_USB_OHCI_DLL_7240)
103
104static void __init ar71xx_usb_setup(void)
105{
106    ar71xx_device_stop(AR71XX_USB_RESET_MASK);
107    mdelay(1000);
108    ar71xx_device_start(AR71XX_USB_RESET_MASK);
109
110    /* Turning on the Buff and Desc swap bits */
111    ar71xx_usb_ctrl_wr(USB_CTRL_REG_CONFIG, 0xf0000);
112
113    /* WAR for HW bug. Here it adjusts the duration between two SOFS */
114    ar71xx_usb_ctrl_wr(USB_CTRL_REG_FLADJ, 0x20c00);
115
116    mdelay(900);
117
118    platform_device_register(&ar71xx_ohci_device);
119    platform_device_register(&ar71xx_ehci_device);
120}
121
122static void __init ar7240_usb_setup(void)
123{
124    ar71xx_device_stop(AR7240_USB_RESET_MASK);
125    mdelay(1000);
126    ar71xx_device_start(AR7240_USB_RESET_MASK);
127
128    /* WAR for HW bug. Here it adjusts the duration between two SOFS */
129    ar71xx_usb_ctrl_wr(USB_CTRL_REG_FLADJ, 0x3);
130
131    if (ar71xx_soc == AR71XX_SOC_AR7241 || ar71xx_soc == AR71XX_SOC_AR7242) {
132        ar71xx_ehci_data.is_ar91xx = 1;
133        ar71xx_ehci_device.resource = ar7240_ohci_resources;
134        ar71xx_ehci_device.num_resources = ARRAY_SIZE(ar7240_ohci_resources);
135        platform_device_register(&ar71xx_ehci_device);
136    } else {
137        ar71xx_ohci_device.resource = ar7240_ohci_resources;
138        ar71xx_ohci_device.num_resources = ARRAY_SIZE(ar7240_ohci_resources);
139        platform_device_register(&ar71xx_ohci_device);
140    }
141}
142
143static void __init ar91xx_usb_setup(void)
144{
145    ar71xx_device_stop(RESET_MODULE_USBSUS_OVERRIDE);
146    mdelay(10);
147
148    ar71xx_device_start(RESET_MODULE_USB_HOST);
149    mdelay(10);
150
151    ar71xx_device_start(RESET_MODULE_USB_PHY);
152    mdelay(10);
153
154    ar71xx_ehci_data.is_ar91xx = 1;
155    platform_device_register(&ar71xx_ehci_device);
156}
157
158void __init ar71xx_add_device_usb(void)
159{
160    switch (ar71xx_soc) {
161    case AR71XX_SOC_AR7240:
162    case AR71XX_SOC_AR7241:
163    case AR71XX_SOC_AR7242:
164        ar7240_usb_setup();
165        break;
166
167    case AR71XX_SOC_AR7130:
168    case AR71XX_SOC_AR7141:
169    case AR71XX_SOC_AR7161:
170        ar71xx_usb_setup();
171        break;
172
173    case AR71XX_SOC_AR9130:
174    case AR71XX_SOC_AR9132:
175        ar91xx_usb_setup();
176        break;
177
178    default:
179        BUG();
180    }
181}
182

Archive Download this file



interactive