blob: ccb9c213cc9f7e5b1ba958b9451df218fe3334bc [file] [log] [blame]
Ashwini Pahujaefed4212014-11-13 10:22:32 -08001/*
2 * bdc_core.c - BRCM BDC USB3.0 device controller core operations
3 *
4 * Copyright (C) 2014 Broadcom Corporation
5 *
6 * Author: Ashwini Pahuja
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/slab.h>
17#include <linux/spinlock.h>
18#include <linux/platform_device.h>
19#include <linux/interrupt.h>
20#include <linux/ioport.h>
21#include <linux/io.h>
22#include <linux/list.h>
23#include <linux/delay.h>
24#include <linux/dma-mapping.h>
25#include <linux/dmapool.h>
26#include <linux/of.h>
27#include <linux/moduleparam.h>
28#include <linux/usb/ch9.h>
29#include <linux/usb/gadget.h>
30
31#include "bdc.h"
32#include "bdc_dbg.h"
33
34/* Poll till controller status is not OIP */
35static int poll_oip(struct bdc *bdc, int usec)
36{
37 u32 status;
38 /* Poll till STS!= OIP */
39 while (usec) {
40 status = bdc_readl(bdc->regs, BDC_BDCSC);
41 if (BDC_CSTS(status) != BDC_OIP) {
42 dev_dbg(bdc->dev,
43 "poll_oip complete status=%d",
44 BDC_CSTS(status));
45 return 0;
46 }
47 udelay(10);
48 usec -= 10;
49 }
50 dev_err(bdc->dev, "Err: operation timedout BDCSC: 0x%08x\n", status);
51
52 return -ETIMEDOUT;
53}
54
55/* Stop the BDC controller */
56int bdc_stop(struct bdc *bdc)
57{
58 int ret;
59 u32 temp;
60
61 dev_dbg(bdc->dev, "%s ()\n\n", __func__);
62 temp = bdc_readl(bdc->regs, BDC_BDCSC);
63 /* Check if BDC is already halted */
64 if (BDC_CSTS(temp) == BDC_HLT) {
65 dev_vdbg(bdc->dev, "BDC already halted\n");
66 return 0;
67 }
68 temp &= ~BDC_COP_MASK;
69 temp |= BDC_COS|BDC_COP_STP;
70 bdc_writel(bdc->regs, BDC_BDCSC, temp);
71
72 ret = poll_oip(bdc, BDC_COP_TIMEOUT);
73 if (ret)
74 dev_err(bdc->dev, "bdc stop operation failed");
75
76 return ret;
77}
78
79/* Issue a reset to BDC controller */
80int bdc_reset(struct bdc *bdc)
81{
82 u32 temp;
83 int ret;
84
85 dev_dbg(bdc->dev, "%s ()\n", __func__);
86 /* First halt the controller */
87 ret = bdc_stop(bdc);
88 if (ret)
89 return ret;
90
91 temp = bdc_readl(bdc->regs, BDC_BDCSC);
92 temp &= ~BDC_COP_MASK;
93 temp |= BDC_COS|BDC_COP_RST;
94 bdc_writel(bdc->regs, BDC_BDCSC, temp);
95 ret = poll_oip(bdc, BDC_COP_TIMEOUT);
96 if (ret)
97 dev_err(bdc->dev, "bdc reset operation failed");
98
99 return ret;
100}
101
102/* Run the BDC controller */
103int bdc_run(struct bdc *bdc)
104{
105 u32 temp;
106 int ret;
107
108 dev_dbg(bdc->dev, "%s ()\n", __func__);
109 temp = bdc_readl(bdc->regs, BDC_BDCSC);
110 /* if BDC is already in running state then do not do anything */
111 if (BDC_CSTS(temp) == BDC_NOR) {
112 dev_warn(bdc->dev, "bdc is already in running state\n");
113 return 0;
114 }
115 temp &= ~BDC_COP_MASK;
116 temp |= BDC_COP_RUN;
117 temp |= BDC_COS;
118 bdc_writel(bdc->regs, BDC_BDCSC, temp);
119 ret = poll_oip(bdc, BDC_COP_TIMEOUT);
120 if (ret) {
121 dev_err(bdc->dev, "bdc run operation failed:%d", ret);
122 return ret;
123 }
124 temp = bdc_readl(bdc->regs, BDC_BDCSC);
125 if (BDC_CSTS(temp) != BDC_NOR) {
126 dev_err(bdc->dev, "bdc not in normal mode after RUN op :%d\n",
127 BDC_CSTS(temp));
128 return -ESHUTDOWN;
129 }
130
131 return 0;
132}
133
134/*
135 * Present the termination to the host, typically called from upstream port
136 * event with Vbus present =1
137 */
138void bdc_softconn(struct bdc *bdc)
139{
140 u32 uspc;
141
142 uspc = bdc_readl(bdc->regs, BDC_USPC);
143 uspc &= ~BDC_PST_MASK;
144 uspc |= BDC_LINK_STATE_RX_DET;
145 uspc |= BDC_SWS;
146 dev_dbg(bdc->dev, "%s () uspc=%08x\n", __func__, uspc);
147 bdc_writel(bdc->regs, BDC_USPC, uspc);
148}
149
150/* Remove the termination */
151void bdc_softdisconn(struct bdc *bdc)
152{
153 u32 uspc;
154
155 uspc = bdc_readl(bdc->regs, BDC_USPC);
156 uspc |= BDC_SDC;
157 uspc &= ~BDC_SCN;
158 dev_dbg(bdc->dev, "%s () uspc=%x\n", __func__, uspc);
159 bdc_writel(bdc->regs, BDC_USPC, uspc);
160}
161
162/* Set up the scratchpad buffer array and scratchpad buffers, if needed. */
163static int scratchpad_setup(struct bdc *bdc)
164{
165 int sp_buff_size;
166 u32 low32;
167 u32 upp32;
168
169 sp_buff_size = BDC_SPB(bdc_readl(bdc->regs, BDC_BDCCFG0));
170 dev_dbg(bdc->dev, "%s() sp_buff_size=%d\n", __func__, sp_buff_size);
171 if (!sp_buff_size) {
172 dev_dbg(bdc->dev, "Scratchpad buffer not needed\n");
173 return 0;
174 }
175 /* Refer to BDC spec, Table 4 for description of SPB */
176 sp_buff_size = 1 << (sp_buff_size + 5);
177 dev_dbg(bdc->dev, "Allocating %d bytes for scratchpad\n", sp_buff_size);
178 bdc->scratchpad.buff = dma_zalloc_coherent(bdc->dev, sp_buff_size,
179 &bdc->scratchpad.sp_dma, GFP_KERNEL);
180
181 if (!bdc->scratchpad.buff)
182 goto fail;
183
184 bdc->sp_buff_size = sp_buff_size;
185 bdc->scratchpad.size = sp_buff_size;
186 low32 = lower_32_bits(bdc->scratchpad.sp_dma);
187 upp32 = upper_32_bits(bdc->scratchpad.sp_dma);
188 cpu_to_le32s(&low32);
189 cpu_to_le32s(&upp32);
190 bdc_writel(bdc->regs, BDC_SPBBAL, low32);
191 bdc_writel(bdc->regs, BDC_SPBBAH, upp32);
192 return 0;
193
194fail:
195 bdc->scratchpad.buff = NULL;
196
197 return -ENOMEM;
198}
199
200/* Allocate the status report ring */
201static int setup_srr(struct bdc *bdc, int interrupter)
202{
203 dev_dbg(bdc->dev, "%s() NUM_SR_ENTRIES:%d\n", __func__, NUM_SR_ENTRIES);
204 /* Reset the SRR */
205 bdc_writel(bdc->regs, BDC_SRRINT(0), BDC_SRR_RWS | BDC_SRR_RST);
206 bdc->srr.dqp_index = 0;
207 /* allocate the status report descriptors */
208 bdc->srr.sr_bds = dma_zalloc_coherent(
209 bdc->dev,
210 NUM_SR_ENTRIES * sizeof(struct bdc_bd),
211 &bdc->srr.dma_addr,
212 GFP_KERNEL);
213 if (!bdc->srr.sr_bds)
214 return -ENOMEM;
215
216 return 0;
217}
218
219/* Initialize the HW regs and internal data structures */
220static void bdc_mem_init(struct bdc *bdc, bool reinit)
221{
222 u8 size = 0;
223 u32 usb2_pm;
224 u32 low32;
225 u32 upp32;
226 u32 temp;
227
228 dev_dbg(bdc->dev, "%s ()\n", __func__);
229 bdc->ep0_state = WAIT_FOR_SETUP;
230 bdc->dev_addr = 0;
231 bdc->srr.eqp_index = 0;
232 bdc->srr.dqp_index = 0;
233 bdc->zlp_needed = false;
234 bdc->delayed_status = false;
235
236 bdc_writel(bdc->regs, BDC_SPBBAL, bdc->scratchpad.sp_dma);
237 /* Init the SRR */
238 temp = BDC_SRR_RWS | BDC_SRR_RST;
239 /* Reset the SRR */
240 bdc_writel(bdc->regs, BDC_SRRINT(0), temp);
241 dev_dbg(bdc->dev, "bdc->srr.sr_bds =%p\n", bdc->srr.sr_bds);
242 temp = lower_32_bits(bdc->srr.dma_addr);
243 size = fls(NUM_SR_ENTRIES) - 2;
244 temp |= size;
245 dev_dbg(bdc->dev, "SRRBAL[0]=%08x NUM_SR_ENTRIES:%d size:%d\n",
246 temp, NUM_SR_ENTRIES, size);
247
248 low32 = lower_32_bits(temp);
249 upp32 = upper_32_bits(bdc->srr.dma_addr);
250 cpu_to_le32s(&low32);
251 cpu_to_le32s(&upp32);
252
253 /* Write the dma addresses into regs*/
254 bdc_writel(bdc->regs, BDC_SRRBAL(0), low32);
255 bdc_writel(bdc->regs, BDC_SRRBAH(0), upp32);
256
257 temp = bdc_readl(bdc->regs, BDC_SRRINT(0));
258 temp |= BDC_SRR_IE;
259 temp &= ~(BDC_SRR_RST | BDC_SRR_RWS);
260 bdc_writel(bdc->regs, BDC_SRRINT(0), temp);
261
262 /* Set the Interrupt Coalescence ~500 usec */
263 temp = bdc_readl(bdc->regs, BDC_INTCTLS(0));
264 temp &= ~0xffff;
265 temp |= INT_CLS;
266 bdc_writel(bdc->regs, BDC_INTCTLS(0), temp);
267
268 usb2_pm = bdc_readl(bdc->regs, BDC_USPPM2);
269 dev_dbg(bdc->dev, "usb2_pm=%08x", usb2_pm);
270 /* Enable hardware LPM Enable */
271 usb2_pm |= BDC_HLE;
272 bdc_writel(bdc->regs, BDC_USPPM2, usb2_pm);
273
274 /* readback for debug */
275 usb2_pm = bdc_readl(bdc->regs, BDC_USPPM2);
276 dev_dbg(bdc->dev, "usb2_pm=%08x\n", usb2_pm);
277
278 /* Disable any unwanted SR's on SRR */
279 temp = bdc_readl(bdc->regs, BDC_BDCSC);
280 /* We don't want Microframe counter wrap SR */
281 temp |= BDC_MASK_MCW;
282 bdc_writel(bdc->regs, BDC_BDCSC, temp);
283
284 /*
285 * In some error cases, driver has to reset the entire BDC controller
286 * in that case reinit is passed as 1
287 */
288 if (reinit) {
289 /* Enable interrupts */
290 temp = bdc_readl(bdc->regs, BDC_BDCSC);
291 temp |= BDC_GIE;
292 bdc_writel(bdc->regs, BDC_BDCSC, temp);
293 /* Init scratchpad to 0 */
294 memset(bdc->scratchpad.buff, 0, bdc->sp_buff_size);
295 /* Initialize SRR to 0 */
296 memset(bdc->srr.sr_bds, 0,
297 NUM_SR_ENTRIES * sizeof(struct bdc_bd));
298 } else {
299 /* One time initiaization only */
300 /* Enable status report function pointers */
301 bdc->sr_handler[0] = bdc_sr_xsf;
302 bdc->sr_handler[1] = bdc_sr_uspc;
303
304 /* EP0 status report function pointers */
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/* Free the dynamic memory */
312static void bdc_mem_free(struct bdc *bdc)
313{
314 dev_dbg(bdc->dev, "%s\n", __func__);
315 /* Free SRR */
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 /* Free scratchpad */
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 /* Destroy the dma pools */
Julia Lawall51b91b72015-09-13 14:15:09 +0200327 dma_pool_destroy(bdc->bd_table_pool);
Ashwini Pahujaefed4212014-11-13 10:22:32 -0800328
329 /* Free the bdc_ep array */
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 * bdc reinit gives a controller reset and reinitialize the registers,
340 * called from disconnect/bus reset scenario's, to ensure proper HW cleanup
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 /* the reinit flag is 1 */
356 bdc_mem_init(bdc, true);
357 ret = bdc_run(bdc);
358out:
359 bdc->reinit = false;
360
361 return ret;
362}
363
364/* Allocate all the dyanmic memory */
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 /* page size is 2^pgs KB */
375 page_size = 1 << page_size;
376 /* KB */
377 page_size <<= 10;
378 dev_dbg(bdc->dev, "page_size=%d\n", page_size);
379
380 /* Create a pool of bd tables */
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 /* read from regs */
392 num_ieps = NUM_NCS(bdc_readl(bdc->regs, BDC_FSCNIC));
393 num_oeps = NUM_NCS(bdc_readl(bdc->regs, BDC_FSCNOC));
394 /* +2: 1 for ep0 and the other is rsvd i.e. bdc_ep[0] is rsvd */
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 /* allocate array of ep pointers */
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/* opposite to bdc_hw_init */
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/* Initialize the bdc HW and memory */
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_probe(struct platform_device *pdev)
448{
449 struct bdc *bdc;
450 struct resource *res;
451 int ret = -ENOMEM;
452 int irq;
453 u32 temp;
454 struct device *dev = &pdev->dev;
455
456 dev_dbg(dev, "%s()\n", __func__);
457 bdc = devm_kzalloc(dev, sizeof(*bdc), GFP_KERNEL);
458 if (!bdc)
459 return -ENOMEM;
460
461 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
462 bdc->regs = devm_ioremap_resource(dev, res);
463 if (IS_ERR(bdc->regs)) {
464 dev_err(dev, "ioremap error\n");
465 return -ENOMEM;
466 }
467 irq = platform_get_irq(pdev, 0);
468 if (irq < 0) {
469 dev_err(dev, "platform_get_irq failed:%d\n", irq);
470 return irq;
471 }
472 spin_lock_init(&bdc->lock);
473 platform_set_drvdata(pdev, bdc);
474 bdc->irq = irq;
475 bdc->dev = dev;
476 dev_dbg(bdc->dev, "bdc->regs: %p irq=%d\n", bdc->regs, bdc->irq);
477
478 temp = bdc_readl(bdc->regs, BDC_BDCSC);
479 if ((temp & BDC_P64) &&
480 !dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
481 dev_dbg(bdc->dev, "Using 64-bit address\n");
482 } else {
483 ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
484 if (ret) {
485 dev_err(bdc->dev, "No suitable DMA config available, abort\n");
486 return -ENOTSUPP;
487 }
488 dev_dbg(bdc->dev, "Using 32-bit address\n");
489 }
490 ret = bdc_hw_init(bdc);
491 if (ret) {
492 dev_err(bdc->dev, "BDC init failure:%d\n", ret);
493 return ret;
494 }
495 ret = bdc_udc_init(bdc);
496 if (ret) {
497 dev_err(bdc->dev, "BDC Gadget init failure:%d\n", ret);
498 goto cleanup;
499 }
500 return 0;
501
502cleanup:
503 bdc_hw_exit(bdc);
504
505 return ret;
506}
507
508static int bdc_remove(struct platform_device *pdev)
509{
510 struct bdc *bdc;
511
512 bdc = platform_get_drvdata(pdev);
513 dev_dbg(bdc->dev, "%s ()\n", __func__);
514 bdc_udc_exit(bdc);
515 bdc_hw_exit(bdc);
516
517 return 0;
518}
519
520static struct platform_driver bdc_driver = {
521 .driver = {
522 .name = BRCM_BDC_NAME,
Ashwini Pahujaefed4212014-11-13 10:22:32 -0800523 },
524 .probe = bdc_probe,
525 .remove = bdc_remove,
526};
527
528module_platform_driver(bdc_driver);
529MODULE_AUTHOR("Ashwini Pahuja <ashwini.linux@gmail.com>");
530MODULE_LICENSE("GPL");
531MODULE_DESCRIPTION(BRCM_BDC_DESC);