1/* 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 */ 327 if (bdc->bd_table_pool) 328 dma_pool_destroy(bdc->bd_table_pool); 329 330 /* Free the bdc_ep array */ 331 kfree(bdc->bdc_ep_array); 332 333 bdc->srr.sr_bds = NULL; 334 bdc->scratchpad.buff = NULL; 335 bdc->bd_table_pool = NULL; 336 bdc->bdc_ep_array = NULL; 337} 338 339/* 340 * bdc reinit gives a controller reset and reinitialize the registers, 341 * called from disconnect/bus reset scenario's, to ensure proper HW cleanup 342 */ 343int bdc_reinit(struct bdc *bdc) 344{ 345 int ret; 346 347 dev_dbg(bdc->dev, "%s\n", __func__); 348 ret = bdc_stop(bdc); 349 if (ret) 350 goto out; 351 352 ret = bdc_reset(bdc); 353 if (ret) 354 goto out; 355 356 /* the reinit flag is 1 */ 357 bdc_mem_init(bdc, true); 358 ret = bdc_run(bdc); 359out: 360 bdc->reinit = false; 361 362 return ret; 363} 364 365/* Allocate all the dyanmic memory */ 366static int bdc_mem_alloc(struct bdc *bdc) 367{ 368 u32 page_size; 369 unsigned int num_ieps, num_oeps; 370 371 dev_dbg(bdc->dev, 372 "%s() NUM_BDS_PER_TABLE:%d\n", __func__, 373 NUM_BDS_PER_TABLE); 374 page_size = BDC_PGS(bdc_readl(bdc->regs, BDC_BDCCFG0)); 375 /* page size is 2^pgs KB */ 376 page_size = 1 << page_size; 377 /* KB */ 378 page_size <<= 10; 379 dev_dbg(bdc->dev, "page_size=%d\n", page_size); 380 381 /* Create a pool of bd tables */ 382 bdc->bd_table_pool = 383 dma_pool_create("BDC BD tables", bdc->dev, NUM_BDS_PER_TABLE * 16, 384 16, page_size); 385 386 if (!bdc->bd_table_pool) 387 goto fail; 388 389 if (scratchpad_setup(bdc)) 390 goto fail; 391 392 /* read from regs */ 393 num_ieps = NUM_NCS(bdc_readl(bdc->regs, BDC_FSCNIC)); 394 num_oeps = NUM_NCS(bdc_readl(bdc->regs, BDC_FSCNOC)); 395 /* +2: 1 for ep0 and the other is rsvd i.e. bdc_ep[0] is rsvd */ 396 bdc->num_eps = num_ieps + num_oeps + 2; 397 dev_dbg(bdc->dev, 398 "ieps:%d eops:%d num_eps:%d\n", 399 num_ieps, num_oeps, bdc->num_eps); 400 /* allocate array of ep pointers */ 401 bdc->bdc_ep_array = kcalloc(bdc->num_eps, sizeof(struct bdc_ep *), 402 GFP_KERNEL); 403 if (!bdc->bdc_ep_array) 404 goto fail; 405 406 dev_dbg(bdc->dev, "Allocating sr report0\n"); 407 if (setup_srr(bdc, 0)) 408 goto fail; 409 410 return 0; 411fail: 412 dev_warn(bdc->dev, "Couldn't initialize memory\n"); 413 bdc_mem_free(bdc); 414 415 return -ENOMEM; 416} 417 418/* opposite to bdc_hw_init */ 419static void bdc_hw_exit(struct bdc *bdc) 420{ 421 dev_dbg(bdc->dev, "%s ()\n", __func__); 422 bdc_mem_free(bdc); 423} 424 425/* Initialize the bdc HW and memory */ 426static int bdc_hw_init(struct bdc *bdc) 427{ 428 int ret; 429 430 dev_dbg(bdc->dev, "%s ()\n", __func__); 431 ret = bdc_reset(bdc); 432 if (ret) { 433 dev_err(bdc->dev, "err resetting bdc abort bdc init%d\n", ret); 434 return ret; 435 } 436 ret = bdc_mem_alloc(bdc); 437 if (ret) { 438 dev_err(bdc->dev, "Mem alloc failed, aborting\n"); 439 return -ENOMEM; 440 } 441 bdc_mem_init(bdc, 0); 442 bdc_dbg_regs(bdc); 443 dev_dbg(bdc->dev, "HW Init done\n"); 444 445 return 0; 446} 447 448static int bdc_probe(struct platform_device *pdev) 449{ 450 struct bdc *bdc; 451 struct resource *res; 452 int ret = -ENOMEM; 453 int irq; 454 u32 temp; 455 struct device *dev = &pdev->dev; 456 457 dev_dbg(dev, "%s()\n", __func__); 458 bdc = devm_kzalloc(dev, sizeof(*bdc), GFP_KERNEL); 459 if (!bdc) 460 return -ENOMEM; 461 462 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 463 bdc->regs = devm_ioremap_resource(dev, res); 464 if (IS_ERR(bdc->regs)) { 465 dev_err(dev, "ioremap error\n"); 466 return -ENOMEM; 467 } 468 irq = platform_get_irq(pdev, 0); 469 if (irq < 0) { 470 dev_err(dev, "platform_get_irq failed:%d\n", irq); 471 return irq; 472 } 473 spin_lock_init(&bdc->lock); 474 platform_set_drvdata(pdev, bdc); 475 bdc->irq = irq; 476 bdc->dev = dev; 477 dev_dbg(bdc->dev, "bdc->regs: %p irq=%d\n", bdc->regs, bdc->irq); 478 479 temp = bdc_readl(bdc->regs, BDC_BDCSC); 480 if ((temp & BDC_P64) && 481 !dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) { 482 dev_dbg(bdc->dev, "Using 64-bit address\n"); 483 } else { 484 ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 485 if (ret) { 486 dev_err(bdc->dev, "No suitable DMA config available, abort\n"); 487 return -ENOTSUPP; 488 } 489 dev_dbg(bdc->dev, "Using 32-bit address\n"); 490 } 491 ret = bdc_hw_init(bdc); 492 if (ret) { 493 dev_err(bdc->dev, "BDC init failure:%d\n", ret); 494 return ret; 495 } 496 ret = bdc_udc_init(bdc); 497 if (ret) { 498 dev_err(bdc->dev, "BDC Gadget init failure:%d\n", ret); 499 goto cleanup; 500 } 501 return 0; 502 503cleanup: 504 bdc_hw_exit(bdc); 505 506 return ret; 507} 508 509static int bdc_remove(struct platform_device *pdev) 510{ 511 struct bdc *bdc; 512 513 bdc = platform_get_drvdata(pdev); 514 dev_dbg(bdc->dev, "%s ()\n", __func__); 515 bdc_udc_exit(bdc); 516 bdc_hw_exit(bdc); 517 518 return 0; 519} 520 521static struct platform_driver bdc_driver = { 522 .driver = { 523 .name = BRCM_BDC_NAME, 524 }, 525 .probe = bdc_probe, 526 .remove = bdc_remove, 527}; 528 529module_platform_driver(bdc_driver); 530MODULE_AUTHOR("Ashwini Pahuja <ashwini.linux@gmail.com>"); 531MODULE_LICENSE("GPL"); 532MODULE_DESCRIPTION(BRCM_BDC_DESC); 533