Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * linux/drivers/regulator/aat2870-regulator.c
0004  *
0005  * Copyright (c) 2011, NVIDIA Corporation.
0006  * Author: Jin Park <jinyoungp@nvidia.com>
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/init.h>
0011 #include <linux/err.h>
0012 #include <linux/module.h>
0013 #include <linux/slab.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/regulator/driver.h>
0016 #include <linux/regulator/machine.h>
0017 #include <linux/mfd/aat2870.h>
0018 
0019 struct aat2870_regulator {
0020     struct aat2870_data *aat2870;
0021     struct regulator_desc desc;
0022 
0023     u8 enable_addr;
0024     u8 enable_shift;
0025     u8 enable_mask;
0026 
0027     u8 voltage_addr;
0028     u8 voltage_shift;
0029     u8 voltage_mask;
0030 };
0031 
0032 static int aat2870_ldo_set_voltage_sel(struct regulator_dev *rdev,
0033                        unsigned selector)
0034 {
0035     struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
0036     struct aat2870_data *aat2870 = ri->aat2870;
0037 
0038     return aat2870->update(aat2870, ri->voltage_addr, ri->voltage_mask,
0039                    selector << ri->voltage_shift);
0040 }
0041 
0042 static int aat2870_ldo_get_voltage_sel(struct regulator_dev *rdev)
0043 {
0044     struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
0045     struct aat2870_data *aat2870 = ri->aat2870;
0046     u8 val;
0047     int ret;
0048 
0049     ret = aat2870->read(aat2870, ri->voltage_addr, &val);
0050     if (ret)
0051         return ret;
0052 
0053     return (val & ri->voltage_mask) >> ri->voltage_shift;
0054 }
0055 
0056 static int aat2870_ldo_enable(struct regulator_dev *rdev)
0057 {
0058     struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
0059     struct aat2870_data *aat2870 = ri->aat2870;
0060 
0061     return aat2870->update(aat2870, ri->enable_addr, ri->enable_mask,
0062                    ri->enable_mask);
0063 }
0064 
0065 static int aat2870_ldo_disable(struct regulator_dev *rdev)
0066 {
0067     struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
0068     struct aat2870_data *aat2870 = ri->aat2870;
0069 
0070     return aat2870->update(aat2870, ri->enable_addr, ri->enable_mask, 0);
0071 }
0072 
0073 static int aat2870_ldo_is_enabled(struct regulator_dev *rdev)
0074 {
0075     struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
0076     struct aat2870_data *aat2870 = ri->aat2870;
0077     u8 val;
0078     int ret;
0079 
0080     ret = aat2870->read(aat2870, ri->enable_addr, &val);
0081     if (ret)
0082         return ret;
0083 
0084     return val & ri->enable_mask ? 1 : 0;
0085 }
0086 
0087 static const struct regulator_ops aat2870_ldo_ops = {
0088     .list_voltage = regulator_list_voltage_table,
0089     .map_voltage = regulator_map_voltage_ascend,
0090     .set_voltage_sel = aat2870_ldo_set_voltage_sel,
0091     .get_voltage_sel = aat2870_ldo_get_voltage_sel,
0092     .enable = aat2870_ldo_enable,
0093     .disable = aat2870_ldo_disable,
0094     .is_enabled = aat2870_ldo_is_enabled,
0095 };
0096 
0097 static const unsigned int aat2870_ldo_voltages[] = {
0098     1200000, 1300000, 1500000, 1600000,
0099     1800000, 2000000, 2200000, 2500000,
0100     2600000, 2700000, 2800000, 2900000,
0101     3000000, 3100000, 3200000, 3300000,
0102 };
0103 
0104 #define AAT2870_LDO(ids)                \
0105     {                       \
0106         .desc = {               \
0107             .name = #ids,           \
0108             .id = AAT2870_ID_##ids,     \
0109             .n_voltages = ARRAY_SIZE(aat2870_ldo_voltages), \
0110             .volt_table = aat2870_ldo_voltages, \
0111             .ops = &aat2870_ldo_ops,    \
0112             .type = REGULATOR_VOLTAGE,  \
0113             .owner = THIS_MODULE,       \
0114         },                  \
0115     }
0116 
0117 static struct aat2870_regulator aat2870_regulators[] = {
0118     AAT2870_LDO(LDOA),
0119     AAT2870_LDO(LDOB),
0120     AAT2870_LDO(LDOC),
0121     AAT2870_LDO(LDOD),
0122 };
0123 
0124 static struct aat2870_regulator *aat2870_get_regulator(int id)
0125 {
0126     struct aat2870_regulator *ri = NULL;
0127     int i;
0128 
0129     for (i = 0; i < ARRAY_SIZE(aat2870_regulators); i++) {
0130         ri = &aat2870_regulators[i];
0131         if (ri->desc.id == id)
0132             break;
0133     }
0134 
0135     if (i == ARRAY_SIZE(aat2870_regulators))
0136         return NULL;
0137 
0138     ri->enable_addr = AAT2870_LDO_EN;
0139     ri->enable_shift = id - AAT2870_ID_LDOA;
0140     ri->enable_mask = 0x1 << ri->enable_shift;
0141 
0142     ri->voltage_addr = (id - AAT2870_ID_LDOA) / 2 ?
0143                AAT2870_LDO_CD : AAT2870_LDO_AB;
0144     ri->voltage_shift = (id - AAT2870_ID_LDOA) % 2 ? 0 : 4;
0145     ri->voltage_mask = 0xF << ri->voltage_shift;
0146 
0147     return ri;
0148 }
0149 
0150 static int aat2870_regulator_probe(struct platform_device *pdev)
0151 {
0152     struct aat2870_regulator *ri;
0153     struct regulator_config config = { };
0154     struct regulator_dev *rdev;
0155 
0156     ri = aat2870_get_regulator(pdev->id);
0157     if (!ri) {
0158         dev_err(&pdev->dev, "Invalid device ID, %d\n", pdev->id);
0159         return -EINVAL;
0160     }
0161     ri->aat2870 = dev_get_drvdata(pdev->dev.parent);
0162 
0163     config.dev = &pdev->dev;
0164     config.driver_data = ri;
0165     config.init_data = dev_get_platdata(&pdev->dev);
0166 
0167     rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
0168     if (IS_ERR(rdev)) {
0169         dev_err(&pdev->dev, "Failed to register regulator %s\n",
0170             ri->desc.name);
0171         return PTR_ERR(rdev);
0172     }
0173     platform_set_drvdata(pdev, rdev);
0174 
0175     return 0;
0176 }
0177 
0178 static struct platform_driver aat2870_regulator_driver = {
0179     .driver = {
0180         .name   = "aat2870-regulator",
0181     },
0182     .probe  = aat2870_regulator_probe,
0183 };
0184 
0185 static int __init aat2870_regulator_init(void)
0186 {
0187     return platform_driver_register(&aat2870_regulator_driver);
0188 }
0189 subsys_initcall(aat2870_regulator_init);
0190 
0191 static void __exit aat2870_regulator_exit(void)
0192 {
0193     platform_driver_unregister(&aat2870_regulator_driver);
0194 }
0195 module_exit(aat2870_regulator_exit);
0196 
0197 MODULE_DESCRIPTION("AnalogicTech AAT2870 Regulator");
0198 MODULE_LICENSE("GPL");
0199 MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");
0200 MODULE_ALIAS("platform:aat2870-regulator");