diff options
Diffstat (limited to 'arch/arm/mach-ux500/usb.c')
-rw-r--r-- | arch/arm/mach-ux500/usb.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c new file mode 100644 index 000000000000..82e535953fd9 --- /dev/null +++ b/arch/arm/mach-ux500/usb.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2011 | ||
3 | * | ||
4 | * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> | ||
5 | * License terms: GNU General Public License (GPL) version 2 | ||
6 | */ | ||
7 | #include <linux/platform_device.h> | ||
8 | #include <linux/usb/musb.h> | ||
9 | #include <plat/ste_dma40.h> | ||
10 | #include <mach/hardware.h> | ||
11 | #include <mach/usb.h> | ||
12 | |||
13 | #define MUSB_DMA40_RX_CH { \ | ||
14 | .mode = STEDMA40_MODE_LOGICAL, \ | ||
15 | .dir = STEDMA40_PERIPH_TO_MEM, \ | ||
16 | .dst_dev_type = STEDMA40_DEV_DST_MEMORY, \ | ||
17 | .src_info.data_width = STEDMA40_WORD_WIDTH, \ | ||
18 | .dst_info.data_width = STEDMA40_WORD_WIDTH, \ | ||
19 | .src_info.psize = STEDMA40_PSIZE_LOG_16, \ | ||
20 | .dst_info.psize = STEDMA40_PSIZE_LOG_16, \ | ||
21 | } | ||
22 | |||
23 | #define MUSB_DMA40_TX_CH { \ | ||
24 | .mode = STEDMA40_MODE_LOGICAL, \ | ||
25 | .dir = STEDMA40_MEM_TO_PERIPH, \ | ||
26 | .src_dev_type = STEDMA40_DEV_SRC_MEMORY, \ | ||
27 | .src_info.data_width = STEDMA40_WORD_WIDTH, \ | ||
28 | .dst_info.data_width = STEDMA40_WORD_WIDTH, \ | ||
29 | .src_info.psize = STEDMA40_PSIZE_LOG_16, \ | ||
30 | .dst_info.psize = STEDMA40_PSIZE_LOG_16, \ | ||
31 | } | ||
32 | |||
33 | static struct stedma40_chan_cfg musb_dma_rx_ch[UX500_MUSB_DMA_NUM_RX_CHANNELS] | ||
34 | = { | ||
35 | MUSB_DMA40_RX_CH, | ||
36 | MUSB_DMA40_RX_CH, | ||
37 | MUSB_DMA40_RX_CH, | ||
38 | MUSB_DMA40_RX_CH, | ||
39 | MUSB_DMA40_RX_CH, | ||
40 | MUSB_DMA40_RX_CH, | ||
41 | MUSB_DMA40_RX_CH, | ||
42 | MUSB_DMA40_RX_CH | ||
43 | }; | ||
44 | |||
45 | static struct stedma40_chan_cfg musb_dma_tx_ch[UX500_MUSB_DMA_NUM_TX_CHANNELS] | ||
46 | = { | ||
47 | MUSB_DMA40_TX_CH, | ||
48 | MUSB_DMA40_TX_CH, | ||
49 | MUSB_DMA40_TX_CH, | ||
50 | MUSB_DMA40_TX_CH, | ||
51 | MUSB_DMA40_TX_CH, | ||
52 | MUSB_DMA40_TX_CH, | ||
53 | MUSB_DMA40_TX_CH, | ||
54 | MUSB_DMA40_TX_CH, | ||
55 | }; | ||
56 | |||
57 | static void *ux500_dma_rx_param_array[UX500_MUSB_DMA_NUM_RX_CHANNELS] = { | ||
58 | &musb_dma_rx_ch[0], | ||
59 | &musb_dma_rx_ch[1], | ||
60 | &musb_dma_rx_ch[2], | ||
61 | &musb_dma_rx_ch[3], | ||
62 | &musb_dma_rx_ch[4], | ||
63 | &musb_dma_rx_ch[5], | ||
64 | &musb_dma_rx_ch[6], | ||
65 | &musb_dma_rx_ch[7] | ||
66 | }; | ||
67 | |||
68 | static void *ux500_dma_tx_param_array[UX500_MUSB_DMA_NUM_TX_CHANNELS] = { | ||
69 | &musb_dma_tx_ch[0], | ||
70 | &musb_dma_tx_ch[1], | ||
71 | &musb_dma_tx_ch[2], | ||
72 | &musb_dma_tx_ch[3], | ||
73 | &musb_dma_tx_ch[4], | ||
74 | &musb_dma_tx_ch[5], | ||
75 | &musb_dma_tx_ch[6], | ||
76 | &musb_dma_tx_ch[7] | ||
77 | }; | ||
78 | |||
79 | static struct ux500_musb_board_data musb_board_data = { | ||
80 | .dma_rx_param_array = ux500_dma_rx_param_array, | ||
81 | .dma_tx_param_array = ux500_dma_tx_param_array, | ||
82 | .num_rx_channels = UX500_MUSB_DMA_NUM_RX_CHANNELS, | ||
83 | .num_tx_channels = UX500_MUSB_DMA_NUM_TX_CHANNELS, | ||
84 | .dma_filter = stedma40_filter, | ||
85 | }; | ||
86 | |||
87 | static u64 ux500_musb_dmamask = DMA_BIT_MASK(32); | ||
88 | |||
89 | static struct musb_hdrc_config musb_hdrc_config = { | ||
90 | .multipoint = true, | ||
91 | .dyn_fifo = true, | ||
92 | .num_eps = 16, | ||
93 | .ram_bits = 16, | ||
94 | }; | ||
95 | |||
96 | static struct musb_hdrc_platform_data musb_platform_data = { | ||
97 | #if defined(CONFIG_USB_MUSB_OTG) | ||
98 | .mode = MUSB_OTG, | ||
99 | #elif defined(CONFIG_USB_MUSB_PERIPHERAL) | ||
100 | .mode = MUSB_PERIPHERAL, | ||
101 | #else /* defined(CONFIG_USB_MUSB_HOST) */ | ||
102 | .mode = MUSB_HOST, | ||
103 | #endif | ||
104 | .config = &musb_hdrc_config, | ||
105 | .board_data = &musb_board_data, | ||
106 | }; | ||
107 | |||
108 | static struct resource usb_resources[] = { | ||
109 | [0] = { | ||
110 | .name = "usb-mem", | ||
111 | .flags = IORESOURCE_MEM, | ||
112 | }, | ||
113 | |||
114 | [1] = { | ||
115 | .name = "mc", /* hard-coded in musb */ | ||
116 | .flags = IORESOURCE_IRQ, | ||
117 | }, | ||
118 | }; | ||
119 | |||
120 | struct platform_device ux500_musb_device = { | ||
121 | .name = "musb-ux500", | ||
122 | .id = 0, | ||
123 | .dev = { | ||
124 | .platform_data = &musb_platform_data, | ||
125 | .dma_mask = &ux500_musb_dmamask, | ||
126 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
127 | }, | ||
128 | .num_resources = ARRAY_SIZE(usb_resources), | ||
129 | .resource = usb_resources, | ||
130 | }; | ||
131 | |||
132 | static inline void ux500_usb_dma_update_rx_ch_config(int *src_dev_type) | ||
133 | { | ||
134 | u32 idx; | ||
135 | |||
136 | for (idx = 0; idx < UX500_MUSB_DMA_NUM_RX_CHANNELS; idx++) | ||
137 | musb_dma_rx_ch[idx].src_dev_type = src_dev_type[idx]; | ||
138 | } | ||
139 | |||
140 | static inline void ux500_usb_dma_update_tx_ch_config(int *dst_dev_type) | ||
141 | { | ||
142 | u32 idx; | ||
143 | |||
144 | for (idx = 0; idx < UX500_MUSB_DMA_NUM_TX_CHANNELS; idx++) | ||
145 | musb_dma_tx_ch[idx].dst_dev_type = dst_dev_type[idx]; | ||
146 | } | ||
147 | |||
148 | void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg, | ||
149 | int *dma_tx_cfg) | ||
150 | { | ||
151 | ux500_musb_device.resource[0].start = base; | ||
152 | ux500_musb_device.resource[0].end = base + SZ_64K - 1; | ||
153 | ux500_musb_device.resource[1].start = irq; | ||
154 | ux500_musb_device.resource[1].end = irq; | ||
155 | |||
156 | ux500_usb_dma_update_rx_ch_config(dma_rx_cfg); | ||
157 | ux500_usb_dma_update_tx_ch_config(dma_tx_cfg); | ||
158 | |||
159 | platform_device_register(&ux500_musb_device); | ||
160 | } | ||