Root/
Source at commit 4525beeb9aadbb9e1cb3e9e135f4371553f26a70 created 9 years 11 months ago. By Felipe Balbi, usb: phy: rename usb_nop_xceiv to usb_phy_generic | |
---|---|
1 | /* |
2 | * MUSB OTG controller driver for Blackfin Processors |
3 | * |
4 | * Copyright 2006-2008 Analog Devices Inc. |
5 | * |
6 | * Enter bugs at http://blackfin.uclinux.org/ |
7 | * |
8 | * Licensed under the GPL-2 or later. |
9 | */ |
10 | |
11 | #include <linux/module.h> |
12 | #include <linux/kernel.h> |
13 | #include <linux/sched.h> |
14 | #include <linux/list.h> |
15 | #include <linux/gpio.h> |
16 | #include <linux/io.h> |
17 | #include <linux/err.h> |
18 | #include <linux/platform_device.h> |
19 | #include <linux/dma-mapping.h> |
20 | #include <linux/prefetch.h> |
21 | #include <linux/usb/usb_phy_gen_xceiv.h> |
22 | |
23 | #include <asm/cacheflush.h> |
24 | |
25 | #include "musb_core.h" |
26 | #include "musbhsdma.h" |
27 | #include "blackfin.h" |
28 | |
29 | struct bfin_glue { |
30 | struct device *dev; |
31 | struct platform_device *musb; |
32 | }; |
33 | #define glue_to_musb(g) platform_get_drvdata(g->musb) |
34 | |
35 | /* |
36 | * Load an endpoint's FIFO |
37 | */ |
38 | void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) |
39 | { |
40 | struct musb *musb = hw_ep->musb; |
41 | void __iomem *fifo = hw_ep->fifo; |
42 | void __iomem *epio = hw_ep->regs; |
43 | u8 epnum = hw_ep->epnum; |
44 | |
45 | prefetch((u8 *)src); |
46 | |
47 | musb_writew(epio, MUSB_TXCOUNT, len); |
48 | |
49 | dev_dbg(musb->controller, "TX ep%d fifo %p count %d buf %p, epio %p\n", |
50 | hw_ep->epnum, fifo, len, src, epio); |
51 | |
52 | dump_fifo_data(src, len); |
53 | |
54 | if (!ANOMALY_05000380 && epnum != 0) { |
55 | u16 dma_reg; |
56 | |
57 | flush_dcache_range((unsigned long)src, |
58 | (unsigned long)(src + len)); |
59 | |
60 | /* Setup DMA address register */ |
61 | dma_reg = (u32)src; |
62 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); |
63 | SSYNC(); |
64 | |
65 | dma_reg = (u32)src >> 16; |
66 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); |
67 | SSYNC(); |
68 | |
69 | /* Setup DMA count register */ |
70 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len); |
71 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0); |
72 | SSYNC(); |
73 | |
74 | /* Enable the DMA */ |
75 | dma_reg = (epnum << 4) | DMA_ENA | INT_ENA | DIRECTION; |
76 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg); |
77 | SSYNC(); |
78 | |
79 | /* Wait for complete */ |
80 | while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum))) |
81 | cpu_relax(); |
82 | |
83 | /* acknowledge dma interrupt */ |
84 | bfin_write_USB_DMA_INTERRUPT(1 << epnum); |
85 | SSYNC(); |
86 | |
87 | /* Reset DMA */ |
88 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0); |
89 | SSYNC(); |
90 | } else { |
91 | SSYNC(); |
92 | |
93 | if (unlikely((unsigned long)src & 0x01)) |
94 | outsw_8((unsigned long)fifo, src, (len + 1) >> 1); |
95 | else |
96 | outsw((unsigned long)fifo, src, (len + 1) >> 1); |
97 | } |
98 | } |
99 | /* |
100 | * Unload an endpoint's FIFO |
101 | */ |
102 | void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) |
103 | { |
104 | struct musb *musb = hw_ep->musb; |
105 | void __iomem *fifo = hw_ep->fifo; |
106 | u8 epnum = hw_ep->epnum; |
107 | |
108 | if (ANOMALY_05000467 && epnum != 0) { |
109 | u16 dma_reg; |
110 | |
111 | invalidate_dcache_range((unsigned long)dst, |
112 | (unsigned long)(dst + len)); |
113 | |
114 | /* Setup DMA address register */ |
115 | dma_reg = (u32)dst; |
116 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); |
117 | SSYNC(); |
118 | |
119 | dma_reg = (u32)dst >> 16; |
120 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); |
121 | SSYNC(); |
122 | |
123 | /* Setup DMA count register */ |
124 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len); |
125 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0); |
126 | SSYNC(); |
127 | |
128 | /* Enable the DMA */ |
129 | dma_reg = (epnum << 4) | DMA_ENA | INT_ENA; |
130 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg); |
131 | SSYNC(); |
132 | |
133 | /* Wait for complete */ |
134 | while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum))) |
135 | cpu_relax(); |
136 | |
137 | /* acknowledge dma interrupt */ |
138 | bfin_write_USB_DMA_INTERRUPT(1 << epnum); |
139 | SSYNC(); |
140 | |
141 | /* Reset DMA */ |
142 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0); |
143 | SSYNC(); |
144 | } else { |
145 | SSYNC(); |
146 | /* Read the last byte of packet with odd size from address fifo + 4 |
147 | * to trigger 1 byte access to EP0 FIFO. |
148 | */ |
149 | if (len == 1) |
150 | *dst = (u8)inw((unsigned long)fifo + 4); |
151 | else { |
152 | if (unlikely((unsigned long)dst & 0x01)) |
153 | insw_8((unsigned long)fifo, dst, len >> 1); |
154 | else |
155 | insw((unsigned long)fifo, dst, len >> 1); |
156 | |
157 | if (len & 0x01) |
158 | *(dst + len - 1) = (u8)inw((unsigned long)fifo + 4); |
159 | } |
160 | } |
161 | dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", |
162 | 'R', hw_ep->epnum, fifo, len, dst); |
163 | |
164 | dump_fifo_data(dst, len); |
165 | } |
166 | |
167 | static irqreturn_t blackfin_interrupt(int irq, void *__hci) |
168 | { |
169 | unsigned long flags; |
170 | irqreturn_t retval = IRQ_NONE; |
171 | struct musb *musb = __hci; |
172 | |
173 | spin_lock_irqsave(&musb->lock, flags); |
174 | |
175 | musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); |
176 | musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); |
177 | musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); |
178 | |
179 | if (musb->int_usb || musb->int_tx || musb->int_rx) { |
180 | musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb); |
181 | musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx); |
182 | musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx); |
183 | retval = musb_interrupt(musb); |
184 | } |
185 | |
186 | /* Start sampling ID pin, when plug is removed from MUSB */ |
187 | if ((musb->xceiv->state == OTG_STATE_B_IDLE |
188 | || musb->xceiv->state == OTG_STATE_A_WAIT_BCON) || |
189 | (musb->int_usb & MUSB_INTR_DISCONNECT && is_host_active(musb))) { |
190 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); |
191 | musb->a_wait_bcon = TIMER_DELAY; |
192 | } |
193 | |
194 | spin_unlock_irqrestore(&musb->lock, flags); |
195 | |
196 | return retval; |
197 | } |
198 | |
199 | static void musb_conn_timer_handler(unsigned long _musb) |
200 | { |
201 | struct musb *musb = (void *)_musb; |
202 | unsigned long flags; |
203 | u16 val; |
204 | static u8 toggle; |
205 | |
206 | spin_lock_irqsave(&musb->lock, flags); |
207 | switch (musb->xceiv->state) { |
208 | case OTG_STATE_A_IDLE: |
209 | case OTG_STATE_A_WAIT_BCON: |
210 | /* Start a new session */ |
211 | val = musb_readw(musb->mregs, MUSB_DEVCTL); |
212 | val &= ~MUSB_DEVCTL_SESSION; |
213 | musb_writew(musb->mregs, MUSB_DEVCTL, val); |
214 | val |= MUSB_DEVCTL_SESSION; |
215 | musb_writew(musb->mregs, MUSB_DEVCTL, val); |
216 | /* Check if musb is host or peripheral. */ |
217 | val = musb_readw(musb->mregs, MUSB_DEVCTL); |
218 | |
219 | if (!(val & MUSB_DEVCTL_BDEVICE)) { |
220 | gpio_set_value(musb->config->gpio_vrsel, 1); |
221 | musb->xceiv->state = OTG_STATE_A_WAIT_BCON; |
222 | } else { |
223 | gpio_set_value(musb->config->gpio_vrsel, 0); |
224 | /* Ignore VBUSERROR and SUSPEND IRQ */ |
225 | val = musb_readb(musb->mregs, MUSB_INTRUSBE); |
226 | val &= ~MUSB_INTR_VBUSERROR; |
227 | musb_writeb(musb->mregs, MUSB_INTRUSBE, val); |
228 | |
229 | val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR; |
230 | musb_writeb(musb->mregs, MUSB_INTRUSB, val); |
231 | musb->xceiv->state = OTG_STATE_B_IDLE; |
232 | } |
233 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); |
234 | break; |
235 | case OTG_STATE_B_IDLE: |
236 | /* |
237 | * Start a new session. It seems that MUSB needs taking |
238 | * some time to recognize the type of the plug inserted? |
239 | */ |
240 | val = musb_readw(musb->mregs, MUSB_DEVCTL); |
241 | val |= MUSB_DEVCTL_SESSION; |
242 | musb_writew(musb->mregs, MUSB_DEVCTL, val); |
243 | val = musb_readw(musb->mregs, MUSB_DEVCTL); |
244 | |
245 | if (!(val & MUSB_DEVCTL_BDEVICE)) { |
246 | gpio_set_value(musb->config->gpio_vrsel, 1); |
247 | musb->xceiv->state = OTG_STATE_A_WAIT_BCON; |
248 | } else { |
249 | gpio_set_value(musb->config->gpio_vrsel, 0); |
250 | |
251 | /* Ignore VBUSERROR and SUSPEND IRQ */ |
252 | val = musb_readb(musb->mregs, MUSB_INTRUSBE); |
253 | val &= ~MUSB_INTR_VBUSERROR; |
254 | musb_writeb(musb->mregs, MUSB_INTRUSBE, val); |
255 | |
256 | val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR; |
257 | musb_writeb(musb->mregs, MUSB_INTRUSB, val); |
258 | |
259 | /* Toggle the Soft Conn bit, so that we can response to |
260 | * the inserting of either A-plug or B-plug. |
261 | */ |
262 | if (toggle) { |
263 | val = musb_readb(musb->mregs, MUSB_POWER); |
264 | val &= ~MUSB_POWER_SOFTCONN; |
265 | musb_writeb(musb->mregs, MUSB_POWER, val); |
266 | toggle = 0; |
267 | } else { |
268 | val = musb_readb(musb->mregs, MUSB_POWER); |
269 | val |= MUSB_POWER_SOFTCONN; |
270 | musb_writeb(musb->mregs, MUSB_POWER, val); |
271 | toggle = 1; |
272 | } |
273 | /* The delay time is set to 1/4 second by default, |
274 | * shortening it, if accelerating A-plug detection |
275 | * is needed in OTG mode. |
276 | */ |
277 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY / 4); |
278 | } |
279 | break; |
280 | default: |
281 | dev_dbg(musb->controller, "%s state not handled\n", |
282 | usb_otg_state_string(musb->xceiv->state)); |
283 | break; |
284 | } |
285 | spin_unlock_irqrestore(&musb->lock, flags); |
286 | |
287 | dev_dbg(musb->controller, "state is %s\n", |
288 | usb_otg_state_string(musb->xceiv->state)); |
289 | } |
290 | |
291 | static void bfin_musb_enable(struct musb *musb) |
292 | { |
293 | /* REVISIT is this really correct ? */ |
294 | } |
295 | |
296 | static void bfin_musb_disable(struct musb *musb) |
297 | { |
298 | } |
299 | |
300 | static void bfin_musb_set_vbus(struct musb *musb, int is_on) |
301 | { |
302 | int value = musb->config->gpio_vrsel_active; |
303 | if (!is_on) |
304 | value = !value; |
305 | gpio_set_value(musb->config->gpio_vrsel, value); |
306 | |
307 | dev_dbg(musb->controller, "VBUS %s, devctl %02x " |
308 | /* otg %3x conf %08x prcm %08x */ "\n", |
309 | usb_otg_state_string(musb->xceiv->state), |
310 | musb_readb(musb->mregs, MUSB_DEVCTL)); |
311 | } |
312 | |
313 | static int bfin_musb_set_power(struct usb_phy *x, unsigned mA) |
314 | { |
315 | return 0; |
316 | } |
317 | |
318 | static int bfin_musb_vbus_status(struct musb *musb) |
319 | { |
320 | return 0; |
321 | } |
322 | |
323 | static int bfin_musb_set_mode(struct musb *musb, u8 musb_mode) |
324 | { |
325 | return -EIO; |
326 | } |
327 | |
328 | static int bfin_musb_adjust_channel_params(struct dma_channel *channel, |
329 | u16 packet_sz, u8 *mode, |
330 | dma_addr_t *dma_addr, u32 *len) |
331 | { |
332 | struct musb_dma_channel *musb_channel = channel->private_data; |
333 | |
334 | /* |
335 | * Anomaly 05000450 might cause data corruption when using DMA |
336 | * MODE 1 transmits with short packet. So to work around this, |
337 | * we truncate all MODE 1 transfers down to a multiple of the |
338 | * max packet size, and then do the last short packet transfer |
339 | * (if there is any) using MODE 0. |
340 | */ |
341 | if (ANOMALY_05000450) { |
342 | if (musb_channel->transmit && *mode == 1) |
343 | *len = *len - (*len % packet_sz); |
344 | } |
345 | |
346 | return 0; |
347 | } |
348 | |
349 | static void bfin_musb_reg_init(struct musb *musb) |
350 | { |
351 | if (ANOMALY_05000346) { |
352 | bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); |
353 | SSYNC(); |
354 | } |
355 | |
356 | if (ANOMALY_05000347) { |
357 | bfin_write_USB_APHY_CNTRL(0x0); |
358 | SSYNC(); |
359 | } |
360 | |
361 | /* Configure PLL oscillator register */ |
362 | bfin_write_USB_PLLOSC_CTRL(0x3080 | |
363 | ((480/musb->config->clkin) << 1)); |
364 | SSYNC(); |
365 | |
366 | bfin_write_USB_SRP_CLKDIV((get_sclk()/1000) / 32 - 1); |
367 | SSYNC(); |
368 | |
369 | bfin_write_USB_EP_NI0_RXMAXP(64); |
370 | SSYNC(); |
371 | |
372 | bfin_write_USB_EP_NI0_TXMAXP(64); |
373 | SSYNC(); |
374 | |
375 | /* Route INTRUSB/INTR_RX/INTR_TX to USB_INT0*/ |
376 | bfin_write_USB_GLOBINTR(0x7); |
377 | SSYNC(); |
378 | |
379 | bfin_write_USB_GLOBAL_CTL(GLOBAL_ENA | EP1_TX_ENA | EP2_TX_ENA | |
380 | EP3_TX_ENA | EP4_TX_ENA | EP5_TX_ENA | |
381 | EP6_TX_ENA | EP7_TX_ENA | EP1_RX_ENA | |
382 | EP2_RX_ENA | EP3_RX_ENA | EP4_RX_ENA | |
383 | EP5_RX_ENA | EP6_RX_ENA | EP7_RX_ENA); |
384 | SSYNC(); |
385 | } |
386 | |
387 | static int bfin_musb_init(struct musb *musb) |
388 | { |
389 | |
390 | /* |
391 | * Rev 1.0 BF549 EZ-KITs require PE7 to be high for both DEVICE |
392 | * and OTG HOST modes, while rev 1.1 and greater require PE7 to |
393 | * be low for DEVICE mode and high for HOST mode. We set it high |
394 | * here because we are in host mode |
395 | */ |
396 | |
397 | if (gpio_request(musb->config->gpio_vrsel, "USB_VRSEL")) { |
398 | printk(KERN_ERR "Failed ro request USB_VRSEL GPIO_%d\n", |
399 | musb->config->gpio_vrsel); |
400 | return -ENODEV; |
401 | } |
402 | gpio_direction_output(musb->config->gpio_vrsel, 0); |
403 | |
404 | usb_phy_generic_register(); |
405 | musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); |
406 | if (IS_ERR_OR_NULL(musb->xceiv)) { |
407 | gpio_free(musb->config->gpio_vrsel); |
408 | return -EPROBE_DEFER; |
409 | } |
410 | |
411 | bfin_musb_reg_init(musb); |
412 | |
413 | setup_timer(&musb_conn_timer, musb_conn_timer_handler, |
414 | (unsigned long) musb); |
415 | |
416 | musb->xceiv->set_power = bfin_musb_set_power; |
417 | |
418 | musb->isr = blackfin_interrupt; |
419 | musb->double_buffer_not_ok = true; |
420 | |
421 | return 0; |
422 | } |
423 | |
424 | static int bfin_musb_exit(struct musb *musb) |
425 | { |
426 | gpio_free(musb->config->gpio_vrsel); |
427 | |
428 | usb_put_phy(musb->xceiv); |
429 | usb_phy_generic_unregister(); |
430 | return 0; |
431 | } |
432 | |
433 | static const struct musb_platform_ops bfin_ops = { |
434 | .init = bfin_musb_init, |
435 | .exit = bfin_musb_exit, |
436 | |
437 | .enable = bfin_musb_enable, |
438 | .disable = bfin_musb_disable, |
439 | |
440 | .set_mode = bfin_musb_set_mode, |
441 | |
442 | .vbus_status = bfin_musb_vbus_status, |
443 | .set_vbus = bfin_musb_set_vbus, |
444 | |
445 | .adjust_channel_params = bfin_musb_adjust_channel_params, |
446 | }; |
447 | |
448 | static u64 bfin_dmamask = DMA_BIT_MASK(32); |
449 | |
450 | static int bfin_probe(struct platform_device *pdev) |
451 | { |
452 | struct resource musb_resources[2]; |
453 | struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); |
454 | struct platform_device *musb; |
455 | struct bfin_glue *glue; |
456 | |
457 | int ret = -ENOMEM; |
458 | |
459 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); |
460 | if (!glue) { |
461 | dev_err(&pdev->dev, "failed to allocate glue context\n"); |
462 | goto err0; |
463 | } |
464 | |
465 | musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); |
466 | if (!musb) { |
467 | dev_err(&pdev->dev, "failed to allocate musb device\n"); |
468 | goto err1; |
469 | } |
470 | |
471 | musb->dev.parent = &pdev->dev; |
472 | musb->dev.dma_mask = &bfin_dmamask; |
473 | musb->dev.coherent_dma_mask = bfin_dmamask; |
474 | |
475 | glue->dev = &pdev->dev; |
476 | glue->musb = musb; |
477 | |
478 | pdata->platform_ops = &bfin_ops; |
479 | |
480 | platform_set_drvdata(pdev, glue); |
481 | |
482 | memset(musb_resources, 0x00, sizeof(*musb_resources) * |
483 | ARRAY_SIZE(musb_resources)); |
484 | |
485 | musb_resources[0].name = pdev->resource[0].name; |
486 | musb_resources[0].start = pdev->resource[0].start; |
487 | musb_resources[0].end = pdev->resource[0].end; |
488 | musb_resources[0].flags = pdev->resource[0].flags; |
489 | |
490 | musb_resources[1].name = pdev->resource[1].name; |
491 | musb_resources[1].start = pdev->resource[1].start; |
492 | musb_resources[1].end = pdev->resource[1].end; |
493 | musb_resources[1].flags = pdev->resource[1].flags; |
494 | |
495 | ret = platform_device_add_resources(musb, musb_resources, |
496 | ARRAY_SIZE(musb_resources)); |
497 | if (ret) { |
498 | dev_err(&pdev->dev, "failed to add resources\n"); |
499 | goto err3; |
500 | } |
501 | |
502 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); |
503 | if (ret) { |
504 | dev_err(&pdev->dev, "failed to add platform_data\n"); |
505 | goto err3; |
506 | } |
507 | |
508 | ret = platform_device_add(musb); |
509 | if (ret) { |
510 | dev_err(&pdev->dev, "failed to register musb device\n"); |
511 | goto err3; |
512 | } |
513 | |
514 | return 0; |
515 | |
516 | err3: |
517 | platform_device_put(musb); |
518 | |
519 | err1: |
520 | kfree(glue); |
521 | |
522 | err0: |
523 | return ret; |
524 | } |
525 | |
526 | static int bfin_remove(struct platform_device *pdev) |
527 | { |
528 | struct bfin_glue *glue = platform_get_drvdata(pdev); |
529 | |
530 | platform_device_unregister(glue->musb); |
531 | kfree(glue); |
532 | |
533 | return 0; |
534 | } |
535 | |
536 | #ifdef CONFIG_PM |
537 | static int bfin_suspend(struct device *dev) |
538 | { |
539 | struct bfin_glue *glue = dev_get_drvdata(dev); |
540 | struct musb *musb = glue_to_musb(glue); |
541 | |
542 | if (is_host_active(musb)) |
543 | /* |
544 | * During hibernate gpio_vrsel will change from high to low |
545 | * low which will generate wakeup event resume the system |
546 | * immediately. Set it to 0 before hibernate to avoid this |
547 | * wakeup event. |
548 | */ |
549 | gpio_set_value(musb->config->gpio_vrsel, 0); |
550 | |
551 | return 0; |
552 | } |
553 | |
554 | static int bfin_resume(struct device *dev) |
555 | { |
556 | struct bfin_glue *glue = dev_get_drvdata(dev); |
557 | struct musb *musb = glue_to_musb(glue); |
558 | |
559 | bfin_musb_reg_init(musb); |
560 | |
561 | return 0; |
562 | } |
563 | #endif |
564 | |
565 | static SIMPLE_DEV_PM_OPS(bfin_pm_ops, bfin_suspend, bfin_resume); |
566 | |
567 | static struct platform_driver bfin_driver = { |
568 | .probe = bfin_probe, |
569 | .remove = __exit_p(bfin_remove), |
570 | .driver = { |
571 | .name = "musb-blackfin", |
572 | .pm = &bfin_pm_ops, |
573 | }, |
574 | }; |
575 | |
576 | MODULE_DESCRIPTION("Blackfin MUSB Glue Layer"); |
577 | MODULE_AUTHOR("Bryan Wy <cooloney@kernel.org>"); |
578 | MODULE_LICENSE("GPL v2"); |
579 | module_platform_driver(bfin_driver); |
580 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9