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

usb: chipidea: Add support for NPCM

Add Nuvoton NPCM BMC SoCs support to USB ChipIdea driver.
NPCM SoC includes ChipIdea IP block that is used for USB device controller
mode.

Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
Acked-by: Peter Chen <peter.chen@kernel.org>
Link: https://lore.kernel.org/r/20231017195903.1665260-4-tmaimon77@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Tomer Maimon and committed by
Greg Kroah-Hartman
70f13579 ceae398f

+119
+4
drivers/usb/chipidea/Kconfig
··· 43 43 tristate "Enable MSM hsusb glue driver" if EXPERT 44 44 default USB_CHIPIDEA 45 45 46 + config USB_CHIPIDEA_NPCM 47 + tristate "Enable NPCM hsusb glue driver" if EXPERT 48 + default USB_CHIPIDEA 49 + 46 50 config USB_CHIPIDEA_IMX 47 51 tristate "Enable i.MX USB glue driver" if EXPERT 48 52 depends on OF
+1
drivers/usb/chipidea/Makefile
··· 13 13 14 14 obj-$(CONFIG_USB_CHIPIDEA_GENERIC) += ci_hdrc_usb2.o 15 15 obj-$(CONFIG_USB_CHIPIDEA_MSM) += ci_hdrc_msm.o 16 + obj-$(CONFIG_USB_CHIPIDEA_NPCM) += ci_hdrc_npcm.o 16 17 obj-$(CONFIG_USB_CHIPIDEA_PCI) += ci_hdrc_pci.o 17 18 obj-$(CONFIG_USB_CHIPIDEA_IMX) += usbmisc_imx.o ci_hdrc_imx.o 18 19 obj-$(CONFIG_USB_CHIPIDEA_TEGRA) += ci_hdrc_tegra.o
+114
drivers/usb/chipidea/ci_hdrc_npcm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2023 Nuvoton Technology corporation. 3 + 4 + #include <linux/module.h> 5 + #include <linux/platform_device.h> 6 + #include <linux/pm_runtime.h> 7 + #include <linux/usb/chipidea.h> 8 + #include <linux/clk.h> 9 + #include <linux/io.h> 10 + #include <linux/reset-controller.h> 11 + #include <linux/of.h> 12 + 13 + #include "ci.h" 14 + 15 + struct npcm_udc_data { 16 + struct platform_device *ci; 17 + struct clk *core_clk; 18 + struct ci_hdrc_platform_data pdata; 19 + }; 20 + 21 + static int npcm_udc_notify_event(struct ci_hdrc *ci, unsigned event) 22 + { 23 + struct device *dev = ci->dev->parent; 24 + 25 + switch (event) { 26 + case CI_HDRC_CONTROLLER_RESET_EVENT: 27 + /* clear all mode bits */ 28 + hw_write(ci, OP_USBMODE, 0xffffffff, 0x0); 29 + break; 30 + default: 31 + dev_dbg(dev, "unknown ci_hdrc event (%d)\n",event); 32 + break; 33 + } 34 + 35 + return 0; 36 + } 37 + 38 + static int npcm_udc_probe(struct platform_device *pdev) 39 + { 40 + int ret; 41 + struct npcm_udc_data *ci; 42 + struct platform_device *plat_ci; 43 + struct device *dev = &pdev->dev; 44 + 45 + ci = devm_kzalloc(&pdev->dev, sizeof(*ci), GFP_KERNEL); 46 + if (!ci) 47 + return -ENOMEM; 48 + platform_set_drvdata(pdev, ci); 49 + 50 + ci->core_clk = devm_clk_get_optional(dev, NULL); 51 + if (IS_ERR(ci->core_clk)) 52 + return PTR_ERR(ci->core_clk); 53 + 54 + ret = clk_prepare_enable(ci->core_clk); 55 + if (ret) 56 + return dev_err_probe(dev, ret, "failed to enable the clock: %d\n", ret); 57 + 58 + ci->pdata.name = dev_name(dev); 59 + ci->pdata.capoffset = DEF_CAPOFFSET; 60 + ci->pdata.flags = CI_HDRC_REQUIRES_ALIGNED_DMA | 61 + CI_HDRC_FORCE_VBUS_ACTIVE_ALWAYS; 62 + ci->pdata.phy_mode = USBPHY_INTERFACE_MODE_UTMI; 63 + ci->pdata.notify_event = npcm_udc_notify_event; 64 + 65 + plat_ci = ci_hdrc_add_device(dev, pdev->resource, pdev->num_resources, 66 + &ci->pdata); 67 + if (IS_ERR(plat_ci)) { 68 + ret = PTR_ERR(plat_ci); 69 + dev_err(dev, "failed to register HDRC NPCM device: %d\n", ret); 70 + goto clk_err; 71 + } 72 + 73 + pm_runtime_no_callbacks(dev); 74 + pm_runtime_enable(dev); 75 + 76 + return 0; 77 + 78 + clk_err: 79 + clk_disable_unprepare(ci->core_clk); 80 + return ret; 81 + } 82 + 83 + static int npcm_udc_remove(struct platform_device *pdev) 84 + { 85 + struct npcm_udc_data *ci = platform_get_drvdata(pdev); 86 + 87 + pm_runtime_disable(&pdev->dev); 88 + ci_hdrc_remove_device(ci->ci); 89 + clk_disable_unprepare(ci->core_clk); 90 + 91 + return 0; 92 + } 93 + 94 + static const struct of_device_id npcm_udc_dt_match[] = { 95 + { .compatible = "nuvoton,npcm750-udc", }, 96 + { .compatible = "nuvoton,npcm845-udc", }, 97 + { } 98 + }; 99 + MODULE_DEVICE_TABLE(of, npcm_udc_dt_match); 100 + 101 + static struct platform_driver npcm_udc_driver = { 102 + .probe = npcm_udc_probe, 103 + .remove = npcm_udc_remove, 104 + .driver = { 105 + .name = "npcm_udc", 106 + .of_match_table = npcm_udc_dt_match, 107 + }, 108 + }; 109 + 110 + module_platform_driver(npcm_udc_driver); 111 + 112 + MODULE_DESCRIPTION("NPCM USB device controller driver"); 113 + MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>"); 114 + MODULE_LICENSE("GPL v2");