Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'usb-ci-v5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb into usb-next

Peter writes:

- Some improvments for ci_hdrc_usb2.c
- Support imx7d USB charger
- Add software sg support for UDC
- Enable user trigger role switch

* tag 'usb-ci-v5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb:
usb: chipidea: Enable user-space triggered role-switching
usb: chipidea: udc: add software sg list support
usb: chipidea: usbmisc_imx: using different ops for imx7d and imx7ulp
usb: chipidea: pull down dp for possible charger detection operation
usb: chipidea: introduce imx7d USB charger detection
usb: chipidea: introduce CI_HDRC_CONTROLLER_VBUS_EVENT glue layer use
usb: chipidea: usb2: remove unneeded semicolon
usb: chipidea: allow disabling glue drivers if EMBEDDED
usb: chipidea: usb2: absorb zevio glue driver
usb: chipidea: usb2: make clock optional
usb: chipidea: usb2: fix formatting
usb: chipidea: usb2: constify zynq_pdata
usb: chipidea: core: show the real pointer value for register
usb: chipidea: core: refine the description for this driver
usb: chipidea: udc: fix the kernel doc for udc.h

+546 -176
+26 -11
drivers/usb/chipidea/Kconfig
··· 18 18 19 19 if USB_CHIPIDEA 20 20 21 - config USB_CHIPIDEA_OF 22 - tristate 23 - depends on OF 24 - default USB_CHIPIDEA 25 - 26 - config USB_CHIPIDEA_PCI 27 - tristate 28 - depends on USB_PCI 29 - depends on NOP_USB_XCEIV 30 - default USB_CHIPIDEA 31 - 32 21 config USB_CHIPIDEA_UDC 33 22 bool "ChipIdea device controller" 34 23 depends on USB_GADGET ··· 32 43 help 33 44 Say Y here to enable host controller functionality of the 34 45 ChipIdea driver. 46 + 47 + config USB_CHIPIDEA_PCI 48 + tristate "Enable PCI glue driver" if EMBEDDED 49 + depends on USB_PCI 50 + depends on NOP_USB_XCEIV 51 + default USB_CHIPIDEA 52 + 53 + config USB_CHIPIDEA_MSM 54 + tristate "Enable MSM hsusb glue driver" if EMBEDDED 55 + default USB_CHIPIDEA 56 + 57 + config USB_CHIPIDEA_IMX 58 + tristate "Enable i.MX USB glue driver" if EMBEDDED 59 + depends on OF 60 + default USB_CHIPIDEA 61 + 62 + config USB_CHIPIDEA_GENERIC 63 + tristate "Enable generic USB2 glue driver" if EMBEDDED 64 + default USB_CHIPIDEA 65 + 66 + config USB_CHIPIDEA_TEGRA 67 + tristate "Enable Tegra UDC glue driver" if EMBEDDED 68 + depends on OF 69 + depends on USB_CHIPIDEA_UDC 70 + default USB_CHIPIDEA 71 + 35 72 endif
+5 -8
drivers/usb/chipidea/Makefile
··· 8 8 9 9 # Glue/Bridge layers go here 10 10 11 - obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_usb2.o 12 - obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_msm.o 13 - obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_zevio.o 14 - 15 - obj-$(CONFIG_USB_CHIPIDEA_PCI) += ci_hdrc_pci.o 16 - 17 - obj-$(CONFIG_USB_CHIPIDEA_OF) += usbmisc_imx.o ci_hdrc_imx.o 18 - obj-$(CONFIG_USB_CHIPIDEA_OF) += ci_hdrc_tegra.o 11 + obj-$(CONFIG_USB_CHIPIDEA_GENERIC) += ci_hdrc_usb2.o 12 + obj-$(CONFIG_USB_CHIPIDEA_MSM) += ci_hdrc_msm.o 13 + obj-$(CONFIG_USB_CHIPIDEA_PCI) += ci_hdrc_pci.o 14 + obj-$(CONFIG_USB_CHIPIDEA_IMX) += ci_hdrc_imx.o usbmisc_imx.o 15 + obj-$(CONFIG_USB_CHIPIDEA_TEGRA) += ci_hdrc_tegra.o
+1
drivers/usb/chipidea/ci.h
··· 25 25 #define TD_PAGE_COUNT 5 26 26 #define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */ 27 27 #define ENDPT_MAX 32 28 + #define CI_MAX_BUF_SIZE (TD_PAGE_COUNT * CI_HDRC_PAGE_SIZE) 28 29 29 30 /****************************************************************************** 30 31 * REGISTERS
+12 -1
drivers/usb/chipidea/ci_hdrc_imx.c
··· 271 271 struct device *dev = ci->dev->parent; 272 272 struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); 273 273 int ret = 0; 274 + struct imx_usbmisc_data *mdata = data->usbmisc_data; 274 275 275 276 switch (event) { 276 277 case CI_HDRC_IMX_HSIC_ACTIVE_EVENT: ··· 285 284 } 286 285 break; 287 286 case CI_HDRC_IMX_HSIC_SUSPEND_EVENT: 288 - ret = imx_usbmisc_hsic_set_connect(data->usbmisc_data); 287 + ret = imx_usbmisc_hsic_set_connect(mdata); 289 288 if (ret) 290 289 dev_err(dev, 291 290 "hsic_set_connect failed, err=%d\n", ret); 291 + break; 292 + case CI_HDRC_CONTROLLER_VBUS_EVENT: 293 + if (ci->vbus_active) 294 + ret = imx_usbmisc_charger_detection(mdata, true); 295 + else 296 + ret = imx_usbmisc_charger_detection(mdata, false); 297 + if (ci->usb_phy) 298 + schedule_work(&ci->usb_phy->chg_work); 292 299 break; 293 300 default: 294 301 break; ··· 423 414 } 424 415 425 416 pdata.usb_phy = data->phy; 417 + if (data->usbmisc_data) 418 + data->usbmisc_data->usb_phy = data->phy; 426 419 427 420 if ((of_device_is_compatible(np, "fsl,imx53-usb") || 428 421 of_device_is_compatible(np, "fsl,imx51-usb")) && pdata.usb_phy &&
+2
drivers/usb/chipidea/ci_hdrc_imx.h
··· 24 24 unsigned int hsic:1; /* HSIC controlller */ 25 25 unsigned int ext_id:1; /* ID from exteranl event */ 26 26 unsigned int ext_vbus:1; /* Vbus from exteranl event */ 27 + struct usb_phy *usb_phy; 27 28 }; 28 29 29 30 int imx_usbmisc_init(struct imx_usbmisc_data *data); ··· 32 31 int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled); 33 32 int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data); 34 33 int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on); 34 + int imx_usbmisc_charger_detection(struct imx_usbmisc_data *data, bool connect); 35 35 36 36 #endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */
+18 -12
drivers/usb/chipidea/ci_hdrc_usb2.c
··· 28 28 .flags = CI_HDRC_DISABLE_STREAMING, 29 29 }; 30 30 31 - static struct ci_hdrc_platform_data ci_zynq_pdata = { 31 + static const struct ci_hdrc_platform_data ci_zynq_pdata = { 32 32 .capoffset = DEF_CAPOFFSET, 33 33 }; 34 34 35 + static const struct ci_hdrc_platform_data ci_zevio_pdata = { 36 + .capoffset = DEF_CAPOFFSET, 37 + .flags = CI_HDRC_REGS_SHARED | CI_HDRC_FORCE_FULLSPEED, 38 + }; 39 + 35 40 static const struct of_device_id ci_hdrc_usb2_of_match[] = { 36 - { .compatible = "chipidea,usb2"}, 37 - { .compatible = "xlnx,zynq-usb-2.20a", .data = &ci_zynq_pdata}, 41 + { .compatible = "chipidea,usb2" }, 42 + { .compatible = "xlnx,zynq-usb-2.20a", .data = &ci_zynq_pdata }, 43 + { .compatible = "lsi,zevio-usb", .data = &ci_zevio_pdata }, 38 44 { } 39 45 }; 40 46 MODULE_DEVICE_TABLE(of, ci_hdrc_usb2_of_match); ··· 70 64 if (!priv) 71 65 return -ENOMEM; 72 66 73 - priv->clk = devm_clk_get(dev, NULL); 74 - if (!IS_ERR(priv->clk)) { 75 - ret = clk_prepare_enable(priv->clk); 76 - if (ret) { 77 - dev_err(dev, "failed to enable the clock: %d\n", ret); 78 - return ret; 79 - } 67 + priv->clk = devm_clk_get_optional(dev, NULL); 68 + if (IS_ERR(priv->clk)) 69 + return PTR_ERR(priv->clk); 70 + 71 + ret = clk_prepare_enable(priv->clk); 72 + if (ret) { 73 + dev_err(dev, "failed to enable the clock: %d\n", ret); 74 + return ret; 80 75 } 81 76 82 77 ci_pdata->name = dev_name(dev); ··· 101 94 return 0; 102 95 103 96 clk_err: 104 - if (!IS_ERR(priv->clk)) 105 - clk_disable_unprepare(priv->clk); 97 + clk_disable_unprepare(priv->clk); 106 98 return ret; 107 99 } 108 100
-67
drivers/usb/chipidea/ci_hdrc_zevio.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au> 4 - * 5 - * Based off drivers/usb/chipidea/ci_hdrc_msm.c 6 - */ 7 - 8 - #include <linux/module.h> 9 - #include <linux/platform_device.h> 10 - #include <linux/usb/gadget.h> 11 - #include <linux/usb/chipidea.h> 12 - 13 - #include "ci.h" 14 - 15 - static struct ci_hdrc_platform_data ci_hdrc_zevio_platdata = { 16 - .name = "ci_hdrc_zevio", 17 - .flags = CI_HDRC_REGS_SHARED | CI_HDRC_FORCE_FULLSPEED, 18 - .capoffset = DEF_CAPOFFSET, 19 - }; 20 - 21 - static int ci_hdrc_zevio_probe(struct platform_device *pdev) 22 - { 23 - struct platform_device *ci_pdev; 24 - 25 - dev_dbg(&pdev->dev, "ci_hdrc_zevio_probe\n"); 26 - 27 - ci_pdev = ci_hdrc_add_device(&pdev->dev, 28 - pdev->resource, pdev->num_resources, 29 - &ci_hdrc_zevio_platdata); 30 - 31 - if (IS_ERR(ci_pdev)) { 32 - dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n"); 33 - return PTR_ERR(ci_pdev); 34 - } 35 - 36 - platform_set_drvdata(pdev, ci_pdev); 37 - 38 - return 0; 39 - } 40 - 41 - static int ci_hdrc_zevio_remove(struct platform_device *pdev) 42 - { 43 - struct platform_device *ci_pdev = platform_get_drvdata(pdev); 44 - 45 - ci_hdrc_remove_device(ci_pdev); 46 - 47 - return 0; 48 - } 49 - 50 - static const struct of_device_id ci_hdrc_zevio_dt_ids[] = { 51 - { .compatible = "lsi,zevio-usb", }, 52 - { /* sentinel */ } 53 - }; 54 - 55 - static struct platform_driver ci_hdrc_zevio_driver = { 56 - .probe = ci_hdrc_zevio_probe, 57 - .remove = ci_hdrc_zevio_remove, 58 - .driver = { 59 - .name = "zevio_usb", 60 - .of_match_table = ci_hdrc_zevio_dt_ids, 61 - }, 62 - }; 63 - 64 - MODULE_DEVICE_TABLE(of, ci_hdrc_zevio_dt_ids); 65 - module_platform_driver(ci_hdrc_zevio_driver); 66 - 67 - MODULE_LICENSE("GPL v2");
+13 -35
drivers/usb/chipidea/core.c
··· 3 3 * core.c - ChipIdea USB IP core family device controller 4 4 * 5 5 * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. 6 + * Copyright (C) 2020 NXP 6 7 * 7 8 * Author: David Lopo 8 - */ 9 - 10 - /* 11 - * Description: ChipIdea USB IP core family device controller 9 + * Peter Chen <peter.chen@nxp.com> 12 10 * 13 - * This driver is composed of several blocks: 14 - * - HW: hardware interface 15 - * - DBG: debug facilities (optional) 16 - * - UTIL: utilities 17 - * - ISR: interrupts handling 18 - * - ENDPT: endpoint operations (Gadget API) 19 - * - GADGET: gadget operations (Gadget API) 20 - * - BUS: bus glue code, bus abstraction layer 21 - * 22 - * Compile Options 23 - * - STALL_IN: non-empty bulk-in pipes cannot be halted 24 - * if defined mass storage compliance succeeds but with warnings 25 - * => case 4: Hi > Dn 26 - * => case 5: Hi > Di 27 - * => case 8: Hi <> Do 28 - * if undefined usbtest 13 fails 29 - * - TRACE: enable function tracing (depends on DEBUG) 30 - * 31 - * Main Features 32 - * - Chapter 9 & Mass Storage Compliance with Gadget File Storage 33 - * - Chapter 9 Compliance with Gadget Zero (STALL_IN undefined) 34 - * - Normal & LPM support 35 - * 36 - * USBTEST Report 37 - * - OK: 0-12, 13 (STALL_IN defined) & 14 38 - * - Not Supported: 15 & 16 (ISO) 39 - * 40 - * TODO List 41 - * - Suspend & Remote Wakeup 11 + * Main Features: 12 + * - Four transfers are supported, usbtest is passed 13 + * - USB Certification for gadget: CH9 and Mass Storage are passed 14 + * - Low power mode 15 + * - USB wakeup 42 16 */ 43 17 #include <linux/delay.h> 44 18 #include <linux/device.h> ··· 246 272 ci->rev = ci_get_revision(ci); 247 273 248 274 dev_dbg(ci->dev, 249 - "ChipIdea HDRC found, revision: %d, lpm: %d; cap: %p op: %p\n", 275 + "revision: %d, lpm: %d; cap: %px op: %px\n", 250 276 ci->rev, ci->hw_bank.lpm, ci->hw_bank.cap, ci->hw_bank.op); 251 277 252 278 /* setup lock mode ? */ ··· 640 666 static struct usb_role_switch_desc ci_role_switch = { 641 667 .set = ci_usb_role_switch_set, 642 668 .get = ci_usb_role_switch_get, 669 + .allow_userspace_control = true, 643 670 }; 644 671 645 672 static int ci_get_platdata(struct device *dev, ··· 1124 1149 1125 1150 if (!ci_otg_is_fsm_mode(ci)) { 1126 1151 /* only update vbus status for peripheral */ 1127 - if (ci->role == CI_ROLE_GADGET) 1152 + if (ci->role == CI_ROLE_GADGET) { 1153 + /* Pull down DP for possible charger detection */ 1154 + hw_write(ci, OP_USBCMD, USBCMD_RS, 0); 1128 1155 ci_handle_vbus_change(ci); 1156 + } 1129 1157 1130 1158 ret = ci_role_start(ci, ci->role); 1131 1159 if (ret) {
+137 -33
drivers/usb/chipidea/udc.c
··· 338 338 *****************************************************************************/ 339 339 340 340 static int add_td_to_list(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq, 341 - unsigned length) 341 + unsigned int length, struct scatterlist *s) 342 342 { 343 343 int i; 344 344 u32 temp; ··· 366 366 node->ptr->token |= cpu_to_le32(mul << __ffs(TD_MULTO)); 367 367 } 368 368 369 - temp = (u32) (hwreq->req.dma + hwreq->req.actual); 369 + if (s) { 370 + temp = (u32) (sg_dma_address(s) + hwreq->req.actual); 371 + node->td_remaining_size = CI_MAX_BUF_SIZE - length; 372 + } else { 373 + temp = (u32) (hwreq->req.dma + hwreq->req.actual); 374 + } 375 + 370 376 if (length) { 371 377 node->ptr->page[0] = cpu_to_le32(temp); 372 378 for (i = 1; i < TD_PAGE_COUNT; i++) { ··· 406 400 return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num; 407 401 } 408 402 403 + static int prepare_td_for_non_sg(struct ci_hw_ep *hwep, 404 + struct ci_hw_req *hwreq) 405 + { 406 + unsigned int rest = hwreq->req.length; 407 + int pages = TD_PAGE_COUNT; 408 + int ret = 0; 409 + 410 + if (rest == 0) { 411 + ret = add_td_to_list(hwep, hwreq, 0, NULL); 412 + if (ret < 0) 413 + return ret; 414 + } 415 + 416 + /* 417 + * The first buffer could be not page aligned. 418 + * In that case we have to span into one extra td. 419 + */ 420 + if (hwreq->req.dma % PAGE_SIZE) 421 + pages--; 422 + 423 + while (rest > 0) { 424 + unsigned int count = min(hwreq->req.length - hwreq->req.actual, 425 + (unsigned int)(pages * CI_HDRC_PAGE_SIZE)); 426 + 427 + ret = add_td_to_list(hwep, hwreq, count, NULL); 428 + if (ret < 0) 429 + return ret; 430 + 431 + rest -= count; 432 + } 433 + 434 + if (hwreq->req.zero && hwreq->req.length && hwep->dir == TX 435 + && (hwreq->req.length % hwep->ep.maxpacket == 0)) { 436 + ret = add_td_to_list(hwep, hwreq, 0, NULL); 437 + if (ret < 0) 438 + return ret; 439 + } 440 + 441 + return ret; 442 + } 443 + 444 + static int prepare_td_per_sg(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq, 445 + struct scatterlist *s) 446 + { 447 + unsigned int rest = sg_dma_len(s); 448 + int ret = 0; 449 + 450 + hwreq->req.actual = 0; 451 + while (rest > 0) { 452 + unsigned int count = min_t(unsigned int, rest, 453 + CI_MAX_BUF_SIZE); 454 + 455 + ret = add_td_to_list(hwep, hwreq, count, s); 456 + if (ret < 0) 457 + return ret; 458 + 459 + rest -= count; 460 + } 461 + 462 + return ret; 463 + } 464 + 465 + static void ci_add_buffer_entry(struct td_node *node, struct scatterlist *s) 466 + { 467 + int empty_td_slot_index = (CI_MAX_BUF_SIZE - node->td_remaining_size) 468 + / CI_HDRC_PAGE_SIZE; 469 + int i; 470 + 471 + node->ptr->token += 472 + cpu_to_le32(sg_dma_len(s) << __ffs(TD_TOTAL_BYTES)); 473 + 474 + for (i = empty_td_slot_index; i < TD_PAGE_COUNT; i++) { 475 + u32 page = (u32) sg_dma_address(s) + 476 + (i - empty_td_slot_index) * CI_HDRC_PAGE_SIZE; 477 + 478 + page &= ~TD_RESERVED_MASK; 479 + node->ptr->page[i] = cpu_to_le32(page); 480 + } 481 + } 482 + 483 + static int prepare_td_for_sg(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) 484 + { 485 + struct usb_request *req = &hwreq->req; 486 + struct scatterlist *s = req->sg; 487 + int ret = 0, i = 0; 488 + struct td_node *node = NULL; 489 + 490 + if (!s || req->zero || req->length == 0) { 491 + dev_err(hwep->ci->dev, "not supported operation for sg\n"); 492 + return -EINVAL; 493 + } 494 + 495 + while (i++ < req->num_mapped_sgs) { 496 + if (sg_dma_address(s) % PAGE_SIZE) { 497 + dev_err(hwep->ci->dev, "not page aligned sg buffer\n"); 498 + return -EINVAL; 499 + } 500 + 501 + if (node && (node->td_remaining_size >= sg_dma_len(s))) { 502 + ci_add_buffer_entry(node, s); 503 + node->td_remaining_size -= sg_dma_len(s); 504 + } else { 505 + ret = prepare_td_per_sg(hwep, hwreq, s); 506 + if (ret) 507 + return ret; 508 + 509 + node = list_entry(hwreq->tds.prev, 510 + struct td_node, td); 511 + } 512 + 513 + s = sg_next(s); 514 + } 515 + 516 + return ret; 517 + } 518 + 409 519 /** 410 520 * _hardware_enqueue: configures a request at hardware level 411 521 * @hwep: endpoint ··· 533 411 { 534 412 struct ci_hdrc *ci = hwep->ci; 535 413 int ret = 0; 536 - unsigned rest = hwreq->req.length; 537 - int pages = TD_PAGE_COUNT; 538 414 struct td_node *firstnode, *lastnode; 539 415 540 416 /* don't queue twice */ ··· 546 426 if (ret) 547 427 return ret; 548 428 549 - /* 550 - * The first buffer could be not page aligned. 551 - * In that case we have to span into one extra td. 552 - */ 553 - if (hwreq->req.dma % PAGE_SIZE) 554 - pages--; 429 + if (hwreq->req.num_mapped_sgs) 430 + ret = prepare_td_for_sg(hwep, hwreq); 431 + else 432 + ret = prepare_td_for_non_sg(hwep, hwreq); 555 433 556 - if (rest == 0) { 557 - ret = add_td_to_list(hwep, hwreq, 0); 558 - if (ret < 0) 559 - goto done; 560 - } 561 - 562 - while (rest > 0) { 563 - unsigned count = min(hwreq->req.length - hwreq->req.actual, 564 - (unsigned)(pages * CI_HDRC_PAGE_SIZE)); 565 - ret = add_td_to_list(hwep, hwreq, count); 566 - if (ret < 0) 567 - goto done; 568 - 569 - rest -= count; 570 - } 571 - 572 - if (hwreq->req.zero && hwreq->req.length && hwep->dir == TX 573 - && (hwreq->req.length % hwep->ep.maxpacket == 0)) { 574 - ret = add_td_to_list(hwep, hwreq, 0); 575 - if (ret < 0) 576 - goto done; 577 - } 434 + if (ret) 435 + return ret; 578 436 579 437 firstnode = list_first_entry(&hwreq->tds, struct td_node, td); 580 438 ··· 1659 1561 { 1660 1562 struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); 1661 1563 unsigned long flags; 1564 + int ret = 0; 1662 1565 1663 1566 spin_lock_irqsave(&ci->lock, flags); 1664 1567 ci->vbus_active = is_active; ··· 1669 1570 usb_phy_set_charger_state(ci->usb_phy, is_active ? 1670 1571 USB_CHARGER_PRESENT : USB_CHARGER_ABSENT); 1671 1572 1573 + if (ci->platdata->notify_event) 1574 + ret = ci->platdata->notify_event(ci, 1575 + CI_HDRC_CONTROLLER_VBUS_EVENT); 1576 + 1672 1577 if (ci->driver) 1673 1578 ci_hdrc_gadget_connect(_gadget, is_active); 1674 1579 1675 - return 0; 1580 + return ret; 1676 1581 } 1677 1582 1678 1583 static int ci_udc_wakeup(struct usb_gadget *_gadget) ··· 2039 1936 ci->gadget.max_speed = USB_SPEED_HIGH; 2040 1937 ci->gadget.name = ci->platdata->name; 2041 1938 ci->gadget.otg_caps = otg_caps; 1939 + ci->gadget.sg_supported = 1; 2042 1940 2043 1941 if (ci->platdata->flags & CI_HDRC_REQUIRES_ALIGNED_DMA) 2044 1942 ci->gadget.quirk_avoids_skb_reserve = 1;
+2 -4
drivers/usb/chipidea/udc.h
··· 61 61 struct list_head td; 62 62 dma_addr_t dma; 63 63 struct ci_hw_td *ptr; 64 + int td_remaining_size; 64 65 }; 65 66 66 67 /** 67 68 * struct ci_hw_req - usb request representation 68 69 * @req: request structure for gadget drivers 69 70 * @queue: link to QH list 70 - * @ptr: transfer descriptor for this request 71 - * @dma: dma address for the transfer descriptor 72 - * @zptr: transfer descriptor for the zero packet 73 - * @zdma: dma address of the zero packet's transfer descriptor 71 + * @tds: link to TD list 74 72 */ 75 73 struct ci_hw_req { 76 74 struct usb_request req;
+329 -5
drivers/usb/chipidea/usbmisc_imx.c
··· 8 8 #include <linux/err.h> 9 9 #include <linux/io.h> 10 10 #include <linux/delay.h> 11 + #include <linux/usb/otg.h> 11 12 12 13 #include "ci_hdrc_imx.h" 13 14 ··· 100 99 #define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID MX7D_USB_VBUS_WAKEUP_SOURCE(1) 101 100 #define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID MX7D_USB_VBUS_WAKEUP_SOURCE(2) 102 101 #define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END MX7D_USB_VBUS_WAKEUP_SOURCE(3) 102 + #define MX7D_USBNC_AUTO_RESUME BIT(2) 103 + /* The default DM/DP value is pull-down */ 104 + #define MX7D_USBNC_USB_CTRL2_OPMODE(v) (v << 6) 105 + #define MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING MX7D_USBNC_USB_CTRL2_OPMODE(1) 106 + #define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK (BIT(7) | BIT(6)) 107 + #define MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN BIT(8) 108 + #define MX7D_USBNC_USB_CTRL2_DP_OVERRIDE_VAL BIT(12) 109 + #define MX7D_USBNC_USB_CTRL2_DP_OVERRIDE_EN BIT(13) 110 + #define MX7D_USBNC_USB_CTRL2_DM_OVERRIDE_VAL BIT(14) 111 + #define MX7D_USBNC_USB_CTRL2_DM_OVERRIDE_EN BIT(15) 112 + #define MX7D_USBNC_USB_CTRL2_DP_DM_MASK (BIT(12) | BIT(13) | \ 113 + BIT(14) | BIT(15)) 114 + 115 + #define MX7D_USB_OTG_PHY_CFG1 0x30 116 + #define MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL BIT(0) 117 + #define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 BIT(1) 118 + #define MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 BIT(2) 119 + #define MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB BIT(3) 120 + #define MX7D_USB_OTG_PHY_CFG2_DRVVBUS0 BIT(16) 121 + 122 + #define MX7D_USB_OTG_PHY_CFG2 0x34 123 + 124 + #define MX7D_USB_OTG_PHY_STATUS 0x3c 125 + #define MX7D_USB_OTG_PHY_STATUS_LINE_STATE0 BIT(0) 126 + #define MX7D_USB_OTG_PHY_STATUS_LINE_STATE1 BIT(1) 127 + #define MX7D_USB_OTG_PHY_STATUS_VBUS_VLD BIT(3) 128 + #define MX7D_USB_OTG_PHY_STATUS_CHRGDET BIT(29) 103 129 104 130 #define MX6_USB_OTG_WAKEUP_BITS (MX6_BM_WAKEUP_ENABLE | MX6_BM_VBUS_WAKEUP | \ 105 131 MX6_BM_ID_WAKEUP) ··· 142 114 int (*hsic_set_connect)(struct imx_usbmisc_data *data); 143 115 /* It's called during suspend/resume */ 144 116 int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled); 117 + /* usb charger detection */ 118 + int (*charger_detection)(struct imx_usbmisc_data *data); 145 119 }; 146 120 147 121 struct imx_usbmisc { ··· 639 609 reg |= MX6_BM_PWR_POLARITY; 640 610 writel(reg, usbmisc->base); 641 611 642 - reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 643 - reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; 644 - writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID, 645 - usbmisc->base + MX7D_USBNC_USB_CTRL2); 612 + /* SoC non-burst setting */ 613 + reg = readl(usbmisc->base); 614 + writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base); 615 + 616 + if (!data->hsic) { 617 + reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 618 + reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; 619 + writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID 620 + | MX7D_USBNC_AUTO_RESUME, 621 + usbmisc->base + MX7D_USBNC_USB_CTRL2); 622 + } 623 + 624 + spin_unlock_irqrestore(&usbmisc->lock, flags); 625 + 626 + usbmisc_imx7d_set_wakeup(data, false); 627 + 628 + return 0; 629 + } 630 + 631 + static int imx7d_charger_secondary_detection(struct imx_usbmisc_data *data) 632 + { 633 + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 634 + struct usb_phy *usb_phy = data->usb_phy; 635 + int val; 636 + unsigned long flags; 637 + 638 + /* VDM_SRC is connected to D- and IDP_SINK is connected to D+ */ 639 + spin_lock_irqsave(&usbmisc->lock, flags); 640 + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 641 + writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 | 642 + MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 | 643 + MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL, 644 + usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 645 + spin_unlock_irqrestore(&usbmisc->lock, flags); 646 + 647 + usleep_range(1000, 2000); 648 + 649 + /* 650 + * Per BC 1.2, check voltage of D+: 651 + * DCP: if greater than VDAT_REF; 652 + * CDP: if less than VDAT_REF. 653 + */ 654 + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS); 655 + if (val & MX7D_USB_OTG_PHY_STATUS_CHRGDET) { 656 + dev_dbg(data->dev, "It is a dedicate charging port\n"); 657 + usb_phy->chg_type = DCP_TYPE; 658 + } else { 659 + dev_dbg(data->dev, "It is a charging downstream port\n"); 660 + usb_phy->chg_type = CDP_TYPE; 661 + } 662 + 663 + return 0; 664 + } 665 + 666 + static void imx7_disable_charger_detector(struct imx_usbmisc_data *data) 667 + { 668 + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 669 + unsigned long flags; 670 + u32 val; 671 + 672 + spin_lock_irqsave(&usbmisc->lock, flags); 673 + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 674 + val &= ~(MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB | 675 + MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 | 676 + MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0 | 677 + MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL); 678 + writel(val, usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 679 + 680 + /* Set OPMODE to be 2'b00 and disable its override */ 681 + val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 682 + val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK; 683 + writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2); 684 + 685 + val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 686 + writel(val & ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN, 687 + usbmisc->base + MX7D_USBNC_USB_CTRL2); 688 + spin_unlock_irqrestore(&usbmisc->lock, flags); 689 + } 690 + 691 + static int imx7d_charger_data_contact_detect(struct imx_usbmisc_data *data) 692 + { 693 + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 694 + unsigned long flags; 695 + u32 val; 696 + int i, data_pin_contact_count = 0; 697 + 698 + /* Enable Data Contact Detect (DCD) per the USB BC 1.2 */ 699 + spin_lock_irqsave(&usbmisc->lock, flags); 700 + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 701 + writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB, 702 + usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 703 + spin_unlock_irqrestore(&usbmisc->lock, flags); 704 + 705 + for (i = 0; i < 100; i = i + 1) { 706 + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS); 707 + if (!(val & MX7D_USB_OTG_PHY_STATUS_LINE_STATE0)) { 708 + if (data_pin_contact_count++ > 5) 709 + /* Data pin makes contact */ 710 + break; 711 + usleep_range(5000, 10000); 712 + } else { 713 + data_pin_contact_count = 0; 714 + usleep_range(5000, 6000); 715 + } 716 + } 717 + 718 + /* Disable DCD after finished data contact check */ 719 + spin_lock_irqsave(&usbmisc->lock, flags); 720 + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 721 + writel(val & ~MX7D_USB_OTG_PHY_CFG2_CHRG_DCDENB, 722 + usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 723 + spin_unlock_irqrestore(&usbmisc->lock, flags); 724 + 725 + if (i == 100) { 726 + dev_err(data->dev, 727 + "VBUS is coming from a dedicated power supply.\n"); 728 + return -ENXIO; 729 + } 730 + 731 + return 0; 732 + } 733 + 734 + static int imx7d_charger_primary_detection(struct imx_usbmisc_data *data) 735 + { 736 + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 737 + struct usb_phy *usb_phy = data->usb_phy; 738 + unsigned long flags; 739 + u32 val; 740 + 741 + /* VDP_SRC is connected to D+ and IDM_SINK is connected to D- */ 742 + spin_lock_irqsave(&usbmisc->lock, flags); 743 + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 744 + val &= ~MX7D_USB_OTG_PHY_CFG2_CHRG_CHRGSEL; 745 + writel(val | MX7D_USB_OTG_PHY_CFG2_CHRG_VDATSRCENB0 | 746 + MX7D_USB_OTG_PHY_CFG2_CHRG_VDATDETENB0, 747 + usbmisc->base + MX7D_USB_OTG_PHY_CFG2); 748 + spin_unlock_irqrestore(&usbmisc->lock, flags); 749 + 750 + usleep_range(1000, 2000); 751 + 752 + /* Check if D- is less than VDAT_REF to determine an SDP per BC 1.2 */ 753 + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS); 754 + if (!(val & MX7D_USB_OTG_PHY_STATUS_CHRGDET)) { 755 + dev_dbg(data->dev, "It is a standard downstream port\n"); 756 + usb_phy->chg_type = SDP_TYPE; 757 + } 758 + 759 + return 0; 760 + } 761 + 762 + /** 763 + * Whole charger detection process: 764 + * 1. OPMODE override to be non-driving 765 + * 2. Data contact check 766 + * 3. Primary detection 767 + * 4. Secondary detection 768 + * 5. Disable charger detection 769 + */ 770 + static int imx7d_charger_detection(struct imx_usbmisc_data *data) 771 + { 772 + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 773 + struct usb_phy *usb_phy = data->usb_phy; 774 + unsigned long flags; 775 + u32 val; 776 + int ret; 777 + 778 + /* Check if vbus is valid */ 779 + val = readl(usbmisc->base + MX7D_USB_OTG_PHY_STATUS); 780 + if (!(val & MX7D_USB_OTG_PHY_STATUS_VBUS_VLD)) { 781 + dev_err(data->dev, "vbus is error\n"); 782 + return -EINVAL; 783 + } 784 + 785 + /* 786 + * Keep OPMODE to be non-driving mode during the whole 787 + * charger detection process. 788 + */ 789 + spin_lock_irqsave(&usbmisc->lock, flags); 790 + val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 791 + val &= ~MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_MASK; 792 + val |= MX7D_USBNC_USB_CTRL2_OPMODE_NON_DRIVING; 793 + writel(val, usbmisc->base + MX7D_USBNC_USB_CTRL2); 794 + 795 + val = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 796 + writel(val | MX7D_USBNC_USB_CTRL2_OPMODE_OVERRIDE_EN, 797 + usbmisc->base + MX7D_USBNC_USB_CTRL2); 798 + spin_unlock_irqrestore(&usbmisc->lock, flags); 799 + 800 + ret = imx7d_charger_data_contact_detect(data); 801 + if (ret) 802 + return ret; 803 + 804 + ret = imx7d_charger_primary_detection(data); 805 + if (!ret && usb_phy->chg_type != SDP_TYPE) 806 + ret = imx7d_charger_secondary_detection(data); 807 + 808 + imx7_disable_charger_detector(data); 809 + 810 + return ret; 811 + } 812 + 813 + static int usbmisc_imx7ulp_init(struct imx_usbmisc_data *data) 814 + { 815 + struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); 816 + unsigned long flags; 817 + u32 reg; 818 + 819 + if (data->index >= 1) 820 + return -EINVAL; 821 + 822 + spin_lock_irqsave(&usbmisc->lock, flags); 823 + reg = readl(usbmisc->base); 824 + if (data->disable_oc) { 825 + reg |= MX6_BM_OVER_CUR_DIS; 826 + } else { 827 + reg &= ~MX6_BM_OVER_CUR_DIS; 828 + 829 + /* 830 + * If the polarity is not configured keep it as setup by the 831 + * bootloader. 832 + */ 833 + if (data->oc_pol_configured && data->oc_pol_active_low) 834 + reg |= MX6_BM_OVER_CUR_POLARITY; 835 + else if (data->oc_pol_configured) 836 + reg &= ~MX6_BM_OVER_CUR_POLARITY; 837 + } 838 + /* If the polarity is not set keep it as setup by the bootlader */ 839 + if (data->pwr_pol == 1) 840 + reg |= MX6_BM_PWR_POLARITY; 841 + 842 + writel(reg, usbmisc->base); 843 + 844 + /* SoC non-burst setting */ 845 + reg = readl(usbmisc->base); 846 + writel(reg | MX6_BM_NON_BURST_SETTING, usbmisc->base); 847 + 848 + if (data->hsic) { 849 + reg = readl(usbmisc->base); 850 + writel(reg | MX6_BM_UTMI_ON_CLOCK, usbmisc->base); 851 + 852 + reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); 853 + reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON; 854 + writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); 855 + 856 + /* 857 + * For non-HSIC controller, the autoresume is enabled 858 + * at MXS PHY driver (usbphy_ctrl bit18). 859 + */ 860 + reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 861 + writel(reg | MX7D_USBNC_AUTO_RESUME, 862 + usbmisc->base + MX7D_USBNC_USB_CTRL2); 863 + } else { 864 + reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2); 865 + reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; 866 + writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID, 867 + usbmisc->base + MX7D_USBNC_USB_CTRL2); 868 + } 646 869 647 870 spin_unlock_irqrestore(&usbmisc->lock, flags); 648 871 ··· 942 659 static const struct usbmisc_ops imx7d_usbmisc_ops = { 943 660 .init = usbmisc_imx7d_init, 944 661 .set_wakeup = usbmisc_imx7d_set_wakeup, 662 + .charger_detection = imx7d_charger_detection, 663 + }; 664 + 665 + static const struct usbmisc_ops imx7ulp_usbmisc_ops = { 666 + .init = usbmisc_imx7ulp_init, 667 + .set_wakeup = usbmisc_imx7d_set_wakeup, 668 + .hsic_set_connect = usbmisc_imx6_hsic_set_connect, 669 + .hsic_set_clk = usbmisc_imx6_hsic_set_clk, 945 670 }; 946 671 947 672 static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data) ··· 1028 737 return usbmisc->ops->hsic_set_clk(data, on); 1029 738 } 1030 739 EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk); 740 + 741 + int imx_usbmisc_charger_detection(struct imx_usbmisc_data *data, bool connect) 742 + { 743 + struct imx_usbmisc *usbmisc; 744 + struct usb_phy *usb_phy; 745 + int ret = 0; 746 + 747 + if (!data) 748 + return -EINVAL; 749 + 750 + usbmisc = dev_get_drvdata(data->dev); 751 + usb_phy = data->usb_phy; 752 + if (!usbmisc->ops->charger_detection) 753 + return -ENOTSUPP; 754 + 755 + if (connect) { 756 + ret = usbmisc->ops->charger_detection(data); 757 + if (ret) { 758 + dev_err(data->dev, 759 + "Error occurs during detection: %d\n", 760 + ret); 761 + usb_phy->chg_state = USB_CHARGER_ABSENT; 762 + } else { 763 + usb_phy->chg_state = USB_CHARGER_PRESENT; 764 + } 765 + } else { 766 + usb_phy->chg_state = USB_CHARGER_ABSENT; 767 + usb_phy->chg_type = UNKNOWN_TYPE; 768 + } 769 + return ret; 770 + } 771 + EXPORT_SYMBOL_GPL(imx_usbmisc_charger_detection); 772 + 1031 773 static const struct of_device_id usbmisc_imx_dt_ids[] = { 1032 774 { 1033 775 .compatible = "fsl,imx25-usbmisc", ··· 1104 780 }, 1105 781 { 1106 782 .compatible = "fsl,imx7ulp-usbmisc", 1107 - .data = &imx7d_usbmisc_ops, 783 + .data = &imx7ulp_usbmisc_ops, 1108 784 }, 1109 785 { /* sentinel */ } 1110 786 };
+1
include/linux/usb/chipidea.h
··· 67 67 #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 68 68 #define CI_HDRC_IMX_HSIC_ACTIVE_EVENT 2 69 69 #define CI_HDRC_IMX_HSIC_SUSPEND_EVENT 3 70 + #define CI_HDRC_CONTROLLER_VBUS_EVENT 4 70 71 int (*notify_event) (struct ci_hdrc *ci, unsigned event); 71 72 struct regulator *reg_vbus; 72 73 struct usb_otg_caps ci_otg_caps;