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

Configure Feed

Select the types of activity you want to include in your feed.

at v6.4 139 lines 3.5 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Renesas RZ/V2M USB3DRD driver 4 * 5 * Copyright (C) 2022 Renesas Electronics Corporation 6 */ 7 8#include <linux/io.h> 9#include <linux/of_platform.h> 10#include <linux/platform_device.h> 11#include <linux/pm_runtime.h> 12#include <linux/reset.h> 13#include <linux/usb/rzv2m_usb3drd.h> 14 15#define USB_PERI_DRD_CON 0x000 16 17#define USB_PERI_DRD_CON_PERI_RST BIT(31) 18#define USB_PERI_DRD_CON_HOST_RST BIT(30) 19#define USB_PERI_DRD_CON_PERI_CON BIT(24) 20 21static void rzv2m_usb3drd_set_bit(struct rzv2m_usb3drd *usb3, u32 bits, 22 u32 offs) 23{ 24 u32 val = readl(usb3->reg + offs); 25 26 val |= bits; 27 writel(val, usb3->reg + offs); 28} 29 30static void rzv2m_usb3drd_clear_bit(struct rzv2m_usb3drd *usb3, u32 bits, 31 u32 offs) 32{ 33 u32 val = readl(usb3->reg + offs); 34 35 val &= ~bits; 36 writel(val, usb3->reg + offs); 37} 38 39void rzv2m_usb3drd_reset(struct device *dev, bool host) 40{ 41 struct rzv2m_usb3drd *usb3 = dev_get_drvdata(dev); 42 43 if (host) { 44 rzv2m_usb3drd_clear_bit(usb3, USB_PERI_DRD_CON_PERI_CON, 45 USB_PERI_DRD_CON); 46 rzv2m_usb3drd_clear_bit(usb3, USB_PERI_DRD_CON_HOST_RST, 47 USB_PERI_DRD_CON); 48 rzv2m_usb3drd_set_bit(usb3, USB_PERI_DRD_CON_PERI_RST, 49 USB_PERI_DRD_CON); 50 } else { 51 rzv2m_usb3drd_set_bit(usb3, USB_PERI_DRD_CON_PERI_CON, 52 USB_PERI_DRD_CON); 53 rzv2m_usb3drd_set_bit(usb3, USB_PERI_DRD_CON_HOST_RST, 54 USB_PERI_DRD_CON); 55 rzv2m_usb3drd_clear_bit(usb3, USB_PERI_DRD_CON_PERI_RST, 56 USB_PERI_DRD_CON); 57 } 58} 59EXPORT_SYMBOL_GPL(rzv2m_usb3drd_reset); 60 61static int rzv2m_usb3drd_remove(struct platform_device *pdev) 62{ 63 struct rzv2m_usb3drd *usb3 = platform_get_drvdata(pdev); 64 65 of_platform_depopulate(usb3->dev); 66 pm_runtime_put(usb3->dev); 67 pm_runtime_disable(&pdev->dev); 68 reset_control_assert(usb3->drd_rstc); 69 70 return 0; 71} 72 73static int rzv2m_usb3drd_probe(struct platform_device *pdev) 74{ 75 struct rzv2m_usb3drd *usb3; 76 int ret; 77 78 usb3 = devm_kzalloc(&pdev->dev, sizeof(*usb3), GFP_KERNEL); 79 if (!usb3) 80 return -ENOMEM; 81 82 usb3->dev = &pdev->dev; 83 84 usb3->drd_irq = platform_get_irq_byname(pdev, "drd"); 85 if (usb3->drd_irq < 0) 86 return usb3->drd_irq; 87 88 usb3->reg = devm_platform_ioremap_resource(pdev, 0); 89 if (IS_ERR(usb3->reg)) 90 return PTR_ERR(usb3->reg); 91 92 platform_set_drvdata(pdev, usb3); 93 94 usb3->drd_rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); 95 if (IS_ERR(usb3->drd_rstc)) 96 return dev_err_probe(&pdev->dev, PTR_ERR(usb3->drd_rstc), 97 "failed to get drd reset"); 98 99 reset_control_deassert(usb3->drd_rstc); 100 pm_runtime_enable(&pdev->dev); 101 ret = pm_runtime_resume_and_get(usb3->dev); 102 if (ret) 103 goto err_rst; 104 105 ret = of_platform_populate(usb3->dev->of_node, NULL, NULL, usb3->dev); 106 if (ret) 107 goto err_pm; 108 109 return 0; 110 111err_pm: 112 pm_runtime_put(usb3->dev); 113 114err_rst: 115 pm_runtime_disable(&pdev->dev); 116 reset_control_assert(usb3->drd_rstc); 117 return ret; 118} 119 120static const struct of_device_id rzv2m_usb3drd_of_match[] = { 121 { .compatible = "renesas,rzv2m-usb3drd", }, 122 { /* Sentinel */ } 123}; 124MODULE_DEVICE_TABLE(of, rzv2m_usb3drd_of_match); 125 126static struct platform_driver rzv2m_usb3drd_driver = { 127 .driver = { 128 .name = "rzv2m-usb3drd", 129 .of_match_table = rzv2m_usb3drd_of_match, 130 }, 131 .probe = rzv2m_usb3drd_probe, 132 .remove = rzv2m_usb3drd_remove, 133}; 134module_platform_driver(rzv2m_usb3drd_driver); 135 136MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>"); 137MODULE_DESCRIPTION("Renesas RZ/V2M USB3DRD driver"); 138MODULE_LICENSE("GPL"); 139MODULE_ALIAS("platform:rzv2m_usb3drd");