^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Regulator controller driver for UniPhier SoC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) // Copyright 2018 Socionext Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/regulator/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/regulator/of_regulator.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/reset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define MAX_CLKS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define MAX_RSTS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct uniphier_regulator_soc_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) int nclks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) const char * const *clock_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) int nrsts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) const char * const *reset_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) const struct regulator_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) const struct regmap_config *regconf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct uniphier_regulator_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct clk_bulk_data clk[MAX_CLKS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct reset_control *rst[MAX_RSTS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) const struct uniphier_regulator_soc_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static const struct regulator_ops uniphier_regulator_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) .enable = regulator_enable_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .disable = regulator_disable_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) .is_enabled = regulator_is_enabled_regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int uniphier_regulator_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct uniphier_regulator_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct regulator_config config = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct regulator_dev *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int i, ret, nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) priv->data = of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (WARN_ON(!priv->data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) base = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (IS_ERR(base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return PTR_ERR(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) for (i = 0; i < priv->data->nclks; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) priv->clk[i].id = priv->data->clock_names[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) ret = devm_clk_bulk_get(dev, priv->data->nclks, priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) for (i = 0; i < priv->data->nrsts; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) name = priv->data->reset_names[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) priv->rst[i] = devm_reset_control_get_shared(dev, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (IS_ERR(priv->rst[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return PTR_ERR(priv->rst[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) for (nr = 0; nr < priv->data->nrsts; nr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ret = reset_control_deassert(priv->rst[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) goto out_rst_assert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) regmap = devm_regmap_init_mmio(dev, base, priv->data->regconf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (IS_ERR(regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ret = PTR_ERR(regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) goto out_rst_assert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) config.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) config.driver_data = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) config.of_node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) config.regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) config.init_data = of_get_regulator_init_data(dev, dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) priv->data->desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) rdev = devm_regulator_register(dev, priv->data->desc, &config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (IS_ERR(rdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) ret = PTR_ERR(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) goto out_rst_assert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) platform_set_drvdata(pdev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) out_rst_assert:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) while (nr--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) reset_control_assert(priv->rst[nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static int uniphier_regulator_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct uniphier_regulator_priv *priv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) for (i = 0; i < priv->data->nrsts; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) reset_control_assert(priv->rst[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* USB3 controller data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define USB3VBUS_OFFSET 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define USB3VBUS_REG BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define USB3VBUS_REG_EN BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static const struct regulator_desc uniphier_usb3_regulator_desc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .name = "vbus",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .of_match = of_match_ptr("vbus"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .ops = &uniphier_regulator_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .type = REGULATOR_VOLTAGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .enable_reg = USB3VBUS_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .enable_mask = USB3VBUS_REG_EN | USB3VBUS_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .enable_val = USB3VBUS_REG_EN | USB3VBUS_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .disable_val = USB3VBUS_REG_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static const struct regmap_config uniphier_usb3_regulator_regconf = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .reg_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .val_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .reg_stride = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .max_register = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static const char * const uniphier_pro4_clock_reset_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) "gio", "link",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static const struct uniphier_regulator_soc_data uniphier_pro4_usb3_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .clock_names = uniphier_pro4_clock_reset_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .reset_names = uniphier_pro4_clock_reset_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .desc = &uniphier_usb3_regulator_desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .regconf = &uniphier_usb3_regulator_regconf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static const char * const uniphier_pxs2_clock_reset_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) "link",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static const struct uniphier_regulator_soc_data uniphier_pxs2_usb3_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .clock_names = uniphier_pxs2_clock_reset_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .reset_names = uniphier_pxs2_clock_reset_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .desc = &uniphier_usb3_regulator_desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .regconf = &uniphier_usb3_regulator_regconf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static const struct of_device_id uniphier_regulator_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* USB VBUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .compatible = "socionext,uniphier-pro4-usb3-regulator",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .data = &uniphier_pro4_usb3_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .compatible = "socionext,uniphier-pro5-usb3-regulator",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .data = &uniphier_pro4_usb3_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .compatible = "socionext,uniphier-pxs2-usb3-regulator",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .data = &uniphier_pxs2_usb3_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .compatible = "socionext,uniphier-ld20-usb3-regulator",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .data = &uniphier_pxs2_usb3_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .compatible = "socionext,uniphier-pxs3-usb3-regulator",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .data = &uniphier_pxs2_usb3_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) { /* Sentinel */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) MODULE_DEVICE_TABLE(of, uniphier_regulator_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static struct platform_driver uniphier_regulator_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .probe = uniphier_regulator_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .remove = uniphier_regulator_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .name = "uniphier-regulator",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .of_match_table = uniphier_regulator_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) module_platform_driver(uniphier_regulator_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) MODULE_DESCRIPTION("UniPhier Regulator Controller Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) MODULE_LICENSE("GPL");