17
17
#include <linux/of_device.h>
18
18
#include <linux/of_dma.h>
19
19
20
- #define TI_XBAR_OUTPUTS 127
21
- #define TI_XBAR_INPUTS 256
20
+ #define TI_XBAR_DRA7 0
21
+ #define TI_XBAR_AM335X 1
22
+
23
+ static const struct of_device_id ti_dma_xbar_match [] = {
24
+ {
25
+ .compatible = "ti,dra7-dma-crossbar" ,
26
+ .data = (void * )TI_XBAR_DRA7 ,
27
+ },
28
+ {
29
+ .compatible = "ti,am335x-edma-crossbar" ,
30
+ .data = (void * )TI_XBAR_AM335X ,
31
+ },
32
+ {},
33
+ };
34
+
35
+ /* Crossbar on AM335x/AM437x family */
36
+ #define TI_AM335X_XBAR_LINES 64
37
+
38
+ struct ti_am335x_xbar_data {
39
+ void __iomem * iomem ;
40
+
41
+ struct dma_router dmarouter ;
42
+
43
+ u32 xbar_events ; /* maximum number of events to select in xbar */
44
+ u32 dma_requests ; /* number of DMA requests on eDMA */
45
+ };
46
+
47
+ struct ti_am335x_xbar_map {
48
+ u16 dma_line ;
49
+ u16 mux_val ;
50
+ };
51
+
52
+ static inline void ti_am335x_xbar_write (void __iomem * iomem , int event , u16 val )
53
+ {
54
+ writeb_relaxed (val & 0x1f , iomem + event );
55
+ }
56
+
57
+ static void ti_am335x_xbar_free (struct device * dev , void * route_data )
58
+ {
59
+ struct ti_am335x_xbar_data * xbar = dev_get_drvdata (dev );
60
+ struct ti_am335x_xbar_map * map = route_data ;
61
+
62
+ dev_dbg (dev , "Unmapping XBAR event %u on channel %u\n" ,
63
+ map -> mux_val , map -> dma_line );
64
+
65
+ ti_am335x_xbar_write (xbar -> iomem , map -> dma_line , 0 );
66
+ kfree (map );
67
+ }
68
+
69
+ static void * ti_am335x_xbar_route_allocate (struct of_phandle_args * dma_spec ,
70
+ struct of_dma * ofdma )
71
+ {
72
+ struct platform_device * pdev = of_find_device_by_node (ofdma -> of_node );
73
+ struct ti_am335x_xbar_data * xbar = platform_get_drvdata (pdev );
74
+ struct ti_am335x_xbar_map * map ;
75
+
76
+ if (dma_spec -> args_count != 3 )
77
+ return ERR_PTR (- EINVAL );
78
+
79
+ if (dma_spec -> args [2 ] >= xbar -> xbar_events ) {
80
+ dev_err (& pdev -> dev , "Invalid XBAR event number: %d\n" ,
81
+ dma_spec -> args [2 ]);
82
+ return ERR_PTR (- EINVAL );
83
+ }
84
+
85
+ if (dma_spec -> args [0 ] >= xbar -> dma_requests ) {
86
+ dev_err (& pdev -> dev , "Invalid DMA request line number: %d\n" ,
87
+ dma_spec -> args [0 ]);
88
+ return ERR_PTR (- EINVAL );
89
+ }
90
+
91
+ /* The of_node_put() will be done in the core for the node */
92
+ dma_spec -> np = of_parse_phandle (ofdma -> of_node , "dma-masters" , 0 );
93
+ if (!dma_spec -> np ) {
94
+ dev_err (& pdev -> dev , "Can't get DMA master\n" );
95
+ return ERR_PTR (- EINVAL );
96
+ }
97
+
98
+ map = kzalloc (sizeof (* map ), GFP_KERNEL );
99
+ if (!map ) {
100
+ of_node_put (dma_spec -> np );
101
+ return ERR_PTR (- ENOMEM );
102
+ }
103
+
104
+ map -> dma_line = (u16 )dma_spec -> args [0 ];
105
+ map -> mux_val = (u16 )dma_spec -> args [2 ];
106
+
107
+ dma_spec -> args [2 ] = 0 ;
108
+ dma_spec -> args_count = 2 ;
109
+
110
+ dev_dbg (& pdev -> dev , "Mapping XBAR event%u to DMA%u\n" ,
111
+ map -> mux_val , map -> dma_line );
112
+
113
+ ti_am335x_xbar_write (xbar -> iomem , map -> dma_line , map -> mux_val );
114
+
115
+ return map ;
116
+ }
117
+
118
+ static const struct of_device_id ti_am335x_master_match [] = {
119
+ { .compatible = "ti,edma3-tpcc" , },
120
+ {},
121
+ };
122
+
123
+ static int ti_am335x_xbar_probe (struct platform_device * pdev )
124
+ {
125
+ struct device_node * node = pdev -> dev .of_node ;
126
+ const struct of_device_id * match ;
127
+ struct device_node * dma_node ;
128
+ struct ti_am335x_xbar_data * xbar ;
129
+ struct resource * res ;
130
+ void __iomem * iomem ;
131
+ int i , ret ;
132
+
133
+ if (!node )
134
+ return - ENODEV ;
135
+
136
+ xbar = devm_kzalloc (& pdev -> dev , sizeof (* xbar ), GFP_KERNEL );
137
+ if (!xbar )
138
+ return - ENOMEM ;
139
+
140
+ dma_node = of_parse_phandle (node , "dma-masters" , 0 );
141
+ if (!dma_node ) {
142
+ dev_err (& pdev -> dev , "Can't get DMA master node\n" );
143
+ return - ENODEV ;
144
+ }
145
+
146
+ match = of_match_node (ti_am335x_master_match , dma_node );
147
+ if (!match ) {
148
+ dev_err (& pdev -> dev , "DMA master is not supported\n" );
149
+ return - EINVAL ;
150
+ }
151
+
152
+ if (of_property_read_u32 (dma_node , "dma-requests" ,
153
+ & xbar -> dma_requests )) {
154
+ dev_info (& pdev -> dev ,
155
+ "Missing XBAR output information, using %u.\n" ,
156
+ TI_AM335X_XBAR_LINES );
157
+ xbar -> dma_requests = TI_AM335X_XBAR_LINES ;
158
+ }
159
+ of_node_put (dma_node );
160
+
161
+ if (of_property_read_u32 (node , "dma-requests" , & xbar -> xbar_events )) {
162
+ dev_info (& pdev -> dev ,
163
+ "Missing XBAR input information, using %u.\n" ,
164
+ TI_AM335X_XBAR_LINES );
165
+ xbar -> xbar_events = TI_AM335X_XBAR_LINES ;
166
+ }
167
+
168
+ res = platform_get_resource (pdev , IORESOURCE_MEM , 0 );
169
+ iomem = devm_ioremap_resource (& pdev -> dev , res );
170
+ if (IS_ERR (iomem ))
171
+ return PTR_ERR (iomem );
172
+
173
+ xbar -> iomem = iomem ;
174
+
175
+ xbar -> dmarouter .dev = & pdev -> dev ;
176
+ xbar -> dmarouter .route_free = ti_am335x_xbar_free ;
177
+
178
+ platform_set_drvdata (pdev , xbar );
179
+
180
+ /* Reset the crossbar */
181
+ for (i = 0 ; i < xbar -> dma_requests ; i ++ )
182
+ ti_am335x_xbar_write (xbar -> iomem , i , 0 );
183
+
184
+ ret = of_dma_router_register (node , ti_am335x_xbar_route_allocate ,
185
+ & xbar -> dmarouter );
186
+
187
+ return ret ;
188
+ }
189
+
190
+ /* Crossbar on DRA7xx family */
191
+ #define TI_DRA7_XBAR_OUTPUTS 127
192
+ #define TI_DRA7_XBAR_INPUTS 256
22
193
23
194
#define TI_XBAR_EDMA_OFFSET 0
24
195
#define TI_XBAR_SDMA_OFFSET 1
25
196
26
- struct ti_dma_xbar_data {
197
+ struct ti_dra7_xbar_data {
27
198
void __iomem * iomem ;
28
199
29
200
struct dma_router dmarouter ;
@@ -35,35 +206,35 @@ struct ti_dma_xbar_data {
35
206
u32 dma_offset ;
36
207
};
37
208
38
- struct ti_dma_xbar_map {
209
+ struct ti_dra7_xbar_map {
39
210
u16 xbar_in ;
40
211
int xbar_out ;
41
212
};
42
213
43
- static inline void ti_dma_xbar_write (void __iomem * iomem , int xbar , u16 val )
214
+ static inline void ti_dra7_xbar_write (void __iomem * iomem , int xbar , u16 val )
44
215
{
45
216
writew_relaxed (val , iomem + (xbar * 2 ));
46
217
}
47
218
48
- static void ti_dma_xbar_free (struct device * dev , void * route_data )
219
+ static void ti_dra7_xbar_free (struct device * dev , void * route_data )
49
220
{
50
- struct ti_dma_xbar_data * xbar = dev_get_drvdata (dev );
51
- struct ti_dma_xbar_map * map = route_data ;
221
+ struct ti_dra7_xbar_data * xbar = dev_get_drvdata (dev );
222
+ struct ti_dra7_xbar_map * map = route_data ;
52
223
53
224
dev_dbg (dev , "Unmapping XBAR%u (was routed to %d)\n" ,
54
225
map -> xbar_in , map -> xbar_out );
55
226
56
- ti_dma_xbar_write (xbar -> iomem , map -> xbar_out , xbar -> safe_val );
227
+ ti_dra7_xbar_write (xbar -> iomem , map -> xbar_out , xbar -> safe_val );
57
228
idr_remove (& xbar -> map_idr , map -> xbar_out );
58
229
kfree (map );
59
230
}
60
231
61
- static void * ti_dma_xbar_route_allocate (struct of_phandle_args * dma_spec ,
62
- struct of_dma * ofdma )
232
+ static void * ti_dra7_xbar_route_allocate (struct of_phandle_args * dma_spec ,
233
+ struct of_dma * ofdma )
63
234
{
64
235
struct platform_device * pdev = of_find_device_by_node (ofdma -> of_node );
65
- struct ti_dma_xbar_data * xbar = platform_get_drvdata (pdev );
66
- struct ti_dma_xbar_map * map ;
236
+ struct ti_dra7_xbar_data * xbar = platform_get_drvdata (pdev );
237
+ struct ti_dra7_xbar_map * map ;
67
238
68
239
if (dma_spec -> args [0 ] >= xbar -> xbar_requests ) {
69
240
dev_err (& pdev -> dev , "Invalid XBAR request number: %d\n" ,
@@ -93,12 +264,12 @@ static void *ti_dma_xbar_route_allocate(struct of_phandle_args *dma_spec,
93
264
dev_dbg (& pdev -> dev , "Mapping XBAR%u to DMA%d\n" ,
94
265
map -> xbar_in , map -> xbar_out );
95
266
96
- ti_dma_xbar_write (xbar -> iomem , map -> xbar_out , map -> xbar_in );
267
+ ti_dra7_xbar_write (xbar -> iomem , map -> xbar_out , map -> xbar_in );
97
268
98
269
return map ;
99
270
}
100
271
101
- static const struct of_device_id ti_dma_master_match [] = {
272
+ static const struct of_device_id ti_dra7_master_match [] = {
102
273
{
103
274
.compatible = "ti,omap4430-sdma" ,
104
275
.data = (void * )TI_XBAR_SDMA_OFFSET ,
@@ -110,12 +281,12 @@ static const struct of_device_id ti_dma_master_match[] = {
110
281
{},
111
282
};
112
283
113
- static int ti_dma_xbar_probe (struct platform_device * pdev )
284
+ static int ti_dra7_xbar_probe (struct platform_device * pdev )
114
285
{
115
286
struct device_node * node = pdev -> dev .of_node ;
116
287
const struct of_device_id * match ;
117
288
struct device_node * dma_node ;
118
- struct ti_dma_xbar_data * xbar ;
289
+ struct ti_dra7_xbar_data * xbar ;
119
290
struct resource * res ;
120
291
u32 safe_val ;
121
292
void __iomem * iomem ;
@@ -136,7 +307,7 @@ static int ti_dma_xbar_probe(struct platform_device *pdev)
136
307
return - ENODEV ;
137
308
}
138
309
139
- match = of_match_node (ti_dma_master_match , dma_node );
310
+ match = of_match_node (ti_dra7_master_match , dma_node );
140
311
if (!match ) {
141
312
dev_err (& pdev -> dev , "DMA master is not supported\n" );
142
313
return - EINVAL ;
@@ -146,16 +317,16 @@ static int ti_dma_xbar_probe(struct platform_device *pdev)
146
317
& xbar -> dma_requests )) {
147
318
dev_info (& pdev -> dev ,
148
319
"Missing XBAR output information, using %u.\n" ,
149
- TI_XBAR_OUTPUTS );
150
- xbar -> dma_requests = TI_XBAR_OUTPUTS ;
320
+ TI_DRA7_XBAR_OUTPUTS );
321
+ xbar -> dma_requests = TI_DRA7_XBAR_OUTPUTS ;
151
322
}
152
323
of_node_put (dma_node );
153
324
154
325
if (of_property_read_u32 (node , "dma-requests" , & xbar -> xbar_requests )) {
155
326
dev_info (& pdev -> dev ,
156
327
"Missing XBAR input information, using %u.\n" ,
157
- TI_XBAR_INPUTS );
158
- xbar -> xbar_requests = TI_XBAR_INPUTS ;
328
+ TI_DRA7_XBAR_INPUTS );
329
+ xbar -> xbar_requests = TI_DRA7_XBAR_INPUTS ;
159
330
}
160
331
161
332
if (!of_property_read_u32 (node , "ti,dma-safe-map" , & safe_val ))
@@ -169,30 +340,50 @@ static int ti_dma_xbar_probe(struct platform_device *pdev)
169
340
xbar -> iomem = iomem ;
170
341
171
342
xbar -> dmarouter .dev = & pdev -> dev ;
172
- xbar -> dmarouter .route_free = ti_dma_xbar_free ;
343
+ xbar -> dmarouter .route_free = ti_dra7_xbar_free ;
173
344
xbar -> dma_offset = (u32 )match -> data ;
174
345
175
346
platform_set_drvdata (pdev , xbar );
176
347
177
348
/* Reset the crossbar */
178
349
for (i = 0 ; i < xbar -> dma_requests ; i ++ )
179
- ti_dma_xbar_write (xbar -> iomem , i , xbar -> safe_val );
350
+ ti_dra7_xbar_write (xbar -> iomem , i , xbar -> safe_val );
180
351
181
- ret = of_dma_router_register (node , ti_dma_xbar_route_allocate ,
352
+ ret = of_dma_router_register (node , ti_dra7_xbar_route_allocate ,
182
353
& xbar -> dmarouter );
183
354
if (ret ) {
184
355
/* Restore the defaults for the crossbar */
185
356
for (i = 0 ; i < xbar -> dma_requests ; i ++ )
186
- ti_dma_xbar_write (xbar -> iomem , i , i );
357
+ ti_dra7_xbar_write (xbar -> iomem , i , i );
187
358
}
188
359
189
360
return ret ;
190
361
}
191
362
192
- static const struct of_device_id ti_dma_xbar_match [] = {
193
- { .compatible = "ti,dra7-dma-crossbar" },
194
- {},
195
- };
363
+ static int ti_dma_xbar_probe (struct platform_device * pdev )
364
+ {
365
+ const struct of_device_id * match ;
366
+ int ret ;
367
+
368
+ match = of_match_node (ti_dma_xbar_match , pdev -> dev .of_node );
369
+ if (unlikely (!match ))
370
+ return - EINVAL ;
371
+
372
+ switch ((u32 )match -> data ) {
373
+ case TI_XBAR_DRA7 :
374
+ ret = ti_dra7_xbar_probe (pdev );
375
+ break ;
376
+ case TI_XBAR_AM335X :
377
+ ret = ti_am335x_xbar_probe (pdev );
378
+ break ;
379
+ default :
380
+ dev_err (& pdev -> dev , "Unsupported crossbar\n" );
381
+ ret = - ENODEV ;
382
+ break ;
383
+ }
384
+
385
+ return ret ;
386
+ }
196
387
197
388
static struct platform_driver ti_dma_xbar_driver = {
198
389
.driver = {
0 commit comments