Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Broadcom BCM590xx regulator driver
0004  *
0005  * Copyright 2014 Linaro Limited
0006  * Author: Matt Porter <mporter@linaro.org>
0007  */
0008 
0009 #include <linux/err.h>
0010 #include <linux/init.h>
0011 #include <linux/kernel.h>
0012 #include <linux/mfd/bcm590xx.h>
0013 #include <linux/module.h>
0014 #include <linux/of.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/regulator/driver.h>
0017 #include <linux/regulator/machine.h>
0018 #include <linux/regulator/of_regulator.h>
0019 #include <linux/slab.h>
0020 
0021 /* I2C slave 0 registers */
0022 #define BCM590XX_RFLDOPMCTRL1   0x60
0023 #define BCM590XX_IOSR1PMCTRL1   0x7a
0024 #define BCM590XX_IOSR2PMCTRL1   0x7c
0025 #define BCM590XX_CSRPMCTRL1 0x7e
0026 #define BCM590XX_SDSR1PMCTRL1   0x82
0027 #define BCM590XX_SDSR2PMCTRL1   0x86
0028 #define BCM590XX_MSRPMCTRL1 0x8a
0029 #define BCM590XX_VSRPMCTRL1 0x8e
0030 #define BCM590XX_RFLDOCTRL  0x96
0031 #define BCM590XX_CSRVOUT1   0xc0
0032 
0033 /* I2C slave 1 registers */
0034 #define BCM590XX_GPLDO5PMCTRL1  0x16
0035 #define BCM590XX_GPLDO6PMCTRL1  0x18
0036 #define BCM590XX_GPLDO1CTRL 0x1a
0037 #define BCM590XX_GPLDO2CTRL 0x1b
0038 #define BCM590XX_GPLDO3CTRL 0x1c
0039 #define BCM590XX_GPLDO4CTRL 0x1d
0040 #define BCM590XX_GPLDO5CTRL 0x1e
0041 #define BCM590XX_GPLDO6CTRL 0x1f
0042 #define BCM590XX_OTG_CTRL   0x40
0043 #define BCM590XX_GPLDO1PMCTRL1  0x57
0044 #define BCM590XX_GPLDO2PMCTRL1  0x59
0045 #define BCM590XX_GPLDO3PMCTRL1  0x5b
0046 #define BCM590XX_GPLDO4PMCTRL1  0x5d
0047 
0048 #define BCM590XX_REG_ENABLE BIT(7)
0049 #define BCM590XX_VBUS_ENABLE    BIT(2)
0050 #define BCM590XX_LDO_VSEL_MASK  GENMASK(5, 3)
0051 #define BCM590XX_SR_VSEL_MASK   GENMASK(5, 0)
0052 
0053 /*
0054  * RFLDO to VSR regulators are
0055  * accessed via I2C slave 0
0056  */
0057 
0058 /* LDO regulator IDs */
0059 #define BCM590XX_REG_RFLDO  0
0060 #define BCM590XX_REG_CAMLDO1    1
0061 #define BCM590XX_REG_CAMLDO2    2
0062 #define BCM590XX_REG_SIMLDO1    3
0063 #define BCM590XX_REG_SIMLDO2    4
0064 #define BCM590XX_REG_SDLDO  5
0065 #define BCM590XX_REG_SDXLDO 6
0066 #define BCM590XX_REG_MMCLDO1    7
0067 #define BCM590XX_REG_MMCLDO2    8
0068 #define BCM590XX_REG_AUDLDO 9
0069 #define BCM590XX_REG_MICLDO 10
0070 #define BCM590XX_REG_USBLDO 11
0071 #define BCM590XX_REG_VIBLDO 12
0072 
0073 /* DCDC regulator IDs */
0074 #define BCM590XX_REG_CSR    13
0075 #define BCM590XX_REG_IOSR1  14
0076 #define BCM590XX_REG_IOSR2  15
0077 #define BCM590XX_REG_MSR    16
0078 #define BCM590XX_REG_SDSR1  17
0079 #define BCM590XX_REG_SDSR2  18
0080 #define BCM590XX_REG_VSR    19
0081 
0082 /*
0083  * GPLDO1 to VBUS regulators are
0084  * accessed via I2C slave 1
0085  */
0086 
0087 #define BCM590XX_REG_GPLDO1 20
0088 #define BCM590XX_REG_GPLDO2 21
0089 #define BCM590XX_REG_GPLDO3 22
0090 #define BCM590XX_REG_GPLDO4 23
0091 #define BCM590XX_REG_GPLDO5 24
0092 #define BCM590XX_REG_GPLDO6 25
0093 #define BCM590XX_REG_VBUS   26
0094 
0095 #define BCM590XX_NUM_REGS   27
0096 
0097 #define BCM590XX_REG_IS_LDO(n)  (n < BCM590XX_REG_CSR)
0098 #define BCM590XX_REG_IS_GPLDO(n) \
0099     ((n > BCM590XX_REG_VSR) && (n < BCM590XX_REG_VBUS))
0100 #define BCM590XX_REG_IS_VBUS(n) (n == BCM590XX_REG_VBUS)
0101 
0102 /* LDO group A: supported voltages in microvolts */
0103 static const unsigned int ldo_a_table[] = {
0104     1200000, 1800000, 2500000, 2700000, 2800000,
0105     2900000, 3000000, 3300000,
0106 };
0107 
0108 /* LDO group C: supported voltages in microvolts */
0109 static const unsigned int ldo_c_table[] = {
0110     3100000, 1800000, 2500000, 2700000, 2800000,
0111     2900000, 3000000, 3300000,
0112 };
0113 
0114 static const unsigned int ldo_vbus[] = {
0115     5000000,
0116 };
0117 
0118 /* DCDC group CSR: supported voltages in microvolts */
0119 static const struct linear_range dcdc_csr_ranges[] = {
0120     REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
0121     REGULATOR_LINEAR_RANGE(1360000, 51, 55, 20000),
0122     REGULATOR_LINEAR_RANGE(900000, 56, 63, 0),
0123 };
0124 
0125 /* DCDC group IOSR1: supported voltages in microvolts */
0126 static const struct linear_range dcdc_iosr1_ranges[] = {
0127     REGULATOR_LINEAR_RANGE(860000, 2, 51, 10000),
0128     REGULATOR_LINEAR_RANGE(1500000, 52, 52, 0),
0129     REGULATOR_LINEAR_RANGE(1800000, 53, 53, 0),
0130     REGULATOR_LINEAR_RANGE(900000, 54, 63, 0),
0131 };
0132 
0133 /* DCDC group SDSR1: supported voltages in microvolts */
0134 static const struct linear_range dcdc_sdsr1_ranges[] = {
0135     REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
0136     REGULATOR_LINEAR_RANGE(1340000, 51, 51, 0),
0137     REGULATOR_LINEAR_RANGE(900000, 52, 63, 0),
0138 };
0139 
0140 struct bcm590xx_info {
0141     const char *name;
0142     const char *vin_name;
0143     u8 n_voltages;
0144     const unsigned int *volt_table;
0145     u8 n_linear_ranges;
0146     const struct linear_range *linear_ranges;
0147 };
0148 
0149 #define BCM590XX_REG_TABLE(_name, _table) \
0150     { \
0151         .name = #_name, \
0152         .n_voltages = ARRAY_SIZE(_table), \
0153         .volt_table = _table, \
0154     }
0155 
0156 #define BCM590XX_REG_RANGES(_name, _ranges) \
0157     { \
0158         .name = #_name, \
0159         .n_voltages = 64, \
0160         .n_linear_ranges = ARRAY_SIZE(_ranges), \
0161         .linear_ranges = _ranges, \
0162     }
0163 
0164 static struct bcm590xx_info bcm590xx_regs[] = {
0165     BCM590XX_REG_TABLE(rfldo, ldo_a_table),
0166     BCM590XX_REG_TABLE(camldo1, ldo_c_table),
0167     BCM590XX_REG_TABLE(camldo2, ldo_c_table),
0168     BCM590XX_REG_TABLE(simldo1, ldo_a_table),
0169     BCM590XX_REG_TABLE(simldo2, ldo_a_table),
0170     BCM590XX_REG_TABLE(sdldo, ldo_c_table),
0171     BCM590XX_REG_TABLE(sdxldo, ldo_a_table),
0172     BCM590XX_REG_TABLE(mmcldo1, ldo_a_table),
0173     BCM590XX_REG_TABLE(mmcldo2, ldo_a_table),
0174     BCM590XX_REG_TABLE(audldo, ldo_a_table),
0175     BCM590XX_REG_TABLE(micldo, ldo_a_table),
0176     BCM590XX_REG_TABLE(usbldo, ldo_a_table),
0177     BCM590XX_REG_TABLE(vibldo, ldo_c_table),
0178     BCM590XX_REG_RANGES(csr, dcdc_csr_ranges),
0179     BCM590XX_REG_RANGES(iosr1, dcdc_iosr1_ranges),
0180     BCM590XX_REG_RANGES(iosr2, dcdc_iosr1_ranges),
0181     BCM590XX_REG_RANGES(msr, dcdc_iosr1_ranges),
0182     BCM590XX_REG_RANGES(sdsr1, dcdc_sdsr1_ranges),
0183     BCM590XX_REG_RANGES(sdsr2, dcdc_iosr1_ranges),
0184     BCM590XX_REG_RANGES(vsr, dcdc_iosr1_ranges),
0185     BCM590XX_REG_TABLE(gpldo1, ldo_a_table),
0186     BCM590XX_REG_TABLE(gpldo2, ldo_a_table),
0187     BCM590XX_REG_TABLE(gpldo3, ldo_a_table),
0188     BCM590XX_REG_TABLE(gpldo4, ldo_a_table),
0189     BCM590XX_REG_TABLE(gpldo5, ldo_a_table),
0190     BCM590XX_REG_TABLE(gpldo6, ldo_a_table),
0191     BCM590XX_REG_TABLE(vbus, ldo_vbus),
0192 };
0193 
0194 struct bcm590xx_reg {
0195     struct regulator_desc *desc;
0196     struct bcm590xx *mfd;
0197 };
0198 
0199 static int bcm590xx_get_vsel_register(int id)
0200 {
0201     if (BCM590XX_REG_IS_LDO(id))
0202         return BCM590XX_RFLDOCTRL + id;
0203     else if (BCM590XX_REG_IS_GPLDO(id))
0204         return BCM590XX_GPLDO1CTRL + id;
0205     else
0206         return BCM590XX_CSRVOUT1 + (id - BCM590XX_REG_CSR) * 3;
0207 }
0208 
0209 static int bcm590xx_get_enable_register(int id)
0210 {
0211     int reg = 0;
0212 
0213     if (BCM590XX_REG_IS_LDO(id))
0214         reg = BCM590XX_RFLDOPMCTRL1 + id * 2;
0215     else if (BCM590XX_REG_IS_GPLDO(id))
0216         reg = BCM590XX_GPLDO1PMCTRL1 + id * 2;
0217     else
0218         switch (id) {
0219         case BCM590XX_REG_CSR:
0220             reg = BCM590XX_CSRPMCTRL1;
0221             break;
0222         case BCM590XX_REG_IOSR1:
0223             reg = BCM590XX_IOSR1PMCTRL1;
0224             break;
0225         case BCM590XX_REG_IOSR2:
0226             reg = BCM590XX_IOSR2PMCTRL1;
0227             break;
0228         case BCM590XX_REG_MSR:
0229             reg = BCM590XX_MSRPMCTRL1;
0230             break;
0231         case BCM590XX_REG_SDSR1:
0232             reg = BCM590XX_SDSR1PMCTRL1;
0233             break;
0234         case BCM590XX_REG_SDSR2:
0235             reg = BCM590XX_SDSR2PMCTRL1;
0236             break;
0237         case BCM590XX_REG_VSR:
0238             reg = BCM590XX_VSRPMCTRL1;
0239             break;
0240         case BCM590XX_REG_VBUS:
0241             reg = BCM590XX_OTG_CTRL;
0242             break;
0243         }
0244 
0245 
0246     return reg;
0247 }
0248 
0249 static const struct regulator_ops bcm590xx_ops_ldo = {
0250     .is_enabled     = regulator_is_enabled_regmap,
0251     .enable         = regulator_enable_regmap,
0252     .disable        = regulator_disable_regmap,
0253     .get_voltage_sel    = regulator_get_voltage_sel_regmap,
0254     .set_voltage_sel    = regulator_set_voltage_sel_regmap,
0255     .list_voltage       = regulator_list_voltage_table,
0256     .map_voltage        = regulator_map_voltage_iterate,
0257 };
0258 
0259 static const struct regulator_ops bcm590xx_ops_dcdc = {
0260     .is_enabled     = regulator_is_enabled_regmap,
0261     .enable         = regulator_enable_regmap,
0262     .disable        = regulator_disable_regmap,
0263     .get_voltage_sel    = regulator_get_voltage_sel_regmap,
0264     .set_voltage_sel    = regulator_set_voltage_sel_regmap,
0265     .list_voltage       = regulator_list_voltage_linear_range,
0266     .map_voltage        = regulator_map_voltage_linear_range,
0267 };
0268 
0269 static const struct regulator_ops bcm590xx_ops_vbus = {
0270     .is_enabled     = regulator_is_enabled_regmap,
0271     .enable         = regulator_enable_regmap,
0272     .disable        = regulator_disable_regmap,
0273 };
0274 
0275 static int bcm590xx_probe(struct platform_device *pdev)
0276 {
0277     struct bcm590xx *bcm590xx = dev_get_drvdata(pdev->dev.parent);
0278     struct bcm590xx_reg *pmu;
0279     struct regulator_config config = { };
0280     struct bcm590xx_info *info;
0281     struct regulator_dev *rdev;
0282     int i;
0283 
0284     pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
0285     if (!pmu)
0286         return -ENOMEM;
0287 
0288     pmu->mfd = bcm590xx;
0289 
0290     platform_set_drvdata(pdev, pmu);
0291 
0292     pmu->desc = devm_kcalloc(&pdev->dev,
0293                  BCM590XX_NUM_REGS,
0294                  sizeof(struct regulator_desc),
0295                  GFP_KERNEL);
0296     if (!pmu->desc)
0297         return -ENOMEM;
0298 
0299     info = bcm590xx_regs;
0300 
0301     for (i = 0; i < BCM590XX_NUM_REGS; i++, info++) {
0302         /* Register the regulators */
0303         pmu->desc[i].name = info->name;
0304         pmu->desc[i].of_match = of_match_ptr(info->name);
0305         pmu->desc[i].regulators_node = of_match_ptr("regulators");
0306         pmu->desc[i].supply_name = info->vin_name;
0307         pmu->desc[i].id = i;
0308         pmu->desc[i].volt_table = info->volt_table;
0309         pmu->desc[i].n_voltages = info->n_voltages;
0310         pmu->desc[i].linear_ranges = info->linear_ranges;
0311         pmu->desc[i].n_linear_ranges = info->n_linear_ranges;
0312 
0313         if ((BCM590XX_REG_IS_LDO(i)) || (BCM590XX_REG_IS_GPLDO(i))) {
0314             pmu->desc[i].ops = &bcm590xx_ops_ldo;
0315             pmu->desc[i].vsel_mask = BCM590XX_LDO_VSEL_MASK;
0316         } else if (BCM590XX_REG_IS_VBUS(i))
0317             pmu->desc[i].ops = &bcm590xx_ops_vbus;
0318         else {
0319             pmu->desc[i].ops = &bcm590xx_ops_dcdc;
0320             pmu->desc[i].vsel_mask = BCM590XX_SR_VSEL_MASK;
0321         }
0322 
0323         if (BCM590XX_REG_IS_VBUS(i))
0324             pmu->desc[i].enable_mask = BCM590XX_VBUS_ENABLE;
0325         else {
0326             pmu->desc[i].vsel_reg = bcm590xx_get_vsel_register(i);
0327             pmu->desc[i].enable_is_inverted = true;
0328             pmu->desc[i].enable_mask = BCM590XX_REG_ENABLE;
0329         }
0330         pmu->desc[i].enable_reg = bcm590xx_get_enable_register(i);
0331         pmu->desc[i].type = REGULATOR_VOLTAGE;
0332         pmu->desc[i].owner = THIS_MODULE;
0333 
0334         config.dev = bcm590xx->dev;
0335         config.driver_data = pmu;
0336         if (BCM590XX_REG_IS_GPLDO(i) || BCM590XX_REG_IS_VBUS(i))
0337             config.regmap = bcm590xx->regmap_sec;
0338         else
0339             config.regmap = bcm590xx->regmap_pri;
0340 
0341         rdev = devm_regulator_register(&pdev->dev, &pmu->desc[i],
0342                            &config);
0343         if (IS_ERR(rdev)) {
0344             dev_err(bcm590xx->dev,
0345                 "failed to register %s regulator\n",
0346                 pdev->name);
0347             return PTR_ERR(rdev);
0348         }
0349     }
0350 
0351     return 0;
0352 }
0353 
0354 static struct platform_driver bcm590xx_regulator_driver = {
0355     .driver = {
0356         .name = "bcm590xx-vregs",
0357     },
0358     .probe = bcm590xx_probe,
0359 };
0360 module_platform_driver(bcm590xx_regulator_driver);
0361 
0362 MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
0363 MODULE_DESCRIPTION("BCM590xx voltage regulator driver");
0364 MODULE_LICENSE("GPL v2");
0365 MODULE_ALIAS("platform:bcm590xx-vregs");