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

reset: renesas: Add RZ/G2L usbphy control driver

Add support for RZ/G2L USBPHY Control driver. It mainly controls
reset and power down of the USB/PHY.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20210719121938.6532-5-biju.das.jz@bp.renesas.com
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>

authored by

Biju Das and committed by
Philipp Zabel
bee08559 18931afe

+183
+7
drivers/reset/Kconfig
··· 181 181 interfacing with RPi4's co-processor and model these firmware 182 182 initialization routines as reset lines. 183 183 184 + config RESET_RZG2L_USBPHY_CTRL 185 + tristate "Renesas RZ/G2L USBPHY control driver" 186 + depends on ARCH_R9A07G044 || COMPILE_TEST 187 + help 188 + Support for USBPHY Control found on RZ/G2L family. It mainly 189 + controls reset and power down of the USB/PHY. 190 + 184 191 config RESET_SCMI 185 192 tristate "Reset driver controlled via ARM SCMI interface" 186 193 depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
+1
drivers/reset/Makefile
··· 25 25 obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o 26 26 obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o 27 27 obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o 28 + obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o 28 29 obj-$(CONFIG_RESET_SCMI) += reset-scmi.o 29 30 obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o 30 31 obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
+175
drivers/reset/reset-rzg2l-usbphy-ctrl.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Renesas RZ/G2L USBPHY control driver 4 + * 5 + * Copyright (C) 2021 Renesas Electronics Corporation 6 + */ 7 + 8 + #include <linux/io.h> 9 + #include <linux/module.h> 10 + #include <linux/of.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/pm_runtime.h> 13 + #include <linux/reset.h> 14 + #include <linux/reset-controller.h> 15 + 16 + #define RESET 0x000 17 + 18 + #define RESET_SEL_PLLRESET BIT(12) 19 + #define RESET_PLLRESET BIT(8) 20 + 21 + #define RESET_SEL_P2RESET BIT(5) 22 + #define RESET_SEL_P1RESET BIT(4) 23 + #define RESET_PHYRST_2 BIT(1) 24 + #define RESET_PHYRST_1 BIT(0) 25 + 26 + #define PHY_RESET_PORT2 (RESET_SEL_P2RESET | RESET_PHYRST_2) 27 + #define PHY_RESET_PORT1 (RESET_SEL_P1RESET | RESET_PHYRST_1) 28 + 29 + #define NUM_PORTS 2 30 + 31 + struct rzg2l_usbphy_ctrl_priv { 32 + struct reset_controller_dev rcdev; 33 + struct reset_control *rstc; 34 + void __iomem *base; 35 + 36 + spinlock_t lock; 37 + }; 38 + 39 + #define rcdev_to_priv(x) container_of(x, struct rzg2l_usbphy_ctrl_priv, rcdev) 40 + 41 + static int rzg2l_usbphy_ctrl_assert(struct reset_controller_dev *rcdev, 42 + unsigned long id) 43 + { 44 + struct rzg2l_usbphy_ctrl_priv *priv = rcdev_to_priv(rcdev); 45 + u32 port_mask = PHY_RESET_PORT1 | PHY_RESET_PORT2; 46 + void __iomem *base = priv->base; 47 + unsigned long flags; 48 + u32 val; 49 + 50 + spin_lock_irqsave(&priv->lock, flags); 51 + val = readl(base + RESET); 52 + val |= id ? PHY_RESET_PORT2 : PHY_RESET_PORT1; 53 + if (port_mask == (val & port_mask)) 54 + val |= RESET_PLLRESET; 55 + writel(val, base + RESET); 56 + spin_unlock_irqrestore(&priv->lock, flags); 57 + 58 + return 0; 59 + } 60 + 61 + static int rzg2l_usbphy_ctrl_deassert(struct reset_controller_dev *rcdev, 62 + unsigned long id) 63 + { 64 + struct rzg2l_usbphy_ctrl_priv *priv = rcdev_to_priv(rcdev); 65 + void __iomem *base = priv->base; 66 + unsigned long flags; 67 + u32 val; 68 + 69 + spin_lock_irqsave(&priv->lock, flags); 70 + val = readl(base + RESET); 71 + 72 + val |= RESET_SEL_PLLRESET; 73 + val &= ~(RESET_PLLRESET | (id ? PHY_RESET_PORT2 : PHY_RESET_PORT1)); 74 + writel(val, base + RESET); 75 + spin_unlock_irqrestore(&priv->lock, flags); 76 + 77 + return 0; 78 + } 79 + 80 + static int rzg2l_usbphy_ctrl_status(struct reset_controller_dev *rcdev, 81 + unsigned long id) 82 + { 83 + struct rzg2l_usbphy_ctrl_priv *priv = rcdev_to_priv(rcdev); 84 + u32 port_mask; 85 + 86 + port_mask = id ? PHY_RESET_PORT2 : PHY_RESET_PORT1; 87 + 88 + return !!(readl(priv->base + RESET) & port_mask); 89 + } 90 + 91 + static const struct of_device_id rzg2l_usbphy_ctrl_match_table[] = { 92 + { .compatible = "renesas,rzg2l-usbphy-ctrl" }, 93 + { /* Sentinel */ } 94 + }; 95 + MODULE_DEVICE_TABLE(of, rzg2l_usbphy_ctrl_match_table); 96 + 97 + static const struct reset_control_ops rzg2l_usbphy_ctrl_reset_ops = { 98 + .assert = rzg2l_usbphy_ctrl_assert, 99 + .deassert = rzg2l_usbphy_ctrl_deassert, 100 + .status = rzg2l_usbphy_ctrl_status, 101 + }; 102 + 103 + static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev) 104 + { 105 + struct device *dev = &pdev->dev; 106 + struct rzg2l_usbphy_ctrl_priv *priv; 107 + unsigned long flags; 108 + int error; 109 + u32 val; 110 + 111 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 112 + if (!priv) 113 + return -ENOMEM; 114 + 115 + priv->base = devm_platform_ioremap_resource(pdev, 0); 116 + if (IS_ERR(priv->base)) 117 + return PTR_ERR(priv->base); 118 + 119 + priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); 120 + if (IS_ERR(priv->rstc)) 121 + return dev_err_probe(dev, PTR_ERR(priv->rstc), 122 + "failed to get reset\n"); 123 + 124 + reset_control_deassert(priv->rstc); 125 + 126 + priv->rcdev.ops = &rzg2l_usbphy_ctrl_reset_ops; 127 + priv->rcdev.of_reset_n_cells = 1; 128 + priv->rcdev.nr_resets = NUM_PORTS; 129 + priv->rcdev.of_node = dev->of_node; 130 + priv->rcdev.dev = dev; 131 + 132 + error = devm_reset_controller_register(dev, &priv->rcdev); 133 + if (error) 134 + return error; 135 + 136 + spin_lock_init(&priv->lock); 137 + dev_set_drvdata(dev, priv); 138 + 139 + pm_runtime_enable(&pdev->dev); 140 + pm_runtime_resume_and_get(&pdev->dev); 141 + 142 + /* put pll and phy into reset state */ 143 + spin_lock_irqsave(&priv->lock, flags); 144 + val = readl(priv->base + RESET); 145 + val |= RESET_SEL_PLLRESET | RESET_PLLRESET | PHY_RESET_PORT2 | PHY_RESET_PORT1; 146 + writel(val, priv->base + RESET); 147 + spin_unlock_irqrestore(&priv->lock, flags); 148 + 149 + return 0; 150 + } 151 + 152 + static int rzg2l_usbphy_ctrl_remove(struct platform_device *pdev) 153 + { 154 + struct rzg2l_usbphy_ctrl_priv *priv = dev_get_drvdata(&pdev->dev); 155 + 156 + pm_runtime_put(&pdev->dev); 157 + pm_runtime_disable(&pdev->dev); 158 + reset_control_assert(priv->rstc); 159 + 160 + return 0; 161 + } 162 + 163 + static struct platform_driver rzg2l_usbphy_ctrl_driver = { 164 + .driver = { 165 + .name = "rzg2l_usbphy_ctrl", 166 + .of_match_table = rzg2l_usbphy_ctrl_match_table, 167 + }, 168 + .probe = rzg2l_usbphy_ctrl_probe, 169 + .remove = rzg2l_usbphy_ctrl_remove, 170 + }; 171 + module_platform_driver(rzg2l_usbphy_ctrl_driver); 172 + 173 + MODULE_LICENSE("GPL v2"); 174 + MODULE_DESCRIPTION("Renesas RZ/G2L USBPHY Control"); 175 + MODULE_AUTHOR("biju.das.jz@bp.renesas.com>");