1
2
3
4
5
6
7
8
9#include <linux/module.h>
10#include <linux/kernel.h>
11#include <linux/slab.h>
12#include <linux/spinlock.h>
13#include <linux/platform_device.h>
14#include <linux/interrupt.h>
15#include <linux/iopoll.h>
16#include <linux/ioport.h>
17#include <linux/io.h>
18#include <linux/list.h>
19#include <linux/delay.h>
20#include <linux/dma-mapping.h>
21#include <linux/dmapool.h>
22#include <linux/of.h>
23#include <linux/phy/phy.h>
24#include <linux/moduleparam.h>
25#include <linux/usb/ch9.h>
26#include <linux/usb/gadget.h>
27#include <linux/clk.h>
28
29#include "bdc.h"
30#include "bdc_dbg.h"
31
32
33static int poll_oip(struct bdc *bdc, u32 usec)
34{
35 u32 status;
36 int ret;
37
38 ret = readl_poll_timeout(bdc->regs + BDC_BDCSC, status,
39 (BDC_CSTS(status) != BDC_OIP), 10, usec);
40 if (ret)
41 dev_err(bdc->dev, "operation timedout BDCSC: 0x%08x\n", status);
42 else
43 dev_dbg(bdc->dev, "%s complete status=%d", __func__, BDC_CSTS(status));
44
45 return ret;
46}
47
48
49int bdc_stop(struct bdc *bdc)
50{
51 int ret;
52 u32 temp;
53
54 dev_dbg(bdc->dev, "%s ()\n\n", __func__);
55 temp = bdc_readl(bdc->regs, BDC_BDCSC);
56
57 if (BDC_CSTS(temp) == BDC_HLT) {
58 dev_vdbg(bdc->dev, "BDC already halted\n");
59 return 0;
60 }
61 temp &= ~BDC_COP_MASK;
62 temp |= BDC_COS|BDC_COP_STP;
63 bdc_writel(bdc->regs, BDC_BDCSC, temp);
64
65 ret = poll_oip(bdc, BDC_COP_TIMEOUT);
66 if (ret)
67 dev_err(bdc->dev, "bdc stop operation failed");
68
69 return ret;
70}
71
72
73int bdc_reset(struct bdc *bdc)
74{
75 u32 temp;
76 int ret;
77
78 dev_dbg(bdc->dev, "%s ()\n", __func__);
79
80 ret = bdc_stop(bdc);
81 if (ret)
82 return ret;
83
84 temp = bdc_readl(bdc->regs, BDC_BDCSC);
85 temp &= ~BDC_COP_MASK;
86 temp |= BDC_COS|BDC_COP_RST;
87 bdc_writel(bdc->regs, BDC_BDCSC, temp);
88 ret = poll_oip(bdc, BDC_COP_TIMEOUT);
89 if (ret)
90 dev_err(bdc->dev, "bdc reset operation failed");
91
92 return ret;
93}
94
95
96int bdc_run(struct bdc *bdc)
97{
98 u32 temp;
99 int ret;
100
101 dev_dbg(bdc->dev, "%s ()\n", __func__);
102 temp = bdc_readl(bdc->regs, BDC_BDCSC);
103
104 if (BDC_CSTS(temp) == BDC_NOR) {
105 dev_warn(bdc->dev, "bdc is already in running state\n");
106 return 0;
107 }
108 temp &= ~BDC_COP_MASK;
109 temp |= BDC_COP_RUN;
110 temp |= BDC_COS;
111 bdc_writel(bdc->regs, BDC_BDCSC, temp);
112 ret = poll_oip(bdc, BDC_COP_TIMEOUT);
113 if (ret) {
114 dev_err(bdc->dev, "bdc run operation failed:%d", ret);
115 return ret;
116 }
117 temp = bdc_readl(bdc->regs, BDC_BDCSC);
118 if (BDC_CSTS(temp) != BDC_NOR) {
119 dev_err(bdc->dev, "bdc not in normal mode after RUN op :%d\n",
120 BDC_CSTS(temp));
121 return -ESHUTDOWN;
122 }
123
124 return 0;
125}
126
127
128
129
130
131void bdc_softconn(struct bdc *bdc)
132{
133 u32 uspc;
134
135 uspc = bdc_readl(bdc->regs, BDC_USPC);
136 uspc &= ~BDC_PST_MASK;
137 uspc |= BDC_LINK_STATE_RX_DET;
138 uspc |= BDC_SWS;
139 dev_dbg(bdc->dev, "%s () uspc=%08x\n", __func__, uspc);
140 bdc_writel(bdc->regs, BDC_USPC, uspc);
141}
142
143
144void bdc_softdisconn(struct bdc *bdc)
145{
146 u32 uspc;
147
148 uspc = bdc_readl(bdc->regs, BDC_USPC);
149 uspc |= BDC_SDC;
150 uspc &= ~BDC_SCN;
151 dev_dbg(bdc->dev, "%s () uspc=%x\n", __func__, uspc);
152 bdc_writel(bdc->regs, BDC_USPC, uspc);
153}
154
155
156static int scratchpad_setup(struct bdc *bdc)
157{
158 int sp_buff_size;
159 u32 low32;
160 u32 upp32;
161
162 sp_buff_size = BDC_SPB(bdc_readl(bdc->regs, BDC_BDCCFG0));
163 dev_dbg(bdc->dev, "%s() sp_buff_size=%d\n", __func__, sp_buff_size);
164 if (!sp_buff_size) {
165 dev_dbg(bdc->dev, "Scratchpad buffer not needed\n");
166 return 0;
167 }
168
169 sp_buff_size = 1 << (sp_buff_size + 5);
170 dev_dbg(bdc->dev, "Allocating %d bytes for scratchpad\n", sp_buff_size);
171 bdc->scratchpad.buff = dma_alloc_coherent(bdc->dev, sp_buff_size,
172 &bdc->scratchpad.sp_dma,
173 GFP_KERNEL);
174
175 if (!bdc->scratchpad.buff)
176 goto fail;
177
178 bdc->sp_buff_size = sp_buff_size;
179 bdc->scratchpad.size = sp_buff_size;
180 low32 = lower_32_bits(bdc->scratchpad.sp_dma);
181 upp32 = upper_32_bits(bdc->scratchpad.sp_dma);
182 cpu_to_le32s(&low32);
183 cpu_to_le32s(&upp32);
184 bdc_writel(bdc->regs, BDC_SPBBAL, low32);
185 bdc_writel(bdc->regs, BDC_SPBBAH, upp32);
186 return 0;
187
188fail:
189 bdc->scratchpad.buff = NULL;
190
191 return -ENOMEM;
192}
193
194
195static int setup_srr(struct bdc *bdc, int interrupter)
196{
197 dev_dbg(bdc->dev, "%s() NUM_SR_ENTRIES:%d\n", __func__, NUM_SR_ENTRIES);
198
199 bdc_writel(bdc->regs, BDC_SRRINT(0), BDC_SRR_RWS | BDC_SRR_RST);
200 bdc->srr.dqp_index = 0;
201
202 bdc->srr.sr_bds = dma_alloc_coherent(bdc->dev,
203 NUM_SR_ENTRIES * sizeof(struct bdc_bd),
204 &bdc->srr.dma_addr, GFP_KERNEL);
205 if (!bdc->srr.sr_bds)
206 return -ENOMEM;
207
208 return 0;
209}
210
211
212static void bdc_mem_init(struct bdc *bdc, bool reinit)
213{
214 u8 size = 0;
215 u32 usb2_pm;
216 u32 low32;
217 u32 upp32;
218 u32 temp;
219
220 dev_dbg(bdc->dev, "%s ()\n", __func__);
221 bdc->ep0_state = WAIT_FOR_SETUP;
222 bdc->dev_addr = 0;
223 bdc->srr.eqp_index = 0;
224 bdc->srr.dqp_index = 0;
225 bdc->zlp_needed = false;
226 bdc->delayed_status = false;
227
228 bdc_writel(bdc->regs, BDC_SPBBAL, bdc->scratchpad.sp_dma);
229
230 temp = BDC_SRR_RWS | BDC_SRR_RST;
231
232 bdc_writel(bdc->regs, BDC_SRRINT(0), temp);
233 dev_dbg(bdc->dev, "bdc->srr.sr_bds =%p\n", bdc->srr.sr_bds);
234 temp = lower_32_bits(bdc->srr.dma_addr);
235 size = fls(NUM_SR_ENTRIES) - 2;
236 temp |= size;
237 dev_dbg(bdc->dev, "SRRBAL[0]=%08x NUM_SR_ENTRIES:%d size:%d\n",
238 temp, NUM_SR_ENTRIES, size);
239
240 low32 = lower_32_bits(temp);
241 upp32 = upper_32_bits(bdc->srr.dma_addr);
242 cpu_to_le32s(&low32);
243 cpu_to_le32s(&upp32);
244
245
246 bdc_writel(bdc->regs, BDC_SRRBAL(0), low32);
247 bdc_writel(bdc->regs, BDC_SRRBAH(0), upp32);
248
249 temp = bdc_readl(bdc->regs, BDC_SRRINT(0));
250 temp |= BDC_SRR_IE;
251 temp &= ~(BDC_SRR_RST | BDC_SRR_RWS);
252 bdc_writel(bdc->regs, BDC_SRRINT(0), temp);
253
254
255 temp = bdc_readl(bdc->regs, BDC_INTCTLS(0));
256 temp &= ~0xffff;
257 temp |= INT_CLS;
258 bdc_writel(bdc->regs, BDC_INTCTLS(0), temp);
259
260 usb2_pm = bdc_readl(bdc->regs, BDC_USPPM2);
261 dev_dbg(bdc->dev, "usb2_pm=%08x", usb2_pm);
262
263 usb2_pm |= BDC_HLE;
264 bdc_writel(bdc->regs, BDC_USPPM2, usb2_pm);
265
266
267 usb2_pm = bdc_readl(bdc->regs, BDC_USPPM2);
268 dev_dbg(bdc->dev, "usb2_pm=%08x\n", usb2_pm);
269
270
271 temp = bdc_readl(bdc->regs, BDC_BDCSC);
272
273 temp |= BDC_MASK_MCW;
274 bdc_writel(bdc->regs, BDC_BDCSC, temp);
275
276
277
278
279
280 if (reinit) {
281 int i;
282
283 temp = bdc_readl(bdc->regs, BDC_BDCSC);
284 temp |= BDC_GIE;
285 bdc_writel(bdc->regs, BDC_BDCSC, temp);
286
287 memset(bdc->scratchpad.buff, 0, bdc->sp_buff_size);
288
289 memset(bdc->srr.sr_bds, 0,
290 NUM_SR_ENTRIES * sizeof(struct bdc_bd));
291
292
293
294
295 if (!bdc->gadget.speed)
296 for (i = 1; i < bdc->num_eps; ++i)
297 bdc->bdc_ep_array[i]->flags = 0;
298 } else {
299
300
301 bdc->sr_handler[0] = bdc_sr_xsf;
302 bdc->sr_handler[1] = bdc_sr_uspc;
303
304
305 bdc->sr_xsf_ep0[0] = bdc_xsf_ep0_setup_recv;
306 bdc->sr_xsf_ep0[1] = bdc_xsf_ep0_data_start;
307 bdc->sr_xsf_ep0[2] = bdc_xsf_ep0_status_start;
308 }
309}
310
311
312static void bdc_mem_free(struct bdc *bdc)
313{
314 dev_dbg(bdc->dev, "%s\n", __func__);
315
316 if (bdc->srr.sr_bds)
317 dma_free_coherent(bdc->dev,
318 NUM_SR_ENTRIES * sizeof(struct bdc_bd),
319 bdc->srr.sr_bds, bdc->srr.dma_addr);
320
321
322 if (bdc->scratchpad.buff)
323 dma_free_coherent(bdc->dev, bdc->sp_buff_size,
324 bdc->scratchpad.buff, bdc->scratchpad.sp_dma);
325
326
327 dma_pool_destroy(bdc->bd_table_pool);
328
329
330 kfree(bdc->bdc_ep_array);
331
332 bdc->srr.sr_bds = NULL;
333 bdc->scratchpad.buff = NULL;
334 bdc->bd_table_pool = NULL;
335 bdc->bdc_ep_array = NULL;
336}
337
338
339
340
341
342int bdc_reinit(struct bdc *bdc)
343{
344 int ret;
345
346 dev_dbg(bdc->dev, "%s\n", __func__);
347 ret = bdc_stop(bdc);
348 if (ret)
349 goto out;
350
351 ret = bdc_reset(bdc);
352 if (ret)
353 goto out;
354
355
356 bdc_mem_init(bdc, true);
357 ret = bdc_run(bdc);
358out:
359 bdc->reinit = false;
360
361 return ret;
362}
363
364
365static int bdc_mem_alloc(struct bdc *bdc)
366{
367 u32 page_size;
368 unsigned int num_ieps, num_oeps;
369
370 dev_dbg(bdc->dev,
371 "%s() NUM_BDS_PER_TABLE:%d\n", __func__,
372 NUM_BDS_PER_TABLE);
373 page_size = BDC_PGS(bdc_readl(bdc->regs, BDC_BDCCFG0));
374
375 page_size = 1 << page_size;
376
377 page_size <<= 10;
378 dev_dbg(bdc->dev, "page_size=%d\n", page_size);
379
380
381 bdc->bd_table_pool =
382 dma_pool_create("BDC BD tables", bdc->dev, NUM_BDS_PER_TABLE * 16,
383 16, page_size);
384
385 if (!bdc->bd_table_pool)
386 goto fail;
387
388 if (scratchpad_setup(bdc))
389 goto fail;
390
391
392 num_ieps = NUM_NCS(bdc_readl(bdc->regs, BDC_FSCNIC));
393 num_oeps = NUM_NCS(bdc_readl(bdc->regs, BDC_FSCNOC));
394
395 bdc->num_eps = num_ieps + num_oeps + 2;
396 dev_dbg(bdc->dev,
397 "ieps:%d eops:%d num_eps:%d\n",
398 num_ieps, num_oeps, bdc->num_eps);
399
400 bdc->bdc_ep_array = kcalloc(bdc->num_eps, sizeof(struct bdc_ep *),
401 GFP_KERNEL);
402 if (!bdc->bdc_ep_array)
403 goto fail;
404
405 dev_dbg(bdc->dev, "Allocating sr report0\n");
406 if (setup_srr(bdc, 0))
407 goto fail;
408
409 return 0;
410fail:
411 dev_warn(bdc->dev, "Couldn't initialize memory\n");
412 bdc_mem_free(bdc);
413
414 return -ENOMEM;
415}
416
417
418static void bdc_hw_exit(struct bdc *bdc)
419{
420 dev_dbg(bdc->dev, "%s ()\n", __func__);
421 bdc_mem_free(bdc);
422}
423
424
425static int bdc_hw_init(struct bdc *bdc)
426{
427 int ret;
428
429 dev_dbg(bdc->dev, "%s ()\n", __func__);
430 ret = bdc_reset(bdc);
431 if (ret) {
432 dev_err(bdc->dev, "err resetting bdc abort bdc init%d\n", ret);
433 return ret;
434 }
435 ret = bdc_mem_alloc(bdc);
436 if (ret) {
437 dev_err(bdc->dev, "Mem alloc failed, aborting\n");
438 return -ENOMEM;
439 }
440 bdc_mem_init(bdc, 0);
441 bdc_dbg_regs(bdc);
442 dev_dbg(bdc->dev, "HW Init done\n");
443
444 return 0;
445}
446
447static int bdc_phy_init(struct bdc *bdc)
448{
449 int phy_num;
450 int ret;
451
452 for (phy_num = 0; phy_num < bdc->num_phys; phy_num++) {
453 ret = phy_init(bdc->phys[phy_num]);
454 if (ret)
455 goto err_exit_phy;
456 ret = phy_power_on(bdc->phys[phy_num]);
457 if (ret) {
458 phy_exit(bdc->phys[phy_num]);
459 goto err_exit_phy;
460 }
461 }
462
463 return 0;
464
465err_exit_phy:
466 while (--phy_num >= 0) {
467 phy_power_off(bdc->phys[phy_num]);
468 phy_exit(bdc->phys[phy_num]);
469 }
470
471 return ret;
472}
473
474static void bdc_phy_exit(struct bdc *bdc)
475{
476 int phy_num;
477
478 for (phy_num = 0; phy_num < bdc->num_phys; phy_num++) {
479 phy_power_off(bdc->phys[phy_num]);
480 phy_exit(bdc->phys[phy_num]);
481 }
482}
483
484static int bdc_probe(struct platform_device *pdev)
485{
486 struct bdc *bdc;
487 int ret;
488 int irq;
489 u32 temp;
490 struct device *dev = &pdev->dev;
491 int phy_num;
492
493 dev_dbg(dev, "%s()\n", __func__);
494
495 bdc = devm_kzalloc(dev, sizeof(*bdc), GFP_KERNEL);
496 if (!bdc)
497 return -ENOMEM;
498
499 bdc->regs = devm_platform_ioremap_resource(pdev, 0);
500 if (IS_ERR(bdc->regs))
501 return PTR_ERR(bdc->regs);
502
503 irq = platform_get_irq(pdev, 0);
504 if (irq < 0)
505 return irq;
506 spin_lock_init(&bdc->lock);
507 platform_set_drvdata(pdev, bdc);
508 bdc->irq = irq;
509 bdc->dev = dev;
510 dev_dbg(dev, "bdc->regs: %p irq=%d\n", bdc->regs, bdc->irq);
511
512 bdc->num_phys = of_count_phandle_with_args(dev->of_node,
513 "phys", "#phy-cells");
514 if (bdc->num_phys > 0) {
515 bdc->phys = devm_kcalloc(dev, bdc->num_phys,
516 sizeof(struct phy *), GFP_KERNEL);
517 if (!bdc->phys)
518 return -ENOMEM;
519 } else {
520 bdc->num_phys = 0;
521 }
522 dev_info(dev, "Using %d phy(s)\n", bdc->num_phys);
523
524 for (phy_num = 0; phy_num < bdc->num_phys; phy_num++) {
525 bdc->phys[phy_num] = devm_of_phy_get_by_index(
526 dev, dev->of_node, phy_num);
527 if (IS_ERR(bdc->phys[phy_num])) {
528 ret = PTR_ERR(bdc->phys[phy_num]);
529 dev_err(bdc->dev,
530 "BDC phy specified but not found:%d\n", ret);
531 return ret;
532 }
533 }
534
535 bdc->clk = devm_clk_get_optional(dev, "sw_usbd");
536 if (IS_ERR(bdc->clk))
537 return PTR_ERR(bdc->clk);
538
539 ret = clk_prepare_enable(bdc->clk);
540 if (ret) {
541 dev_err(dev, "could not enable clock\n");
542 return ret;
543 }
544
545 ret = bdc_phy_init(bdc);
546 if (ret) {
547 dev_err(bdc->dev, "BDC phy init failure:%d\n", ret);
548 goto disable_clk;
549 }
550
551 temp = bdc_readl(bdc->regs, BDC_BDCCAP1);
552 if ((temp & BDC_P64) &&
553 !dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
554 dev_dbg(dev, "Using 64-bit address\n");
555 } else {
556 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
557 if (ret) {
558 dev_err(dev,
559 "No suitable DMA config available, abort\n");
560 ret = -ENOTSUPP;
561 goto phycleanup;
562 }
563 dev_dbg(dev, "Using 32-bit address\n");
564 }
565 ret = bdc_hw_init(bdc);
566 if (ret) {
567 dev_err(dev, "BDC init failure:%d\n", ret);
568 goto phycleanup;
569 }
570 ret = bdc_udc_init(bdc);
571 if (ret) {
572 dev_err(dev, "BDC Gadget init failure:%d\n", ret);
573 goto cleanup;
574 }
575 return 0;
576
577cleanup:
578 bdc_hw_exit(bdc);
579phycleanup:
580 bdc_phy_exit(bdc);
581disable_clk:
582 clk_disable_unprepare(bdc->clk);
583 return ret;
584}
585
586static int bdc_remove(struct platform_device *pdev)
587{
588 struct bdc *bdc;
589
590 bdc = platform_get_drvdata(pdev);
591 dev_dbg(bdc->dev, "%s ()\n", __func__);
592 bdc_udc_exit(bdc);
593 bdc_hw_exit(bdc);
594 bdc_phy_exit(bdc);
595 clk_disable_unprepare(bdc->clk);
596 return 0;
597}
598
599#ifdef CONFIG_PM_SLEEP
600static int bdc_suspend(struct device *dev)
601{
602 struct bdc *bdc = dev_get_drvdata(dev);
603 int ret;
604
605
606 ret = bdc_stop(bdc);
607 if (!ret)
608 clk_disable_unprepare(bdc->clk);
609
610 return ret;
611}
612
613static int bdc_resume(struct device *dev)
614{
615 struct bdc *bdc = dev_get_drvdata(dev);
616 int ret;
617
618 ret = clk_prepare_enable(bdc->clk);
619 if (ret) {
620 dev_err(bdc->dev, "err enabling the clock\n");
621 return ret;
622 }
623 ret = bdc_reinit(bdc);
624 if (ret) {
625 dev_err(bdc->dev, "err in bdc reinit\n");
626 return ret;
627 }
628
629 return 0;
630}
631
632#endif
633
634static SIMPLE_DEV_PM_OPS(bdc_pm_ops, bdc_suspend,
635 bdc_resume);
636
637static const struct of_device_id bdc_of_match[] = {
638 { .compatible = "brcm,bdc-udc-v2" },
639 { .compatible = "brcm,bdc" },
640 { }
641};
642
643static struct platform_driver bdc_driver = {
644 .driver = {
645 .name = BRCM_BDC_NAME,
646 .pm = &bdc_pm_ops,
647 .of_match_table = bdc_of_match,
648 },
649 .probe = bdc_probe,
650 .remove = bdc_remove,
651};
652
653module_platform_driver(bdc_driver);
654MODULE_AUTHOR("Ashwini Pahuja <ashwini.linux@gmail.com>");
655MODULE_LICENSE("GPL");
656MODULE_DESCRIPTION(BRCM_BDC_DESC);
657