diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
| commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
| tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/regulator | |
| parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) | |
Diffstat (limited to 'drivers/regulator')
| -rw-r--r-- | drivers/regulator/bq24022.c | 161 | ||||
| -rw-r--r-- | drivers/regulator/fan53555-regulator.c | 567 | ||||
| -rw-r--r-- | drivers/regulator/gpio-switch-regulator.c | 412 | ||||
| -rw-r--r-- | drivers/regulator/max77663-regulator.c | 928 | ||||
| -rw-r--r-- | drivers/regulator/max8907c-regulator.c | 421 | ||||
| -rw-r--r-- | drivers/regulator/ricoh583-regulator.c | 412 | ||||
| -rw-r--r-- | drivers/regulator/tps6591x-regulator.c | 955 |
7 files changed, 3856 insertions, 0 deletions
diff --git a/drivers/regulator/bq24022.c b/drivers/regulator/bq24022.c new file mode 100644 index 00000000000..068d488a4f7 --- /dev/null +++ b/drivers/regulator/bq24022.c | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | /* | ||
| 2 | * Support for TI bq24022 (bqTINY-II) Dual Input (USB/AC Adpater) | ||
| 3 | * 1-Cell Li-Ion Charger connected via GPIOs. | ||
| 4 | * | ||
| 5 | * Copyright (c) 2008 Philipp Zabel | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/err.h> | ||
| 17 | #include <linux/gpio.h> | ||
| 18 | #include <linux/regulator/bq24022.h> | ||
| 19 | #include <linux/regulator/driver.h> | ||
| 20 | |||
| 21 | |||
| 22 | static int bq24022_set_current_limit(struct regulator_dev *rdev, | ||
| 23 | int min_uA, int max_uA) | ||
| 24 | { | ||
| 25 | struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev); | ||
| 26 | |||
| 27 | dev_dbg(rdev_get_dev(rdev), "setting current limit to %s mA\n", | ||
| 28 | max_uA >= 500000 ? "500" : "100"); | ||
| 29 | |||
| 30 | /* REVISIT: maybe return error if min_uA != 0 ? */ | ||
| 31 | gpio_set_value(pdata->gpio_iset2, max_uA >= 500000); | ||
| 32 | return 0; | ||
| 33 | } | ||
| 34 | |||
| 35 | static int bq24022_get_current_limit(struct regulator_dev *rdev) | ||
| 36 | { | ||
| 37 | struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev); | ||
| 38 | |||
| 39 | return gpio_get_value(pdata->gpio_iset2) ? 500000 : 100000; | ||
| 40 | } | ||
| 41 | |||
| 42 | static int bq24022_enable(struct regulator_dev *rdev) | ||
| 43 | { | ||
| 44 | struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev); | ||
| 45 | |||
| 46 | dev_dbg(rdev_get_dev(rdev), "enabling charger\n"); | ||
| 47 | |||
| 48 | gpio_set_value(pdata->gpio_nce, 0); | ||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | static int bq24022_disable(struct regulator_dev *rdev) | ||
| 53 | { | ||
| 54 | struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev); | ||
| 55 | |||
| 56 | dev_dbg(rdev_get_dev(rdev), "disabling charger\n"); | ||
| 57 | |||
| 58 | gpio_set_value(pdata->gpio_nce, 1); | ||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | |||
| 62 | static int bq24022_is_enabled(struct regulator_dev *rdev) | ||
| 63 | { | ||
| 64 | struct bq24022_mach_info *pdata = rdev_get_drvdata(rdev); | ||
| 65 | |||
| 66 | return !gpio_get_value(pdata->gpio_nce); | ||
| 67 | } | ||
| 68 | |||
| 69 | static struct regulator_ops bq24022_ops = { | ||
| 70 | .set_current_limit = bq24022_set_current_limit, | ||
| 71 | .get_current_limit = bq24022_get_current_limit, | ||
| 72 | .enable = bq24022_enable, | ||
| 73 | .disable = bq24022_disable, | ||
| 74 | .is_enabled = bq24022_is_enabled, | ||
| 75 | }; | ||
| 76 | |||
| 77 | static struct regulator_desc bq24022_desc = { | ||
| 78 | .name = "bq24022", | ||
| 79 | .ops = &bq24022_ops, | ||
| 80 | .type = REGULATOR_CURRENT, | ||
| 81 | .owner = THIS_MODULE, | ||
| 82 | }; | ||
| 83 | |||
| 84 | static int __init bq24022_probe(struct platform_device *pdev) | ||
| 85 | { | ||
| 86 | struct bq24022_mach_info *pdata = pdev->dev.platform_data; | ||
| 87 | struct regulator_dev *bq24022; | ||
| 88 | int ret; | ||
| 89 | |||
| 90 | if (!pdata || !pdata->gpio_nce || !pdata->gpio_iset2) | ||
| 91 | return -EINVAL; | ||
| 92 | |||
| 93 | ret = gpio_request(pdata->gpio_nce, "ncharge_en"); | ||
| 94 | if (ret) { | ||
| 95 | dev_dbg(&pdev->dev, "couldn't request nCE GPIO: %d\n", | ||
| 96 | pdata->gpio_nce); | ||
| 97 | goto err_ce; | ||
| 98 | } | ||
| 99 | ret = gpio_request(pdata->gpio_iset2, "charge_mode"); | ||
| 100 | if (ret) { | ||
| 101 | dev_dbg(&pdev->dev, "couldn't request ISET2 GPIO: %d\n", | ||
| 102 | pdata->gpio_iset2); | ||
| 103 | goto err_iset2; | ||
| 104 | } | ||
| 105 | ret = gpio_direction_output(pdata->gpio_iset2, 0); | ||
| 106 | ret = gpio_direction_output(pdata->gpio_nce, 1); | ||
| 107 | |||
| 108 | bq24022 = regulator_register(&bq24022_desc, &pdev->dev, | ||
| 109 | pdata->init_data, pdata); | ||
| 110 | if (IS_ERR(bq24022)) { | ||
| 111 | dev_dbg(&pdev->dev, "couldn't register regulator\n"); | ||
| 112 | ret = PTR_ERR(bq24022); | ||
| 113 | goto err_reg; | ||
| 114 | } | ||
| 115 | platform_set_drvdata(pdev, bq24022); | ||
| 116 | dev_dbg(&pdev->dev, "registered regulator\n"); | ||
| 117 | |||
| 118 | return 0; | ||
| 119 | err_reg: | ||
| 120 | gpio_free(pdata->gpio_iset2); | ||
| 121 | err_iset2: | ||
| 122 | gpio_free(pdata->gpio_nce); | ||
| 123 | err_ce: | ||
| 124 | return ret; | ||
| 125 | } | ||
| 126 | |||
| 127 | static int __devexit bq24022_remove(struct platform_device *pdev) | ||
| 128 | { | ||
| 129 | struct bq24022_mach_info *pdata = pdev->dev.platform_data; | ||
| 130 | struct regulator_dev *bq24022 = platform_get_drvdata(pdev); | ||
| 131 | |||
| 132 | regulator_unregister(bq24022); | ||
| 133 | gpio_free(pdata->gpio_iset2); | ||
| 134 | gpio_free(pdata->gpio_nce); | ||
| 135 | |||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | static struct platform_driver bq24022_driver = { | ||
| 140 | .driver = { | ||
| 141 | .name = "bq24022", | ||
| 142 | }, | ||
| 143 | .remove = __devexit_p(bq24022_remove), | ||
| 144 | }; | ||
| 145 | |||
| 146 | static int __init bq24022_init(void) | ||
| 147 | { | ||
| 148 | return platform_driver_probe(&bq24022_driver, bq24022_probe); | ||
| 149 | } | ||
| 150 | |||
| 151 | static void __exit bq24022_exit(void) | ||
| 152 | { | ||
| 153 | platform_driver_unregister(&bq24022_driver); | ||
| 154 | } | ||
| 155 | |||
| 156 | module_init(bq24022_init); | ||
| 157 | module_exit(bq24022_exit); | ||
| 158 | |||
| 159 | MODULE_AUTHOR("Philipp Zabel"); | ||
| 160 | MODULE_DESCRIPTION("TI bq24022 Li-Ion Charger driver"); | ||
| 161 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/regulator/fan53555-regulator.c b/drivers/regulator/fan53555-regulator.c new file mode 100644 index 00000000000..13fa79c4ba3 --- /dev/null +++ b/drivers/regulator/fan53555-regulator.c | |||
| @@ -0,0 +1,567 @@ | |||
| 1 | /* | ||
| 2 | * driver/regultor/fan53555-regulator.c | ||
| 3 | * | ||
| 4 | * Driver for FAN53555UC00X, FAN53555UC01X, FAN53555UC03X, | ||
| 5 | * FAN53555UC04X, FAN53555UC05X | ||
| 6 | * | ||
| 7 | * Copyright (c) 2011, NVIDIA Corporation. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License as | ||
| 11 | * published by the Free Software Foundation version 2. | ||
| 12 | * | ||
| 13 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, | ||
| 14 | * whether express or implied; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 16 | * General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
| 21 | * 02111-1307, USA | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/kernel.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/err.h> | ||
| 28 | #include <linux/platform_device.h> | ||
| 29 | #include <linux/regulator/driver.h> | ||
| 30 | #include <linux/regulator/machine.h> | ||
| 31 | #include <linux/regulator/fan53555-regulator.h> | ||
| 32 | #include <linux/i2c.h> | ||
| 33 | #include <linux/delay.h> | ||
| 34 | #include <linux/slab.h> | ||
| 35 | |||
| 36 | /* Register definitions */ | ||
| 37 | #define FAN53555_REG_VSEL0 0 | ||
| 38 | #define FAN53555_REG_VSEL1 1 | ||
| 39 | #define FAN53555_REG_CONTROL 2 | ||
| 40 | #define FAN53555_REG_ID1 3 | ||
| 41 | #define FAN53555_REG_ID2 4 | ||
| 42 | #define FAN53555_REG_MONITOR 5 | ||
| 43 | |||
| 44 | #define FAN53555_VSEL_BUCK_EN BIT(7) | ||
| 45 | #define FAN53555_VSEL_MODE BIT(6) | ||
| 46 | #define FAN53555_VSEL_NSEL_SHIFT 0 | ||
| 47 | #define FAN53555_VSEL_NSEL_MASK 0x3F | ||
| 48 | |||
| 49 | #define FAN53555_CONTROL_DISCHARGE BIT(7) | ||
| 50 | #define FAN53555_CONTROL_SLEW_SHIFT 4 | ||
| 51 | #define FAN53555_CONTROL_SLEW_MASK 0x70 | ||
| 52 | #define FAN53555_CONTROL_RESET BIT(2) | ||
| 53 | |||
| 54 | #define FAN53555_ID1_VENDOR_SHIFT 4 | ||
| 55 | #define FAN53555_ID1_VENDOR_MASK 0xF0 | ||
| 56 | #define FAN53555_ID1_DIE_ID_SHIFT 0 | ||
| 57 | #define FAN53555_ID1_DIE_ID_MASK 0x0F | ||
| 58 | |||
| 59 | #define FAN53555_ID2_REV_SHIFT 0 | ||
| 60 | #define FAN53555_ID2_REV_MASK 0x0F | ||
| 61 | |||
| 62 | #define FAN53555_MONITOR_ILIM BIT(7) | ||
| 63 | #define FAN53555_MONITOR_UVLO BIT(6) | ||
| 64 | #define FAN53555_MONITOR_OVP BIT(5) | ||
| 65 | #define FAN53555_MONITOR_POS BIT(4) | ||
| 66 | #define FAN53555_MONITOR_NEG BIT(3) | ||
| 67 | #define FAN53555_MONITOR_RESET_STAT BIT(2) | ||
| 68 | #define FAN53555_MONITOR_OT BIT(1) | ||
| 69 | #define FAN53555_MONITOR_BUCK_STATUS BIT(0) | ||
| 70 | |||
| 71 | #define FAN53555_VSEL0_ID 0 | ||
| 72 | #define FAN53555_VSEL1_ID 1 | ||
| 73 | |||
| 74 | #define FAN53555UC00X_ID 0x80 | ||
| 75 | #define FAN53555UC01X_ID 0x81 | ||
| 76 | #define FAN53555UC03X_ID 0x83 | ||
| 77 | #define FAN53555UC04X_ID 0x84 | ||
| 78 | #define FAN53555UC05X_ID 0x85 | ||
| 79 | |||
| 80 | #define FAN53555_N_VOLTAGES 64 | ||
| 81 | |||
| 82 | /* FAN53555 chip information */ | ||
| 83 | struct fan53555_chip { | ||
| 84 | const char *name; | ||
| 85 | struct device *dev; | ||
| 86 | struct regulator_desc desc; | ||
| 87 | struct i2c_client *client; | ||
| 88 | struct regulator_dev *rdev; | ||
| 89 | struct mutex io_lock; | ||
| 90 | int chip_id; | ||
| 91 | int vsel_id; | ||
| 92 | u8 shadow[6]; | ||
| 93 | }; | ||
| 94 | |||
| 95 | #define FAN53555_VOLTAGE(chip_id, vsel) \ | ||
| 96 | (((chip_id) == FAN53555UC04X_ID) ? \ | ||
| 97 | ((vsel) * 12826 + 600000) : ((vsel) * 10000 + 600000)) | ||
| 98 | |||
| 99 | static int fan53555_read(struct fan53555_chip *fan, u8 reg) | ||
| 100 | { | ||
| 101 | u8 data; | ||
| 102 | u8 val; | ||
| 103 | int ret; | ||
| 104 | |||
| 105 | data = reg; | ||
| 106 | |||
| 107 | ret = i2c_master_send(fan->client, &data, 1); | ||
| 108 | if (ret < 0) | ||
| 109 | goto out; | ||
| 110 | |||
| 111 | ret = i2c_master_recv(fan->client, &val, 1); | ||
| 112 | if (ret < 0) | ||
| 113 | goto out; | ||
| 114 | |||
| 115 | ret = val; | ||
| 116 | out: | ||
| 117 | return ret; | ||
| 118 | } | ||
| 119 | |||
| 120 | static inline int fan53555_write(struct fan53555_chip *fan, u8 reg, u8 val) | ||
| 121 | { | ||
| 122 | u8 msg[2]; | ||
| 123 | int ret; | ||
| 124 | |||
| 125 | msg[0] = reg; | ||
| 126 | msg[1] = val; | ||
| 127 | |||
| 128 | ret = i2c_master_send(fan->client, msg, 2); | ||
| 129 | if (ret < 0) | ||
| 130 | return ret; | ||
| 131 | if (ret != 2) | ||
| 132 | return -EIO; | ||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | |||
| 136 | static int fan53555_read_reg(struct fan53555_chip *fan, u8 reg) | ||
| 137 | { | ||
| 138 | int data; | ||
| 139 | |||
| 140 | mutex_lock(&fan->io_lock); | ||
| 141 | data = fan53555_read(fan, reg); | ||
| 142 | if (data < 0) | ||
| 143 | dev_err(fan->dev, "Read from reg 0x%x failed\n", reg); | ||
| 144 | mutex_unlock(&fan->io_lock); | ||
| 145 | |||
| 146 | return data; | ||
| 147 | } | ||
| 148 | |||
| 149 | static int fan53555_set_bits(struct fan53555_chip *fan, u8 reg, u8 mask, u8 val) | ||
| 150 | { | ||
| 151 | int err; | ||
| 152 | u8 data; | ||
| 153 | |||
| 154 | mutex_lock(&fan->io_lock); | ||
| 155 | data = fan->shadow[reg]; | ||
| 156 | data &= ~mask; | ||
| 157 | val &= mask; | ||
| 158 | data |= val; | ||
| 159 | err = fan53555_write(fan, reg, data); | ||
| 160 | if (err) | ||
| 161 | dev_err(fan->dev, "write for reg 0x%x failed\n", reg); | ||
| 162 | else | ||
| 163 | fan->shadow[reg] = data; | ||
| 164 | mutex_unlock(&fan->io_lock); | ||
| 165 | |||
| 166 | return err; | ||
| 167 | } | ||
| 168 | |||
| 169 | static int __fan53555_dcdc_set_voltage(struct fan53555_chip *fan, | ||
| 170 | int vsel_id, int min_uV, int max_uV, | ||
| 171 | unsigned *selector) | ||
| 172 | { | ||
| 173 | int nsel; | ||
| 174 | int uV; | ||
| 175 | int chip_id; | ||
| 176 | int n_voltages; | ||
| 177 | |||
| 178 | chip_id = fan->chip_id; | ||
| 179 | n_voltages = fan->desc.n_voltages; | ||
| 180 | |||
| 181 | if (max_uV < min_uV) { | ||
| 182 | dev_err(fan->dev, "max_uV(%d) < min_uV(%d)\n", max_uV, min_uV); | ||
| 183 | return -EINVAL; | ||
| 184 | } | ||
| 185 | if (min_uV > FAN53555_VOLTAGE(chip_id, n_voltages - 1)) { | ||
| 186 | dev_err(fan->dev, "min_uV(%d) > %d[uV]\n", | ||
| 187 | min_uV, FAN53555_VOLTAGE(chip_id, n_voltages - 1)); | ||
| 188 | return -EINVAL; | ||
| 189 | } | ||
| 190 | if (max_uV < FAN53555_VOLTAGE(chip_id, 0)) { | ||
| 191 | dev_err(fan->dev, "max_uV(%d) < %d[uV]\n", | ||
| 192 | max_uV, FAN53555_VOLTAGE(chip_id, 0)); | ||
| 193 | return -EINVAL; | ||
| 194 | } | ||
| 195 | if ((vsel_id != FAN53555_VSEL0_ID) && (vsel_id != FAN53555_VSEL1_ID)) { | ||
| 196 | dev_err(fan->dev, | ||
| 197 | "%d is not valid VSEL register ID\n", vsel_id); | ||
| 198 | return -EINVAL; | ||
| 199 | } | ||
| 200 | for (nsel = 0; nsel < n_voltages; nsel++) { | ||
| 201 | uV = FAN53555_VOLTAGE(chip_id, nsel); | ||
| 202 | if (min_uV <= uV && uV <= max_uV) { | ||
| 203 | if (selector) | ||
| 204 | *selector = nsel; | ||
| 205 | return fan53555_set_bits(fan, | ||
| 206 | FAN53555_REG_VSEL0 + vsel_id, | ||
| 207 | FAN53555_VSEL_NSEL_MASK, | ||
| 208 | nsel << | ||
| 209 | FAN53555_VSEL_NSEL_SHIFT); | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 213 | return -EINVAL; | ||
| 214 | } | ||
| 215 | |||
| 216 | #ifdef CONFIG_DEBUG_FS | ||
| 217 | |||
| 218 | #include <linux/debugfs.h> | ||
| 219 | #include <linux/seq_file.h> | ||
| 220 | |||
| 221 | static int dbg_fan_show(struct seq_file *s, void *unused) | ||
| 222 | { | ||
| 223 | struct fan53555_chip *fan = s->private; | ||
| 224 | int val; | ||
| 225 | |||
| 226 | seq_printf(s, "FAN53555 Registers\n"); | ||
| 227 | seq_printf(s, "------------------\n"); | ||
| 228 | |||
| 229 | val = fan53555_read_reg(fan, FAN53555_REG_VSEL0); | ||
| 230 | if (val >= 0) | ||
| 231 | seq_printf(s, "Reg VSEL0 Value 0x%02x\n", val); | ||
| 232 | |||
| 233 | val = fan53555_read_reg(fan, FAN53555_REG_VSEL1); | ||
| 234 | if (val >= 0) | ||
| 235 | seq_printf(s, "Reg VSEL1 Value 0x%02x\n", val); | ||
| 236 | |||
| 237 | val = fan53555_read_reg(fan, FAN53555_REG_CONTROL); | ||
| 238 | if (val >= 0) | ||
| 239 | seq_printf(s, "Reg CONTROL Value 0x%02x\n", val); | ||
| 240 | |||
| 241 | val = fan53555_read_reg(fan, FAN53555_REG_ID1); | ||
| 242 | if (val >= 0) | ||
| 243 | seq_printf(s, "Reg ID1 Value 0x%02x\n", val); | ||
| 244 | |||
| 245 | val = fan53555_read_reg(fan, FAN53555_REG_ID2); | ||
| 246 | if (val >= 0) | ||
| 247 | seq_printf(s, "Reg ID2 Value 0x%02x\n", val); | ||
| 248 | |||
| 249 | val = fan53555_read_reg(fan, FAN53555_REG_MONITOR); | ||
| 250 | if (val >= 0) | ||
| 251 | seq_printf(s, "Reg MONITOR Value 0x%02x\n", val); | ||
| 252 | |||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | static int dbg_fan_open(struct inode *inode, struct file *file) | ||
| 257 | { | ||
| 258 | return single_open(file, dbg_fan_show, inode->i_private); | ||
| 259 | } | ||
| 260 | |||
| 261 | static const struct file_operations debug_fops = { | ||
| 262 | .open = dbg_fan_open, | ||
| 263 | .read = seq_read, | ||
| 264 | .llseek = seq_lseek, | ||
| 265 | .release = single_release, | ||
| 266 | }; | ||
| 267 | |||
| 268 | static void __init fan53555_debuginit(struct fan53555_chip *fan) | ||
| 269 | { | ||
| 270 | (void)debugfs_create_file("fan53555", S_IRUGO, NULL, fan, &debug_fops); | ||
| 271 | } | ||
| 272 | #else | ||
| 273 | static void __init fan53555_debuginit(struct fan53555_chip *fan) | ||
| 274 | { | ||
| 275 | } | ||
| 276 | #endif | ||
| 277 | |||
| 278 | static int fan53555_dcdc_init(struct fan53555_chip *fan, | ||
| 279 | struct i2c_client *client, | ||
| 280 | struct fan53555_regulator_platform_data *pdata) | ||
| 281 | { | ||
| 282 | int err; | ||
| 283 | int val; | ||
| 284 | |||
| 285 | err = fan53555_read_reg(fan, FAN53555_REG_VSEL0); | ||
| 286 | if (err < 0) | ||
| 287 | return err; | ||
| 288 | fan->shadow[FAN53555_REG_VSEL0] = (u8)err; | ||
| 289 | |||
| 290 | err = fan53555_read_reg(fan, FAN53555_REG_VSEL1); | ||
| 291 | if (err < 0) | ||
| 292 | return err; | ||
| 293 | fan->shadow[FAN53555_REG_VSEL1] = (u8)err; | ||
| 294 | |||
| 295 | err = fan53555_read_reg(fan, FAN53555_REG_CONTROL); | ||
| 296 | if (err < 0) | ||
| 297 | return err; | ||
| 298 | fan->shadow[FAN53555_REG_CONTROL] = (u8)err; | ||
| 299 | |||
| 300 | err = __fan53555_dcdc_set_voltage(fan, | ||
| 301 | FAN53555_VSEL0_ID, | ||
| 302 | pdata->init_vsel0_min_uV, | ||
| 303 | pdata->init_vsel0_max_uV, | ||
| 304 | NULL); | ||
| 305 | if (err < 0) | ||
| 306 | return err; | ||
| 307 | |||
| 308 | val = pdata->vsel0_buck_en ? FAN53555_VSEL_BUCK_EN : 0; | ||
| 309 | val |= pdata->vsel0_mode ? FAN53555_VSEL_MODE : 0; | ||
| 310 | err = fan53555_set_bits(fan, | ||
| 311 | FAN53555_REG_VSEL0, | ||
| 312 | FAN53555_VSEL_BUCK_EN | FAN53555_VSEL_MODE, | ||
| 313 | val); | ||
| 314 | if (err < 0) | ||
| 315 | return err; | ||
| 316 | |||
| 317 | err = __fan53555_dcdc_set_voltage(fan, | ||
| 318 | FAN53555_VSEL1_ID, | ||
| 319 | pdata->init_vsel1_min_uV, | ||
| 320 | pdata->init_vsel1_max_uV, | ||
| 321 | NULL); | ||
| 322 | if (err < 0) | ||
| 323 | return err; | ||
| 324 | |||
| 325 | val = pdata->vsel1_buck_en ? FAN53555_VSEL_BUCK_EN : 0; | ||
| 326 | val |= pdata->vsel1_mode ? FAN53555_VSEL_MODE : 0; | ||
| 327 | err = fan53555_set_bits(fan, | ||
| 328 | FAN53555_REG_VSEL1, | ||
| 329 | FAN53555_VSEL_BUCK_EN | FAN53555_VSEL_MODE, | ||
| 330 | val); | ||
| 331 | if (err < 0) | ||
| 332 | return err; | ||
| 333 | |||
| 334 | val = pdata->slew_rate; | ||
| 335 | val <<= FAN53555_CONTROL_SLEW_SHIFT; | ||
| 336 | val |= pdata->output_discharge ? FAN53555_CONTROL_DISCHARGE : 0; | ||
| 337 | err = fan53555_set_bits(fan, | ||
| 338 | FAN53555_REG_CONTROL, | ||
| 339 | FAN53555_CONTROL_DISCHARGE | | ||
| 340 | FAN53555_CONTROL_SLEW_MASK, val); | ||
| 341 | return err; | ||
| 342 | } | ||
| 343 | |||
| 344 | static int fan53555_dcdc_list_voltage(struct regulator_dev *dev, | ||
| 345 | unsigned selector) | ||
| 346 | { | ||
| 347 | struct fan53555_chip *fan = rdev_get_drvdata(dev); | ||
| 348 | |||
| 349 | if ((selector < 0) || (selector >= fan->desc.n_voltages)) | ||
| 350 | return -EINVAL; | ||
| 351 | |||
| 352 | return FAN53555_VOLTAGE(fan->chip_id, selector); | ||
| 353 | } | ||
| 354 | |||
| 355 | static int fan53555_dcdc_set_voltage(struct regulator_dev *dev, | ||
| 356 | int min_uV, int max_uV, | ||
| 357 | unsigned *selector) | ||
| 358 | { | ||
| 359 | struct fan53555_chip *fan = rdev_get_drvdata(dev); | ||
| 360 | |||
| 361 | return __fan53555_dcdc_set_voltage(fan, fan->vsel_id, min_uV, max_uV, | ||
| 362 | selector); | ||
| 363 | } | ||
| 364 | |||
| 365 | static int fan53555_dcdc_get_voltage(struct regulator_dev *dev) | ||
| 366 | { | ||
| 367 | struct fan53555_chip *fan = rdev_get_drvdata(dev); | ||
| 368 | u8 data; | ||
| 369 | |||
| 370 | if ((fan->vsel_id != FAN53555_VSEL0_ID) && | ||
| 371 | (fan->vsel_id != FAN53555_VSEL1_ID)) { | ||
| 372 | dev_err(fan->dev, | ||
| 373 | "%d is not valid VSEL register ID\n", fan->vsel_id); | ||
| 374 | return -EINVAL; | ||
| 375 | } | ||
| 376 | data = fan->shadow[FAN53555_REG_VSEL0 + fan->vsel_id]; | ||
| 377 | data &= FAN53555_VSEL_NSEL_MASK; | ||
| 378 | data >>= FAN53555_VSEL_NSEL_SHIFT; | ||
| 379 | |||
| 380 | return FAN53555_VOLTAGE(fan->chip_id, data); | ||
| 381 | } | ||
| 382 | |||
| 383 | static int fan53555_dcdc_enable(struct regulator_dev *dev) | ||
| 384 | { | ||
| 385 | struct fan53555_chip *fan = rdev_get_drvdata(dev); | ||
| 386 | |||
| 387 | if ((fan->vsel_id != FAN53555_VSEL0_ID) && | ||
| 388 | (fan->vsel_id != FAN53555_VSEL1_ID)) { | ||
| 389 | dev_err(fan->dev, | ||
| 390 | "%d is not valid VSEL register ID\n", fan->vsel_id); | ||
| 391 | return -EINVAL; | ||
| 392 | } | ||
| 393 | |||
| 394 | return fan53555_set_bits(fan, | ||
| 395 | FAN53555_REG_VSEL0 + fan->vsel_id, | ||
| 396 | FAN53555_VSEL_BUCK_EN, FAN53555_VSEL_BUCK_EN); | ||
| 397 | } | ||
| 398 | |||
| 399 | static int fan53555_dcdc_disable(struct regulator_dev *dev) | ||
| 400 | { | ||
| 401 | struct fan53555_chip *fan = rdev_get_drvdata(dev); | ||
| 402 | |||
| 403 | if ((fan->vsel_id != FAN53555_VSEL0_ID) && | ||
| 404 | (fan->vsel_id != FAN53555_VSEL1_ID)) { | ||
| 405 | dev_err(fan->dev, | ||
| 406 | "%d is not valid VSEL register ID\n", fan->vsel_id); | ||
| 407 | return -EINVAL; | ||
| 408 | } | ||
| 409 | |||
| 410 | return fan53555_set_bits(fan, | ||
| 411 | FAN53555_REG_VSEL0 + fan->vsel_id, | ||
| 412 | FAN53555_VSEL_BUCK_EN, 0); | ||
| 413 | } | ||
| 414 | |||
| 415 | static int fan53555_dcdc_is_enabled(struct regulator_dev *dev) | ||
| 416 | { | ||
| 417 | struct fan53555_chip *fan = rdev_get_drvdata(dev); | ||
| 418 | u8 data; | ||
| 419 | |||
| 420 | if ((fan->vsel_id != FAN53555_VSEL0_ID) && | ||
| 421 | (fan->vsel_id != FAN53555_VSEL1_ID)) { | ||
| 422 | dev_err(fan->dev, | ||
| 423 | "%d is not valid VSEL register ID\n", fan->vsel_id); | ||
| 424 | return -EINVAL; | ||
| 425 | } | ||
| 426 | data = fan->shadow[FAN53555_REG_VSEL0 + fan->vsel_id]; | ||
| 427 | |||
| 428 | return (data & FAN53555_VSEL_BUCK_EN) ? 1 : 0; | ||
| 429 | } | ||
| 430 | |||
| 431 | static struct regulator_ops fan53555_dcdc_ops = { | ||
| 432 | .list_voltage = fan53555_dcdc_list_voltage, | ||
| 433 | .set_voltage = fan53555_dcdc_set_voltage, | ||
| 434 | .get_voltage = fan53555_dcdc_get_voltage, | ||
| 435 | .enable = fan53555_dcdc_enable, | ||
| 436 | .disable = fan53555_dcdc_disable, | ||
| 437 | .is_enabled = fan53555_dcdc_is_enabled, | ||
| 438 | }; | ||
| 439 | |||
| 440 | static int __devinit fan53555_probe(struct i2c_client *client, | ||
| 441 | const struct i2c_device_id *id) | ||
| 442 | { | ||
| 443 | struct fan53555_regulator_platform_data *pdata; | ||
| 444 | struct regulator_init_data *init_data; | ||
| 445 | struct regulator_dev *rdev; | ||
| 446 | struct fan53555_chip *fan; | ||
| 447 | int chip_id; | ||
| 448 | int err; | ||
| 449 | |||
| 450 | pdata = client->dev.platform_data; | ||
| 451 | if (!pdata) { | ||
| 452 | dev_err(&client->dev, "Err: Platform data not found\n"); | ||
| 453 | return -EIO; | ||
| 454 | } | ||
| 455 | init_data = &pdata->reg_init_data; | ||
| 456 | fan = kzalloc(sizeof(*fan), GFP_KERNEL); | ||
| 457 | if (!fan) { | ||
| 458 | dev_err(&client->dev, "Err: Memory allocation fails\n"); | ||
| 459 | return -ENOMEM; | ||
| 460 | } | ||
| 461 | mutex_init(&fan->io_lock); | ||
| 462 | fan->client = client; | ||
| 463 | fan->dev = &client->dev; | ||
| 464 | fan->vsel_id = pdata->vsel_id; | ||
| 465 | fan->name = id->name; | ||
| 466 | fan->desc.name = id->name; | ||
| 467 | fan->desc.id = 0; | ||
| 468 | fan->desc.irq = 0; | ||
| 469 | fan->desc.ops = &fan53555_dcdc_ops; | ||
| 470 | fan->desc.type = REGULATOR_VOLTAGE; | ||
| 471 | fan->desc.owner = THIS_MODULE; | ||
| 472 | fan->desc.n_voltages = FAN53555_N_VOLTAGES; | ||
| 473 | i2c_set_clientdata(client, fan); | ||
| 474 | |||
| 475 | chip_id = fan53555_read_reg(fan, FAN53555_REG_ID1); | ||
| 476 | if (chip_id < 0) { | ||
| 477 | err = chip_id; | ||
| 478 | dev_err(fan->dev, "Error in reading device %d\n", err); | ||
| 479 | goto fail; | ||
| 480 | } | ||
| 481 | |||
| 482 | switch (chip_id) { | ||
| 483 | case FAN53555UC00X_ID: | ||
| 484 | case FAN53555UC01X_ID: | ||
| 485 | case FAN53555UC03X_ID: | ||
| 486 | case FAN53555UC04X_ID: | ||
| 487 | case FAN53555UC05X_ID: | ||
| 488 | fan->chip_id = chip_id; | ||
| 489 | break; | ||
| 490 | default: | ||
| 491 | dev_err(fan->dev, "Err: not supported device chip id 0x%x", | ||
| 492 | chip_id); | ||
| 493 | err = -ENODEV; | ||
| 494 | goto fail; | ||
| 495 | } | ||
| 496 | |||
| 497 | err = fan53555_dcdc_init(fan, client, pdata); | ||
| 498 | if (err < 0) { | ||
| 499 | dev_err(fan->dev, "FAN53555 init fails with %d\n", err); | ||
| 500 | goto fail; | ||
| 501 | } | ||
| 502 | |||
| 503 | rdev = regulator_register(&fan->desc, &client->dev, init_data, fan); | ||
| 504 | if (IS_ERR(rdev)) { | ||
| 505 | dev_err(fan->dev, "Failed to register %s\n", id->name); | ||
| 506 | err = PTR_ERR(rdev); | ||
| 507 | goto fail; | ||
| 508 | } | ||
| 509 | fan->rdev = rdev; | ||
| 510 | |||
| 511 | fan53555_debuginit(fan); | ||
| 512 | return 0; | ||
| 513 | |||
| 514 | fail: | ||
| 515 | kfree(fan); | ||
| 516 | return err; | ||
| 517 | } | ||
| 518 | |||
| 519 | /** | ||
| 520 | * fan53555_remove - fan53555 driver i2c remove handler | ||
| 521 | * @client: i2c driver client device structure | ||
| 522 | * | ||
| 523 | * Unregister fan53555 driver as an i2c client device driver | ||
| 524 | */ | ||
| 525 | static int __devexit fan53555_remove(struct i2c_client *client) | ||
| 526 | { | ||
| 527 | struct fan53555_chip *chip = i2c_get_clientdata(client); | ||
| 528 | |||
| 529 | regulator_unregister(chip->rdev); | ||
| 530 | kfree(chip); | ||
| 531 | return 0; | ||
| 532 | } | ||
| 533 | |||
| 534 | static const struct i2c_device_id fan53555_id[] = { | ||
| 535 | {.name = "fan53555", .driver_data = 0 }, | ||
| 536 | {}, | ||
| 537 | }; | ||
| 538 | MODULE_DEVICE_TABLE(i2c, fan53555_id); | ||
| 539 | |||
| 540 | static struct i2c_driver fan53555_i2c_driver = { | ||
| 541 | .driver = { | ||
| 542 | .name = "fan53555", | ||
| 543 | .owner = THIS_MODULE, | ||
| 544 | }, | ||
| 545 | .probe = fan53555_probe, | ||
| 546 | .remove = __devexit_p(fan53555_remove), | ||
| 547 | .id_table = fan53555_id, | ||
| 548 | }; | ||
| 549 | |||
| 550 | /* Module init function */ | ||
| 551 | static int __init fan53555_init(void) | ||
| 552 | { | ||
| 553 | return i2c_add_driver(&fan53555_i2c_driver); | ||
| 554 | } | ||
| 555 | subsys_initcall_sync(fan53555_init); | ||
| 556 | |||
| 557 | /* Module exit function */ | ||
| 558 | static void __exit fan53555_cleanup(void) | ||
| 559 | { | ||
| 560 | i2c_del_driver(&fan53555_i2c_driver); | ||
| 561 | } | ||
| 562 | module_exit(fan53555_cleanup); | ||
| 563 | |||
| 564 | MODULE_LICENSE("GPL"); | ||
| 565 | MODULE_AUTHOR("Jake Park<jakep@nvidia.com>"); | ||
| 566 | MODULE_DESCRIPTION("Regulator Driver for Fairchild FAN53555 Regulator"); | ||
| 567 | MODULE_ALIAS("platform:fan53555-regulator"); | ||
diff --git a/drivers/regulator/gpio-switch-regulator.c b/drivers/regulator/gpio-switch-regulator.c new file mode 100644 index 00000000000..55dd63675a0 --- /dev/null +++ b/drivers/regulator/gpio-switch-regulator.c | |||
| @@ -0,0 +1,412 @@ | |||
| 1 | /* | ||
| 2 | * driver/regulator/gpio-switch-regulator.c | ||
| 3 | * GPIO based switch regulator to enable/disable power rails. | ||
| 4 | * | ||
| 5 | * Copyright (c) 2011, NVIDIA Corporation. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 15 | * more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License along | ||
| 18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 20 | */ | ||
| 21 | |||
| 22 | /*#define DEBUG 1*/ | ||
| 23 | /*#define VERBOSE_DEBUG 1*/ | ||
| 24 | |||
| 25 | #include <linux/kernel.h> | ||
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/err.h> | ||
| 28 | #include <linux/slab.h> | ||
| 29 | #include <linux/platform_device.h> | ||
| 30 | #include <linux/regulator/driver.h> | ||
| 31 | #include <linux/regulator/machine.h> | ||
| 32 | #include <linux/gpio.h> | ||
| 33 | #include <linux/regulator/gpio-switch-regulator.h> | ||
| 34 | |||
| 35 | struct gpio_switch_regulator { | ||
| 36 | struct regulator_desc reg_desc; | ||
| 37 | struct regulator_init_data reg_init_data; | ||
| 38 | struct regulator *input_regulator; | ||
| 39 | struct regulator_dev *rdev; | ||
| 40 | struct device *dev; | ||
| 41 | int gpio_nr; | ||
| 42 | int pin_group; | ||
| 43 | bool is_gpio_init; | ||
| 44 | bool is_enable; | ||
| 45 | bool active_low; | ||
| 46 | bool is_init_success; | ||
| 47 | int *voltages; | ||
| 48 | unsigned curr_vol_sel; | ||
| 49 | struct gpio_switch_regulator_subdev_data *psubdev_data; | ||
| 50 | int (*enable_rail)(struct gpio_switch_regulator_subdev_data *sdata); | ||
| 51 | int (*disable_rail)(struct gpio_switch_regulator_subdev_data *sdata); | ||
| 52 | }; | ||
| 53 | |||
| 54 | static int _gpio_regulator_enable(struct device *dev, | ||
| 55 | struct gpio_switch_regulator *ri) | ||
| 56 | { | ||
| 57 | int init_val; | ||
| 58 | int ret; | ||
| 59 | |||
| 60 | if (ri->enable_rail) { | ||
| 61 | ret = ri->enable_rail(ri->psubdev_data); | ||
| 62 | if (ret < 0) | ||
| 63 | dev_err(dev, "Unable to enable rail through board api" | ||
| 64 | " error %d\n", ret); | ||
| 65 | } else { | ||
| 66 | init_val = (ri->active_low) ? 0 : 1; | ||
| 67 | ret = gpio_direction_output(ri->gpio_nr, init_val); | ||
| 68 | if (ret < 0) | ||
| 69 | dev_err(dev, "Unable to set direction %d\n", | ||
| 70 | ri->gpio_nr); | ||
| 71 | } | ||
| 72 | return ret; | ||
| 73 | } | ||
| 74 | |||
| 75 | static int _gpio_regulator_disable(struct device *dev, | ||
| 76 | struct gpio_switch_regulator *ri) | ||
| 77 | { | ||
| 78 | int init_val; | ||
| 79 | int ret; | ||
| 80 | |||
| 81 | if (ri->disable_rail) { | ||
| 82 | ret = ri->disable_rail(ri->psubdev_data); | ||
| 83 | if (ret < 0) | ||
| 84 | dev_err(dev, "Unable to disable rail through " | ||
| 85 | "board api %d\n", ret); | ||
| 86 | } else { | ||
| 87 | init_val = (ri->active_low) ? 1 : 0; | ||
| 88 | ret = gpio_direction_output(ri->gpio_nr, init_val); | ||
| 89 | if (ret < 0) | ||
| 90 | dev_err(dev, "Unable to set direction %d\n", | ||
| 91 | ri->gpio_nr); | ||
| 92 | } | ||
| 93 | return ret; | ||
| 94 | } | ||
| 95 | |||
| 96 | static int gpio_switch_list_voltage(struct regulator_dev *rdev, | ||
| 97 | unsigned selector) | ||
| 98 | { | ||
| 99 | struct gpio_switch_regulator *ri = rdev_get_drvdata(rdev); | ||
| 100 | |||
| 101 | if (selector < ri->reg_desc.n_voltages) | ||
| 102 | return ri->voltages[selector] * 1000; | ||
| 103 | else | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | |||
| 107 | static int gpio_switch_set_voltage(struct regulator_dev *rdev, | ||
| 108 | int min_uV, int max_uV, unsigned *selector) | ||
| 109 | { | ||
| 110 | struct gpio_switch_regulator *ri = rdev_get_drvdata(rdev); | ||
| 111 | int uV; | ||
| 112 | bool found = false; | ||
| 113 | unsigned val; | ||
| 114 | |||
| 115 | for (val = 0; val < ri->reg_desc.n_voltages; val++) { | ||
| 116 | uV = ri->voltages[val] * 1000; | ||
| 117 | if (min_uV <= uV && uV <= max_uV) { | ||
| 118 | found = true; | ||
| 119 | *selector = ri->curr_vol_sel = val; | ||
| 120 | break; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | if (found && ri->input_regulator) | ||
| 124 | return regulator_set_voltage(ri->input_regulator, min_uV, | ||
| 125 | max_uV); | ||
| 126 | ri->curr_vol_sel = 0; | ||
| 127 | return -EINVAL; | ||
| 128 | } | ||
| 129 | |||
| 130 | static int gpio_switch_get_voltage(struct regulator_dev *rdev) | ||
| 131 | { | ||
| 132 | struct gpio_switch_regulator *ri = rdev_get_drvdata(rdev); | ||
| 133 | if (ri->input_regulator) | ||
| 134 | return regulator_get_voltage(ri->input_regulator); | ||
| 135 | |||
| 136 | if (ri->curr_vol_sel < ri->reg_desc.n_voltages) | ||
| 137 | return ri->voltages[ri->curr_vol_sel] * 1000; | ||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | static int gpio_switch_regulator_enable(struct regulator_dev *rdev) | ||
| 142 | { | ||
| 143 | struct gpio_switch_regulator *ri = rdev_get_drvdata(rdev); | ||
| 144 | int ret = 0; | ||
| 145 | if (ri->is_enable) | ||
| 146 | return 0; | ||
| 147 | |||
| 148 | if (ri->input_regulator) { | ||
| 149 | ret = regulator_enable(ri->input_regulator); | ||
| 150 | if (ret < 0) { | ||
| 151 | dev_err(&rdev->dev, "%s:Failed to enable regulator" | ||
| 152 | " Error %d\n", __func__, ret); | ||
| 153 | return ret; | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | ret = _gpio_regulator_enable(&rdev->dev, ri); | ||
| 158 | if (ret < 0) | ||
| 159 | return ret; | ||
| 160 | ri->is_enable = true; | ||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | static int gpio_switch_regulator_disable(struct regulator_dev *rdev) | ||
| 165 | { | ||
| 166 | struct gpio_switch_regulator *ri = rdev_get_drvdata(rdev); | ||
| 167 | int ret = 0; | ||
| 168 | |||
| 169 | if (!ri->is_enable) | ||
| 170 | return 0; | ||
| 171 | |||
| 172 | ret = _gpio_regulator_disable(&rdev->dev, ri); | ||
| 173 | if (ret < 0) | ||
| 174 | return ret; | ||
| 175 | |||
| 176 | if (ri->input_regulator) { | ||
| 177 | ret = regulator_disable(ri->input_regulator); | ||
| 178 | if (ret < 0) { | ||
| 179 | dev_err(&rdev->dev, "%s:Failed to disable regulator" | ||
| 180 | " Error %d\n", __func__, ret); | ||
| 181 | return ret; | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | ri->is_enable = false; | ||
| 186 | return 0; | ||
| 187 | } | ||
| 188 | |||
| 189 | static int gpio_switch_regulator_is_enabled(struct regulator_dev *rdev) | ||
| 190 | { | ||
| 191 | struct gpio_switch_regulator *ri = rdev_get_drvdata(rdev); | ||
| 192 | int ret = 0; | ||
| 193 | if (ri->input_regulator) { | ||
| 194 | ret = regulator_is_enabled(ri->input_regulator); | ||
| 195 | if (!ret) | ||
| 196 | return ret; | ||
| 197 | } | ||
| 198 | return (ri->is_enable) ? 1 : 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | static struct regulator_ops gpio_switch_regulator_ops = { | ||
| 202 | .list_voltage = gpio_switch_list_voltage, | ||
| 203 | .get_voltage = gpio_switch_get_voltage, | ||
| 204 | .set_voltage = gpio_switch_set_voltage, | ||
| 205 | .is_enabled = gpio_switch_regulator_is_enabled, | ||
| 206 | .enable = gpio_switch_regulator_enable, | ||
| 207 | .disable = gpio_switch_regulator_disable, | ||
| 208 | }; | ||
| 209 | |||
| 210 | static int __devinit gpio_switch_regulator_probe(struct platform_device *pdev) | ||
| 211 | { | ||
| 212 | struct gpio_switch_regulator *ri = NULL; | ||
| 213 | struct gpio_switch_regulator *gswitch_reg = NULL; | ||
| 214 | struct gpio_switch_regulator_platform_data *pdata; | ||
| 215 | struct gpio_switch_regulator_subdev_data *sdata = NULL; | ||
| 216 | int id = pdev->id; | ||
| 217 | int ret = 0; | ||
| 218 | int rcount; | ||
| 219 | |||
| 220 | dev_dbg(&pdev->dev, "Probing regulator %d\n", id); | ||
| 221 | |||
| 222 | pdata = pdev->dev.platform_data; | ||
| 223 | if (!pdata) { | ||
| 224 | dev_err(&pdev->dev, "%s:No platform data Exiting\n", __func__); | ||
| 225 | return -ENODEV; | ||
| 226 | } | ||
| 227 | |||
| 228 | BUG_ON(!pdata->num_subdevs); | ||
| 229 | |||
| 230 | gswitch_reg = kzalloc(sizeof(struct gpio_switch_regulator) * | ||
| 231 | pdata->num_subdevs, GFP_KERNEL); | ||
| 232 | if (!gswitch_reg) { | ||
| 233 | dev_err(&pdev->dev, "%s:Failed to allocate memory\n", __func__); | ||
| 234 | return -ENOMEM; | ||
| 235 | } | ||
| 236 | |||
| 237 | for (rcount = 0; rcount < pdata->num_subdevs; ++rcount) { | ||
| 238 | ri = &gswitch_reg[rcount]; | ||
| 239 | sdata = pdata->subdevs[rcount]; | ||
| 240 | |||
| 241 | /* Initialize the regulator parameter */ | ||
| 242 | ri->reg_desc.name = sdata->regulator_name; | ||
| 243 | ri->reg_desc.ops = &gpio_switch_regulator_ops; | ||
| 244 | ri->reg_desc.type = REGULATOR_VOLTAGE; | ||
| 245 | ri->reg_desc.id = sdata->id; | ||
| 246 | ri->reg_desc.n_voltages = sdata->n_voltages; | ||
| 247 | ri->reg_desc.owner = THIS_MODULE; | ||
| 248 | ri->is_init_success = false; | ||
| 249 | |||
| 250 | memcpy(&ri->reg_init_data.constraints, &sdata->constraints, | ||
| 251 | sizeof(struct regulation_constraints)); | ||
| 252 | |||
| 253 | /* Initialize min and maximum contraint voltage if it is not | ||
| 254 | * define in platform device */ | ||
| 255 | if (!sdata->constraints.min_uV) | ||
| 256 | ri->reg_init_data.constraints.min_uV = 1000 * | ||
| 257 | sdata->voltages[0]; | ||
| 258 | |||
| 259 | if (!sdata->constraints.max_uV) | ||
| 260 | ri->reg_init_data.constraints.max_uV = 1000 * | ||
| 261 | sdata->voltages[sdata->n_voltages - 1]; | ||
| 262 | |||
| 263 | ri->reg_init_data.num_consumer_supplies = | ||
| 264 | sdata->num_consumer_supplies; | ||
| 265 | ri->reg_init_data.consumer_supplies = sdata->consumer_supplies; | ||
| 266 | |||
| 267 | ri->input_regulator = NULL; | ||
| 268 | ri->is_gpio_init = false; | ||
| 269 | ri->is_enable = (sdata->init_state) ? true : false; | ||
| 270 | ri->voltages = sdata->voltages; | ||
| 271 | ri->psubdev_data = sdata; | ||
| 272 | ri->gpio_nr = sdata->gpio_nr; | ||
| 273 | ri->active_low = sdata->active_low; | ||
| 274 | ri->dev = &pdev->dev; | ||
| 275 | ri->enable_rail = sdata->enable_rail; | ||
| 276 | ri->disable_rail = sdata->disable_rail; | ||
| 277 | ri->pin_group = sdata->pin_group; | ||
| 278 | |||
| 279 | /* Checking for board APIs enable/disable rail */ | ||
| 280 | if (ri->enable_rail || ri->disable_rail) | ||
| 281 | BUG_ON(!(ri->enable_rail && ri->disable_rail)); | ||
| 282 | |||
| 283 | /* Get the regulator structure if input supply is available */ | ||
| 284 | if (sdata->input_supply) { | ||
| 285 | ri->input_regulator = regulator_get(NULL, | ||
| 286 | sdata->input_supply); | ||
| 287 | if (IS_ERR_OR_NULL(ri->input_regulator)) { | ||
| 288 | dev_err(&pdev->dev, "Unable to get regu" | ||
| 289 | "lator %s\n", sdata->input_supply); | ||
| 290 | ret = -ENODEV; | ||
| 291 | goto reg_get_fail; | ||
| 292 | } | ||
| 293 | if (ri->is_enable) { | ||
| 294 | ret = regulator_enable(ri->input_regulator); | ||
| 295 | if (ret < 0) { | ||
| 296 | dev_err(&pdev->dev, "Unable to enable " | ||
| 297 | "regulator %s\n", | ||
| 298 | sdata->input_supply); | ||
| 299 | goto reg_en_fail; | ||
| 300 | } | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 304 | /* Initialize gpios */ | ||
| 305 | ret = gpio_request(ri->gpio_nr, sdata->regulator_name); | ||
| 306 | if (ret < 0) { | ||
| 307 | dev_err(&pdev->dev, "Unable to request gpio %d\n", | ||
| 308 | ri->gpio_nr); | ||
| 309 | goto gpio_req_fail; | ||
| 310 | } | ||
| 311 | |||
| 312 | if (ri->is_enable) | ||
| 313 | ret = _gpio_regulator_enable(&pdev->dev, ri); | ||
| 314 | else | ||
| 315 | ret = _gpio_regulator_disable(&pdev->dev, ri); | ||
| 316 | if (ret < 0) | ||
| 317 | goto reg_cont_fail; | ||
| 318 | |||
| 319 | ri->is_gpio_init = true; | ||
| 320 | |||
| 321 | ri->rdev = regulator_register(&ri->reg_desc, &pdev->dev, | ||
| 322 | &ri->reg_init_data, ri); | ||
| 323 | if (IS_ERR_OR_NULL(ri->rdev)) { | ||
| 324 | dev_err(&pdev->dev, "Failed to register regulator %s\n", | ||
| 325 | ri->reg_desc.name); | ||
| 326 | ret = PTR_ERR(ri->rdev); | ||
| 327 | goto reg_reg_fail; | ||
| 328 | } | ||
| 329 | |||
| 330 | /* If everything success then continue for next registration */ | ||
| 331 | ri->is_init_success = true; | ||
| 332 | continue; | ||
| 333 | |||
| 334 | /* Cleanup the current registration and continue for next | ||
| 335 | * registration*/ | ||
| 336 | reg_reg_fail: | ||
| 337 | if (ri->is_enable) | ||
| 338 | _gpio_regulator_disable(&pdev->dev, ri); | ||
| 339 | reg_cont_fail: | ||
| 340 | gpio_free(ri->gpio_nr); | ||
| 341 | gpio_req_fail: | ||
| 342 | if (ri->is_enable && ri->input_regulator) | ||
| 343 | regulator_disable(ri->input_regulator); | ||
| 344 | reg_en_fail: | ||
| 345 | if (ri->input_regulator) { | ||
| 346 | regulator_put(ri->input_regulator); | ||
| 347 | ri->input_regulator = NULL; | ||
| 348 | } | ||
| 349 | reg_get_fail: | ||
| 350 | dev_err(&pdev->dev, "Unable to register regulator %s\n", | ||
| 351 | sdata->regulator_name); | ||
| 352 | } | ||
| 353 | |||
| 354 | platform_set_drvdata(pdev, gswitch_reg); | ||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | static int __devexit gpio_switch_regulator_remove(struct platform_device *pdev) | ||
| 359 | { | ||
| 360 | struct gpio_switch_regulator *ri = NULL; | ||
| 361 | struct gpio_switch_regulator *gswitch_reg = platform_get_drvdata(pdev); | ||
| 362 | int i; | ||
| 363 | struct gpio_switch_regulator_platform_data *pdata; | ||
| 364 | |||
| 365 | pdata = pdev->dev.platform_data; | ||
| 366 | |||
| 367 | /* Unregister devices in reverse order */ | ||
| 368 | for (i = pdata->num_subdevs; i; --i) { | ||
| 369 | ri = &gswitch_reg[i - 1]; | ||
| 370 | /* If registration was not success, then do not release */ | ||
| 371 | if (!ri->is_init_success) | ||
| 372 | continue; | ||
| 373 | |||
| 374 | if (ri->is_enable) | ||
| 375 | _gpio_regulator_disable(&pdev->dev, ri); | ||
| 376 | |||
| 377 | if (ri->input_regulator) { | ||
| 378 | if (ri->is_enable) | ||
| 379 | regulator_disable(ri->input_regulator); | ||
| 380 | regulator_put(ri->input_regulator); | ||
| 381 | } | ||
| 382 | |||
| 383 | regulator_unregister(ri->rdev); | ||
| 384 | gpio_free(ri->gpio_nr); | ||
| 385 | } | ||
| 386 | |||
| 387 | kfree(gswitch_reg); | ||
| 388 | platform_set_drvdata(pdev, NULL); | ||
| 389 | return 0; | ||
| 390 | } | ||
| 391 | |||
| 392 | static struct platform_driver gpio_switch_regulator_driver = { | ||
| 393 | .driver = { | ||
| 394 | .name = "gpio-switch-regulator", | ||
| 395 | .owner = THIS_MODULE, | ||
| 396 | }, | ||
| 397 | .probe = gpio_switch_regulator_probe, | ||
| 398 | .remove = __devexit_p(gpio_switch_regulator_remove), | ||
| 399 | }; | ||
| 400 | |||
| 401 | static int __init gpio_switch_regulator_init(void) | ||
| 402 | { | ||
| 403 | return platform_driver_register(&gpio_switch_regulator_driver); | ||
| 404 | } | ||
| 405 | |||
| 406 | static void __exit gpio_switch_regulator_exit(void) | ||
| 407 | { | ||
| 408 | platform_driver_unregister(&gpio_switch_regulator_driver); | ||
| 409 | } | ||
| 410 | |||
| 411 | subsys_initcall_sync(gpio_switch_regulator_init); | ||
| 412 | module_exit(gpio_switch_regulator_exit); | ||
diff --git a/drivers/regulator/max77663-regulator.c b/drivers/regulator/max77663-regulator.c new file mode 100644 index 00000000000..dca8ece4c43 --- /dev/null +++ b/drivers/regulator/max77663-regulator.c | |||
| @@ -0,0 +1,928 @@ | |||
| 1 | /* | ||
| 2 | * drivers/regulator/max77663-regulator.c | ||
| 3 | * Maxim LDO and Buck regulators driver | ||
| 4 | * | ||
| 5 | * Copyright 2011-2012 Maxim Integrated Products, Inc. | ||
| 6 | * Copyright (C) 2011-2012 NVIDIA Corporation | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or | ||
| 9 | * modify it under the terms of the GNU General Public License as | ||
| 10 | * published by the Free Software Foundation; either version 2 of the | ||
| 11 | * License, or (at your option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/string.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/debugfs.h> | ||
| 22 | #include <linux/uaccess.h> | ||
| 23 | #include <linux/i2c.h> | ||
| 24 | #include <linux/mfd/core.h> | ||
| 25 | #include <linux/mfd/max77663-core.h> | ||
| 26 | #include <linux/regulator/driver.h> | ||
| 27 | #include <linux/regulator/machine.h> | ||
| 28 | #include <linux/regulator/max77663-regulator.h> | ||
| 29 | |||
| 30 | /* Regulator types */ | ||
| 31 | #define REGULATOR_TYPE_SD 0 | ||
| 32 | #define REGULATOR_TYPE_LDO_N 1 | ||
| 33 | #define REGULATOR_TYPE_LDO_P 2 | ||
| 34 | |||
| 35 | /* SD and LDO Registers */ | ||
| 36 | #define MAX77663_REG_SD0 0x16 | ||
| 37 | #define MAX77663_REG_SD1 0x17 | ||
| 38 | #define MAX77663_REG_SD2 0x18 | ||
| 39 | #define MAX77663_REG_SD3 0x19 | ||
| 40 | #define MAX77663_REG_SD4 0x1A | ||
| 41 | #define MAX77663_REG_DVSSD0 0x1B | ||
| 42 | #define MAX77663_REG_DVSSD1 0x1C | ||
| 43 | #define MAX77663_REG_SD0_CFG 0x1D | ||
| 44 | #define MAX77663_REG_DVSSD0_CFG MAX77663_REG_SD0_CFG | ||
| 45 | #define MAX77663_REG_SD1_CFG 0x1E | ||
| 46 | #define MAX77663_REG_DVSSD1_CFG MAX77663_REG_SD1_CFG | ||
| 47 | #define MAX77663_REG_SD2_CFG 0x1F | ||
| 48 | #define MAX77663_REG_SD3_CFG 0x20 | ||
| 49 | #define MAX77663_REG_SD4_CFG 0x21 | ||
| 50 | #define MAX77663_REG_LDO0_CFG 0x23 | ||
| 51 | #define MAX77663_REG_LDO0_CFG2 0x24 | ||
| 52 | #define MAX77663_REG_LDO1_CFG 0x25 | ||
| 53 | #define MAX77663_REG_LDO1_CFG2 0x26 | ||
| 54 | #define MAX77663_REG_LDO2_CFG 0x27 | ||
| 55 | #define MAX77663_REG_LDO2_CFG2 0x28 | ||
| 56 | #define MAX77663_REG_LDO3_CFG 0x29 | ||
| 57 | #define MAX77663_REG_LDO3_CFG2 0x2A | ||
| 58 | #define MAX77663_REG_LDO4_CFG 0x2B | ||
| 59 | #define MAX77663_REG_LDO4_CFG2 0x2C | ||
| 60 | #define MAX77663_REG_LDO5_CFG 0x2D | ||
| 61 | #define MAX77663_REG_LDO5_CFG2 0x2E | ||
| 62 | #define MAX77663_REG_LDO6_CFG 0x2F | ||
| 63 | #define MAX77663_REG_LDO6_CFG2 0x30 | ||
| 64 | #define MAX77663_REG_LDO7_CFG 0x31 | ||
| 65 | #define MAX77663_REG_LDO7_CFG2 0x32 | ||
| 66 | #define MAX77663_REG_LDO8_CFG 0x33 | ||
| 67 | #define MAX77663_REG_LDO8_CFG2 0x34 | ||
| 68 | #define MAX77663_REG_LDO_CFG3 0x35 | ||
| 69 | |||
| 70 | /* Power Mode */ | ||
| 71 | #define POWER_MODE_NORMAL 3 | ||
| 72 | #define POWER_MODE_LPM 2 | ||
| 73 | #define POWER_MODE_GLPM 1 | ||
| 74 | #define POWER_MODE_DISABLE 0 | ||
| 75 | #define SD_POWER_MODE_MASK 0x30 | ||
| 76 | #define SD_POWER_MODE_SHIFT 4 | ||
| 77 | #define LDO_POWER_MODE_MASK 0xC0 | ||
| 78 | #define LDO_POWER_MODE_SHIFT 6 | ||
| 79 | |||
| 80 | /* SD Slew Rate */ | ||
| 81 | #define SD_SR_13_75 0 | ||
| 82 | #define SD_SR_27_5 1 | ||
| 83 | #define SD_SR_55 2 | ||
| 84 | #define SD_SR_100 3 | ||
| 85 | #define SD_SR_MASK 0xC0 | ||
| 86 | #define SD_SR_SHIFT 6 | ||
| 87 | |||
| 88 | /* SD Forced PWM Mode */ | ||
| 89 | #define SD_FPWM_MASK 0x04 | ||
| 90 | #define SD_FPWM_SHIFT 2 | ||
| 91 | |||
| 92 | /* SD Failling slew rate Active-Discharge Mode */ | ||
| 93 | #define SD_FSRADE_MASK 0x01 | ||
| 94 | #define SD_FSRADE_SHIFT 0 | ||
| 95 | |||
| 96 | /* LDO Configuration 3 */ | ||
| 97 | #define TRACK4_MASK 0x20 | ||
| 98 | #define TRACK4_SHIFT 5 | ||
| 99 | |||
| 100 | /* Voltage */ | ||
| 101 | #define SDX_VOLT_MASK 0xFF | ||
| 102 | #define SD1_VOLT_MASK 0x3F | ||
| 103 | #define LDO_VOLT_MASK 0x3F | ||
| 104 | |||
| 105 | /* FPS Registers */ | ||
| 106 | #define MAX77663_REG_FPS_CFG0 0x43 | ||
| 107 | #define MAX77663_REG_FPS_CFG1 0x44 | ||
| 108 | #define MAX77663_REG_FPS_CFG2 0x45 | ||
| 109 | #define MAX77663_REG_FPS_LDO0 0x46 | ||
| 110 | #define MAX77663_REG_FPS_LDO1 0x47 | ||
| 111 | #define MAX77663_REG_FPS_LDO2 0x48 | ||
| 112 | #define MAX77663_REG_FPS_LDO3 0x49 | ||
| 113 | #define MAX77663_REG_FPS_LDO4 0x4A | ||
| 114 | #define MAX77663_REG_FPS_LDO5 0x4B | ||
| 115 | #define MAX77663_REG_FPS_LDO6 0x4C | ||
| 116 | #define MAX77663_REG_FPS_LDO7 0x4D | ||
| 117 | #define MAX77663_REG_FPS_LDO8 0x4E | ||
| 118 | #define MAX77663_REG_FPS_SD0 0x4F | ||
| 119 | #define MAX77663_REG_FPS_SD1 0x50 | ||
| 120 | #define MAX77663_REG_FPS_SD2 0x51 | ||
| 121 | #define MAX77663_REG_FPS_SD3 0x52 | ||
| 122 | #define MAX77663_REG_FPS_SD4 0x53 | ||
| 123 | #define MAX77663_REG_FPS_NONE 0 | ||
| 124 | |||
| 125 | #define FPS_TIME_PERIOD_MASK 0x38 | ||
| 126 | #define FPS_TIME_PERIOD_SHIFT 3 | ||
| 127 | #define FPS_EN_SRC_MASK 0x06 | ||
| 128 | #define FPS_EN_SRC_SHIFT 1 | ||
| 129 | #define FPS_SW_EN_MASK 0x01 | ||
| 130 | #define FPS_SW_EN_SHIFT 0 | ||
| 131 | #define FPS_SRC_MASK 0xC0 | ||
| 132 | #define FPS_SRC_SHIFT 6 | ||
| 133 | #define FPS_PU_PERIOD_MASK 0x38 | ||
| 134 | #define FPS_PU_PERIOD_SHIFT 3 | ||
| 135 | #define FPS_PD_PERIOD_MASK 0x07 | ||
| 136 | #define FPS_PD_PERIOD_SHIFT 0 | ||
| 137 | |||
| 138 | /* Chip Identification Register */ | ||
| 139 | #define MAX77663_REG_CID5 0x5D | ||
| 140 | |||
| 141 | #define CID_DIDM_MASK 0xF0 | ||
| 142 | #define CID_DIDM_SHIFT 4 | ||
| 143 | |||
| 144 | #define SD_SAFE_DOWN_UV 50000 /* 50mV */ | ||
| 145 | |||
| 146 | enum { | ||
| 147 | VOLT_REG = 0, | ||
| 148 | CFG_REG, | ||
| 149 | FPS_REG, | ||
| 150 | }; | ||
| 151 | |||
| 152 | struct max77663_register { | ||
| 153 | u8 addr; | ||
| 154 | u8 val; | ||
| 155 | }; | ||
| 156 | |||
| 157 | struct max77663_regulator { | ||
| 158 | struct regulator_dev *rdev; | ||
| 159 | struct device *dev; | ||
| 160 | struct max77663_regulator_platform_data *pdata; | ||
| 161 | |||
| 162 | u8 id; | ||
| 163 | u8 type; | ||
| 164 | u32 min_uV; | ||
| 165 | u32 max_uV; | ||
| 166 | u32 step_uV; | ||
| 167 | int safe_down_uV; /* for stable down scaling */ | ||
| 168 | u32 regulator_mode; | ||
| 169 | |||
| 170 | struct max77663_register regs[3]; /* volt, cfg, fps */ | ||
| 171 | enum max77663_regulator_fps_src fps_src; | ||
| 172 | |||
| 173 | u8 volt_mask; | ||
| 174 | |||
| 175 | u8 power_mode; | ||
| 176 | u8 power_mode_mask; | ||
| 177 | u8 power_mode_shift; | ||
| 178 | }; | ||
| 179 | |||
| 180 | #define fps_src_name(fps_src) \ | ||
| 181 | (fps_src == FPS_SRC_0 ? "FPS_SRC_0" : \ | ||
| 182 | fps_src == FPS_SRC_1 ? "FPS_SRC_1" : \ | ||
| 183 | fps_src == FPS_SRC_2 ? "FPS_SRC_2" : "FPS_SRC_NONE") | ||
| 184 | |||
| 185 | static int fps_cfg_init; | ||
| 186 | static struct max77663_register fps_cfg_regs[] = { | ||
| 187 | { | ||
| 188 | .addr = MAX77663_REG_FPS_CFG0, | ||
| 189 | }, | ||
| 190 | { | ||
| 191 | .addr = MAX77663_REG_FPS_CFG1, | ||
| 192 | }, | ||
| 193 | { | ||
| 194 | .addr = MAX77663_REG_FPS_CFG2, | ||
| 195 | }, | ||
| 196 | }; | ||
| 197 | |||
| 198 | static inline struct max77663_regulator_platform_data | ||
| 199 | *_to_pdata(struct max77663_regulator *reg) | ||
| 200 | { | ||
| 201 | return reg->pdata; | ||
| 202 | } | ||
| 203 | |||
| 204 | static inline struct device *_to_parent(struct max77663_regulator *reg) | ||
| 205 | { | ||
| 206 | return reg->dev->parent; | ||
| 207 | } | ||
| 208 | |||
| 209 | static inline int max77663_regulator_cache_write(struct max77663_regulator *reg, | ||
| 210 | u8 addr, u8 mask, u8 val, u8 *cache) | ||
| 211 | { | ||
| 212 | struct device *parent = _to_parent(reg); | ||
| 213 | u8 new_val; | ||
| 214 | int ret; | ||
| 215 | |||
| 216 | new_val = (*cache & ~mask) | (val & mask); | ||
| 217 | if (*cache != new_val) { | ||
| 218 | ret = max77663_write(parent, addr, &new_val, 1, 0); | ||
| 219 | if (ret < 0) | ||
| 220 | return ret; | ||
| 221 | |||
| 222 | *cache = new_val; | ||
| 223 | } | ||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | static int | ||
| 228 | max77663_regulator_set_fps_src(struct max77663_regulator *reg, | ||
| 229 | enum max77663_regulator_fps_src fps_src) | ||
| 230 | { | ||
| 231 | int ret; | ||
| 232 | |||
| 233 | if ((reg->regs[FPS_REG].addr == MAX77663_REG_FPS_NONE) || | ||
| 234 | (reg->fps_src == fps_src)) | ||
| 235 | return 0; | ||
| 236 | |||
| 237 | switch (fps_src) { | ||
| 238 | case FPS_SRC_0: | ||
| 239 | case FPS_SRC_1: | ||
| 240 | case FPS_SRC_2: | ||
| 241 | case FPS_SRC_NONE: | ||
| 242 | break; | ||
| 243 | case FPS_SRC_DEF: | ||
| 244 | return 0; | ||
| 245 | default: | ||
| 246 | return -EINVAL; | ||
| 247 | } | ||
| 248 | |||
| 249 | ret = max77663_regulator_cache_write(reg, reg->regs[FPS_REG].addr, | ||
| 250 | FPS_SRC_MASK, fps_src << FPS_SRC_SHIFT, | ||
| 251 | ®->regs[FPS_REG].val); | ||
| 252 | if (ret < 0) | ||
| 253 | return ret; | ||
| 254 | |||
| 255 | reg->fps_src = fps_src; | ||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | static int max77663_regulator_set_fps(struct max77663_regulator *reg) | ||
| 260 | { | ||
| 261 | struct max77663_regulator_platform_data *pdata = _to_pdata(reg); | ||
| 262 | u8 fps_val = 0, fps_mask = 0; | ||
| 263 | int ret = 0; | ||
| 264 | |||
| 265 | if (reg->regs[FPS_REG].addr == MAX77663_REG_FPS_NONE) | ||
| 266 | return 0; | ||
| 267 | |||
| 268 | if (reg->fps_src == FPS_SRC_NONE) | ||
| 269 | return 0; | ||
| 270 | |||
| 271 | /* FPS power up period setting */ | ||
| 272 | if (pdata->fps_pu_period != FPS_POWER_PERIOD_DEF) { | ||
| 273 | fps_val |= (pdata->fps_pu_period << FPS_PU_PERIOD_SHIFT); | ||
| 274 | fps_mask |= FPS_PU_PERIOD_MASK; | ||
| 275 | } | ||
| 276 | |||
| 277 | /* FPS power down period setting */ | ||
| 278 | if (pdata->fps_pd_period != FPS_POWER_PERIOD_DEF) { | ||
| 279 | fps_val |= (pdata->fps_pd_period << FPS_PD_PERIOD_SHIFT); | ||
| 280 | fps_mask |= FPS_PD_PERIOD_MASK; | ||
| 281 | } | ||
| 282 | |||
| 283 | if (fps_val) | ||
| 284 | ret = max77663_regulator_cache_write(reg, | ||
| 285 | reg->regs[FPS_REG].addr, fps_mask, | ||
| 286 | fps_val, ®->regs[FPS_REG].val); | ||
| 287 | |||
| 288 | return ret; | ||
| 289 | } | ||
| 290 | |||
| 291 | static int | ||
| 292 | max77663_regulator_set_fps_cfg(struct max77663_regulator *reg, | ||
| 293 | struct max77663_regulator_fps_cfg *fps_cfg) | ||
| 294 | { | ||
| 295 | u8 val, mask; | ||
| 296 | |||
| 297 | if ((fps_cfg->src < FPS_SRC_0) || (fps_cfg->src > FPS_SRC_2)) | ||
| 298 | return -EINVAL; | ||
| 299 | |||
| 300 | val = (fps_cfg->en_src << FPS_EN_SRC_SHIFT); | ||
| 301 | mask = FPS_EN_SRC_MASK; | ||
| 302 | |||
| 303 | if (fps_cfg->time_period != FPS_TIME_PERIOD_DEF) { | ||
| 304 | val |= (fps_cfg->time_period << FPS_TIME_PERIOD_SHIFT); | ||
| 305 | mask |= FPS_TIME_PERIOD_MASK; | ||
| 306 | } | ||
| 307 | |||
| 308 | return max77663_regulator_cache_write(reg, | ||
| 309 | fps_cfg_regs[fps_cfg->src].addr, mask, | ||
| 310 | val, &fps_cfg_regs[fps_cfg->src].val); | ||
| 311 | } | ||
| 312 | |||
| 313 | static int | ||
| 314 | max77663_regulator_set_fps_cfgs(struct max77663_regulator *reg, | ||
| 315 | struct max77663_regulator_fps_cfg *fps_cfgs, | ||
| 316 | int num_fps_cfgs) | ||
| 317 | { | ||
| 318 | struct device *parent = _to_parent(reg); | ||
| 319 | int i, ret; | ||
| 320 | |||
| 321 | if (fps_cfg_init) | ||
| 322 | return 0; | ||
| 323 | |||
| 324 | for (i = 0; i <= FPS_SRC_2; i++) { | ||
| 325 | ret = max77663_read(parent, fps_cfg_regs[i].addr, | ||
| 326 | &fps_cfg_regs[i].val, 1, 0); | ||
| 327 | if (ret < 0) | ||
| 328 | return ret; | ||
| 329 | } | ||
| 330 | |||
| 331 | for (i = 0; i < num_fps_cfgs; i++) { | ||
| 332 | ret = max77663_regulator_set_fps_cfg(reg, &fps_cfgs[i]); | ||
| 333 | if (ret < 0) | ||
| 334 | return ret; | ||
| 335 | } | ||
| 336 | fps_cfg_init = 1; | ||
| 337 | |||
| 338 | return 0; | ||
| 339 | } | ||
| 340 | |||
| 341 | static int | ||
| 342 | max77663_regulator_set_power_mode(struct max77663_regulator *reg, u8 power_mode) | ||
| 343 | { | ||
| 344 | u8 mask = reg->power_mode_mask; | ||
| 345 | u8 shift = reg->power_mode_shift; | ||
| 346 | int ret; | ||
| 347 | |||
| 348 | if (reg->type == REGULATOR_TYPE_SD) | ||
| 349 | ret = max77663_regulator_cache_write(reg, | ||
| 350 | reg->regs[CFG_REG].addr, | ||
| 351 | mask, power_mode << shift, | ||
| 352 | ®->regs[CFG_REG].val); | ||
| 353 | else | ||
| 354 | ret = max77663_regulator_cache_write(reg, | ||
| 355 | reg->regs[VOLT_REG].addr, | ||
| 356 | mask, power_mode << shift, | ||
| 357 | ®->regs[VOLT_REG].val); | ||
| 358 | |||
| 359 | if (ret < 0) | ||
| 360 | return ret; | ||
| 361 | |||
| 362 | reg->power_mode = power_mode; | ||
| 363 | return ret; | ||
| 364 | } | ||
| 365 | |||
| 366 | static u8 max77663_regulator_get_power_mode(struct max77663_regulator *reg) | ||
| 367 | { | ||
| 368 | u8 mask = reg->power_mode_mask; | ||
| 369 | u8 shift = reg->power_mode_shift; | ||
| 370 | |||
| 371 | if (reg->type == REGULATOR_TYPE_SD) | ||
| 372 | reg->power_mode = (reg->regs[CFG_REG].val & mask) >> shift; | ||
| 373 | else | ||
| 374 | reg->power_mode = (reg->regs[VOLT_REG].val & mask) >> shift; | ||
| 375 | |||
| 376 | return reg->power_mode; | ||
| 377 | } | ||
| 378 | |||
| 379 | static int max77663_regulator_do_set_voltage(struct max77663_regulator *reg, | ||
| 380 | int min_uV, int max_uV) | ||
| 381 | { | ||
| 382 | u8 addr = reg->regs[VOLT_REG].addr; | ||
| 383 | u8 mask = reg->volt_mask; | ||
| 384 | u8 *cache = ®->regs[VOLT_REG].val; | ||
| 385 | u8 val; | ||
| 386 | int old_uV, new_uV, safe_uV; | ||
| 387 | int i, steps = 1; | ||
| 388 | int ret = 0; | ||
| 389 | |||
| 390 | if (min_uV < reg->min_uV || max_uV > reg->max_uV) | ||
| 391 | return -EDOM; | ||
| 392 | |||
| 393 | old_uV = (*cache & mask) * reg->step_uV + reg->min_uV; | ||
| 394 | |||
| 395 | if ((old_uV > min_uV) && (reg->safe_down_uV >= reg->step_uV)) { | ||
| 396 | steps = DIV_ROUND_UP(old_uV - min_uV, reg->safe_down_uV); | ||
| 397 | safe_uV = -reg->safe_down_uV; | ||
| 398 | } | ||
| 399 | |||
| 400 | if (steps == 1) { | ||
| 401 | val = (min_uV - reg->min_uV) / reg->step_uV; | ||
| 402 | ret = max77663_regulator_cache_write(reg, addr, mask, val, | ||
| 403 | cache); | ||
| 404 | } else { | ||
| 405 | for (i = 0; i < steps; i++) { | ||
| 406 | if (abs(min_uV - old_uV) > abs(safe_uV)) | ||
| 407 | new_uV = old_uV + safe_uV; | ||
| 408 | else | ||
| 409 | new_uV = min_uV; | ||
| 410 | |||
| 411 | dev_dbg(®->rdev->dev, "do_set_voltage: name=%s, " | ||
| 412 | "%d/%d, old_uV=%d, new_uV=%d\n", | ||
| 413 | reg->rdev->desc->name, i + 1, steps, old_uV, | ||
| 414 | new_uV); | ||
| 415 | |||
| 416 | val = (new_uV - reg->min_uV) / reg->step_uV; | ||
| 417 | ret = max77663_regulator_cache_write(reg, addr, mask, | ||
| 418 | val, cache); | ||
| 419 | if (ret < 0) | ||
| 420 | return ret; | ||
| 421 | |||
| 422 | old_uV = new_uV; | ||
| 423 | } | ||
| 424 | } | ||
| 425 | |||
| 426 | return ret; | ||
| 427 | } | ||
| 428 | |||
| 429 | static int max77663_regulator_set_voltage(struct regulator_dev *rdev, | ||
| 430 | int min_uV, int max_uV, | ||
| 431 | unsigned *selector) | ||
| 432 | { | ||
| 433 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
| 434 | |||
| 435 | dev_dbg(&rdev->dev, "set_voltage: name=%s, min_uV=%d, max_uV=%d\n", | ||
| 436 | rdev->desc->name, min_uV, max_uV); | ||
| 437 | return max77663_regulator_do_set_voltage(reg, min_uV, max_uV); | ||
| 438 | } | ||
| 439 | |||
| 440 | static int max77663_regulator_get_voltage(struct regulator_dev *rdev) | ||
| 441 | { | ||
| 442 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
| 443 | int volt; | ||
| 444 | |||
| 445 | volt = (reg->regs[VOLT_REG].val & reg->volt_mask) | ||
| 446 | * reg->step_uV + reg->min_uV; | ||
| 447 | |||
| 448 | dev_dbg(&rdev->dev, "get_voltage: name=%s, volt=%d, val=0x%02x\n", | ||
| 449 | rdev->desc->name, volt, reg->regs[VOLT_REG].val); | ||
| 450 | return volt; | ||
| 451 | } | ||
| 452 | |||
| 453 | static int max77663_regulator_enable(struct regulator_dev *rdev) | ||
| 454 | { | ||
| 455 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
| 456 | struct max77663_regulator_platform_data *pdata = _to_pdata(reg); | ||
| 457 | int power_mode = (pdata->flags & GLPM_ENABLE) ? | ||
| 458 | POWER_MODE_GLPM : POWER_MODE_NORMAL; | ||
| 459 | |||
| 460 | if (reg->fps_src != FPS_SRC_NONE) { | ||
| 461 | dev_dbg(&rdev->dev, "enable: Regulator %s using %s\n", | ||
| 462 | rdev->desc->name, fps_src_name(reg->fps_src)); | ||
| 463 | return 0; | ||
| 464 | } | ||
| 465 | |||
| 466 | if ((reg->id == MAX77663_REGULATOR_ID_SD0) | ||
| 467 | && (pdata->flags & EN2_CTRL_SD0)) { | ||
| 468 | dev_dbg(&rdev->dev, | ||
| 469 | "enable: Regulator %s is controlled by EN2\n", | ||
| 470 | rdev->desc->name); | ||
| 471 | return 0; | ||
| 472 | } | ||
| 473 | |||
| 474 | /* N-Channel LDOs don't support Low-Power mode. */ | ||
| 475 | if ((reg->type != REGULATOR_TYPE_LDO_N) && | ||
| 476 | (reg->regulator_mode == REGULATOR_MODE_STANDBY)) | ||
| 477 | power_mode = POWER_MODE_LPM; | ||
| 478 | |||
| 479 | return max77663_regulator_set_power_mode(reg, power_mode); | ||
| 480 | } | ||
| 481 | |||
| 482 | static int max77663_regulator_disable(struct regulator_dev *rdev) | ||
| 483 | { | ||
| 484 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
| 485 | struct max77663_regulator_platform_data *pdata = _to_pdata(reg); | ||
| 486 | int power_mode = POWER_MODE_DISABLE; | ||
| 487 | |||
| 488 | if (reg->fps_src != FPS_SRC_NONE) { | ||
| 489 | dev_dbg(&rdev->dev, "disable: Regulator %s using %s\n", | ||
| 490 | rdev->desc->name, fps_src_name(reg->fps_src)); | ||
| 491 | return 0; | ||
| 492 | } | ||
| 493 | |||
| 494 | if ((reg->id == MAX77663_REGULATOR_ID_SD0) | ||
| 495 | && (pdata->flags & EN2_CTRL_SD0)) { | ||
| 496 | dev_dbg(&rdev->dev, | ||
| 497 | "disable: Regulator %s is controlled by EN2\n", | ||
| 498 | rdev->desc->name); | ||
| 499 | return 0; | ||
| 500 | } | ||
| 501 | |||
| 502 | return max77663_regulator_set_power_mode(reg, power_mode); | ||
| 503 | } | ||
| 504 | |||
| 505 | static int max77663_regulator_is_enabled(struct regulator_dev *rdev) | ||
| 506 | { | ||
| 507 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
| 508 | struct max77663_regulator_platform_data *pdata = _to_pdata(reg); | ||
| 509 | int ret = 1; | ||
| 510 | |||
| 511 | if (reg->fps_src != FPS_SRC_NONE) { | ||
| 512 | dev_dbg(&rdev->dev, "is_enable: Regulator %s using %s\n", | ||
| 513 | rdev->desc->name, fps_src_name(reg->fps_src)); | ||
| 514 | return 1; | ||
| 515 | } | ||
| 516 | |||
| 517 | if ((reg->id == MAX77663_REGULATOR_ID_SD0) | ||
| 518 | && (pdata->flags & EN2_CTRL_SD0)) { | ||
| 519 | dev_dbg(&rdev->dev, | ||
| 520 | "is_enable: Regulator %s is controlled by EN2\n", | ||
| 521 | rdev->desc->name); | ||
| 522 | return 1; | ||
| 523 | } | ||
| 524 | |||
| 525 | if (max77663_regulator_get_power_mode(reg) == POWER_MODE_DISABLE) | ||
| 526 | ret = 0; | ||
| 527 | |||
| 528 | return ret; | ||
| 529 | } | ||
| 530 | |||
| 531 | static int max77663_regulator_set_mode(struct regulator_dev *rdev, | ||
| 532 | unsigned int mode) | ||
| 533 | { | ||
| 534 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
| 535 | struct max77663_regulator_platform_data *pdata = _to_pdata(reg); | ||
| 536 | u8 power_mode; | ||
| 537 | int ret; | ||
| 538 | |||
| 539 | if (mode == REGULATOR_MODE_NORMAL) | ||
| 540 | power_mode = (pdata->flags & GLPM_ENABLE) ? | ||
| 541 | POWER_MODE_GLPM : POWER_MODE_NORMAL; | ||
| 542 | else if (mode == REGULATOR_MODE_STANDBY) { | ||
| 543 | /* N-Channel LDOs don't support Low-Power mode. */ | ||
| 544 | power_mode = (reg->type != REGULATOR_TYPE_LDO_N) ? | ||
| 545 | POWER_MODE_LPM : POWER_MODE_NORMAL; | ||
| 546 | } else | ||
| 547 | return -EINVAL; | ||
| 548 | |||
| 549 | ret = max77663_regulator_set_power_mode(reg, power_mode); | ||
| 550 | if (!ret) | ||
| 551 | reg->regulator_mode = mode; | ||
| 552 | |||
| 553 | return ret; | ||
| 554 | } | ||
| 555 | |||
| 556 | static unsigned int max77663_regulator_get_mode(struct regulator_dev *rdev) | ||
| 557 | { | ||
| 558 | struct max77663_regulator *reg = rdev_get_drvdata(rdev); | ||
| 559 | |||
| 560 | return reg->regulator_mode; | ||
| 561 | } | ||
| 562 | |||
| 563 | static struct regulator_ops max77663_ldo_ops = { | ||
| 564 | .set_voltage = max77663_regulator_set_voltage, | ||
| 565 | .get_voltage = max77663_regulator_get_voltage, | ||
| 566 | .enable = max77663_regulator_enable, | ||
| 567 | .disable = max77663_regulator_disable, | ||
| 568 | .is_enabled = max77663_regulator_is_enabled, | ||
| 569 | .set_mode = max77663_regulator_set_mode, | ||
| 570 | .get_mode = max77663_regulator_get_mode, | ||
| 571 | }; | ||
| 572 | |||
| 573 | static int max77663_regulator_preinit(struct max77663_regulator *reg) | ||
| 574 | { | ||
| 575 | struct max77663_regulator_platform_data *pdata = _to_pdata(reg); | ||
| 576 | struct device *parent = _to_parent(reg); | ||
| 577 | int i; | ||
| 578 | u8 val, mask; | ||
| 579 | int ret; | ||
| 580 | |||
| 581 | /* Update registers */ | ||
| 582 | for (i = 0; i <= FPS_REG; i++) { | ||
| 583 | ret = max77663_read(parent, reg->regs[i].addr, | ||
| 584 | ®->regs[i].val, 1, 0); | ||
| 585 | if (ret < 0) { | ||
| 586 | dev_err(reg->dev, | ||
| 587 | "preinit: Failed to get register 0x%x\n", | ||
| 588 | reg->regs[i].addr); | ||
| 589 | return ret; | ||
| 590 | } | ||
| 591 | } | ||
| 592 | |||
| 593 | /* Update FPS source */ | ||
| 594 | if (reg->regs[FPS_REG].addr == MAX77663_REG_FPS_NONE) | ||
| 595 | reg->fps_src = FPS_SRC_NONE; | ||
| 596 | else | ||
| 597 | reg->fps_src = (reg->regs[FPS_REG].val & FPS_SRC_MASK) | ||
| 598 | >> FPS_SRC_SHIFT; | ||
| 599 | |||
| 600 | dev_dbg(reg->dev, "preinit: initial fps_src=%s\n", | ||
| 601 | fps_src_name(reg->fps_src)); | ||
| 602 | |||
| 603 | /* Update power mode */ | ||
| 604 | max77663_regulator_get_power_mode(reg); | ||
| 605 | |||
| 606 | /* Check Chip Identification */ | ||
| 607 | ret = max77663_read(parent, MAX77663_REG_CID5, &val, 1, 0); | ||
| 608 | if (ret < 0) { | ||
| 609 | dev_err(reg->dev, "preinit: Failed to get register 0x%x\n", | ||
| 610 | MAX77663_REG_CID5); | ||
| 611 | return ret; | ||
| 612 | } | ||
| 613 | |||
| 614 | /* If metal revision is less than rev.3, | ||
| 615 | * set safe_down_uV for stable down scaling. */ | ||
| 616 | if ((reg->type == REGULATOR_TYPE_SD) && | ||
| 617 | ((val & CID_DIDM_MASK) >> CID_DIDM_SHIFT) <= 2) | ||
| 618 | reg->safe_down_uV = SD_SAFE_DOWN_UV; | ||
| 619 | else | ||
| 620 | reg->safe_down_uV = 0; | ||
| 621 | |||
| 622 | /* Set FPS */ | ||
| 623 | ret = max77663_regulator_set_fps_cfgs(reg, pdata->fps_cfgs, | ||
| 624 | pdata->num_fps_cfgs); | ||
| 625 | if (ret < 0) { | ||
| 626 | dev_err(reg->dev, "preinit: Failed to set FPSCFG\n"); | ||
| 627 | return ret; | ||
| 628 | } | ||
| 629 | |||
| 630 | /* N-Channel LDOs don't support Low-Power mode. */ | ||
| 631 | if ((reg->type == REGULATOR_TYPE_LDO_N) && | ||
| 632 | (pdata->flags & GLPM_ENABLE)) | ||
| 633 | pdata->flags &= ~GLPM_ENABLE; | ||
| 634 | |||
| 635 | /* To prevent power rail turn-off when change FPS source, | ||
| 636 | * it must set power mode to NORMAL before change FPS source to NONE | ||
| 637 | * from SRC_0, SRC_1 and SRC_2. */ | ||
| 638 | if ((reg->fps_src != FPS_SRC_NONE) && (pdata->fps_src == FPS_SRC_NONE) | ||
| 639 | && (reg->power_mode != POWER_MODE_NORMAL)) { | ||
| 640 | val = (pdata->flags & GLPM_ENABLE) ? | ||
| 641 | POWER_MODE_GLPM : POWER_MODE_NORMAL; | ||
| 642 | ret = max77663_regulator_set_power_mode(reg, val); | ||
| 643 | if (ret < 0) { | ||
| 644 | dev_err(reg->dev, "preinit: Failed to " | ||
| 645 | "set power mode to POWER_MODE_NORMAL\n"); | ||
| 646 | return ret; | ||
| 647 | } | ||
| 648 | } | ||
| 649 | |||
| 650 | ret = max77663_regulator_set_fps_src(reg, pdata->fps_src); | ||
| 651 | if (ret < 0) { | ||
| 652 | dev_err(reg->dev, "preinit: Failed to set FPSSRC to %d\n", | ||
| 653 | pdata->fps_src); | ||
| 654 | return ret; | ||
| 655 | } | ||
| 656 | |||
| 657 | ret = max77663_regulator_set_fps(reg); | ||
| 658 | if (ret < 0) { | ||
| 659 | dev_err(reg->dev, "preinit: Failed to set FPS\n"); | ||
| 660 | return ret; | ||
| 661 | } | ||
| 662 | |||
| 663 | /* Set initial state */ | ||
| 664 | if (!pdata->init_apply) | ||
| 665 | goto skip_init_apply; | ||
| 666 | |||
| 667 | if (pdata->init_uV >= 0) { | ||
| 668 | ret = max77663_regulator_do_set_voltage(reg, pdata->init_uV, | ||
| 669 | pdata->init_uV); | ||
| 670 | if (ret < 0) { | ||
| 671 | dev_err(reg->dev, "preinit: Failed to set voltage to " | ||
| 672 | "%d\n", pdata->init_uV); | ||
| 673 | return ret; | ||
| 674 | } | ||
| 675 | } | ||
| 676 | |||
| 677 | if (pdata->init_enable) | ||
| 678 | val = (pdata->flags & GLPM_ENABLE) ? | ||
| 679 | POWER_MODE_GLPM : POWER_MODE_NORMAL; | ||
| 680 | else | ||
| 681 | val = POWER_MODE_DISABLE; | ||
| 682 | |||
| 683 | ret = max77663_regulator_set_power_mode(reg, val); | ||
| 684 | if (ret < 0) { | ||
| 685 | dev_err(reg->dev, | ||
| 686 | "preinit: Failed to set power mode to %d\n", val); | ||
| 687 | return ret; | ||
| 688 | } | ||
| 689 | |||
| 690 | skip_init_apply: | ||
| 691 | if (reg->type == REGULATOR_TYPE_SD) { | ||
| 692 | val = 0; | ||
| 693 | mask = 0; | ||
| 694 | |||
| 695 | if (pdata->flags & SD_SLEW_RATE_MASK) { | ||
| 696 | mask |= SD_SR_MASK; | ||
| 697 | if (pdata->flags & SD_SLEW_RATE_SLOWEST) | ||
| 698 | val |= (SD_SR_13_75 << SD_SR_SHIFT); | ||
| 699 | else if (pdata->flags & SD_SLEW_RATE_SLOW) | ||
| 700 | val |= (SD_SR_27_5 << SD_SR_SHIFT); | ||
| 701 | else if (pdata->flags & SD_SLEW_RATE_FAST) | ||
| 702 | val |= (SD_SR_55 << SD_SR_SHIFT); | ||
| 703 | else | ||
| 704 | val |= (SD_SR_100 << SD_SR_SHIFT); | ||
| 705 | } | ||
| 706 | |||
| 707 | if (pdata->flags & SD_FORCED_PWM_MODE) { | ||
| 708 | mask |= SD_FPWM_MASK; | ||
| 709 | val |= SD_FPWM_MASK; | ||
| 710 | } | ||
| 711 | |||
| 712 | if (pdata->flags & SD_FSRADE_DISABLE) { | ||
| 713 | mask |= SD_FSRADE_MASK; | ||
| 714 | val |= SD_FSRADE_MASK; | ||
| 715 | } | ||
| 716 | |||
| 717 | ret = max77663_regulator_cache_write(reg, | ||
| 718 | reg->regs[CFG_REG].addr, mask, val, | ||
| 719 | ®->regs[CFG_REG].val); | ||
| 720 | if (ret < 0) { | ||
| 721 | dev_err(reg->dev, "preinit: " | ||
| 722 | "Failed to set register 0x%x\n", | ||
| 723 | reg->regs[CFG_REG].addr); | ||
| 724 | return ret; | ||
| 725 | } | ||
| 726 | |||
| 727 | if ((reg->id == MAX77663_REGULATOR_ID_SD0) | ||
| 728 | && (pdata->flags & EN2_CTRL_SD0)) { | ||
| 729 | val = POWER_MODE_DISABLE; | ||
| 730 | ret = max77663_regulator_set_power_mode(reg, val); | ||
| 731 | if (ret < 0) { | ||
| 732 | dev_err(reg->dev, "preinit: " | ||
| 733 | "Failed to set power mode to %d for " | ||
| 734 | "EN2_CTRL_SD0\n", val); | ||
| 735 | return ret; | ||
| 736 | } | ||
| 737 | |||
| 738 | ret = max77663_regulator_set_fps_src(reg, FPS_SRC_NONE); | ||
| 739 | if (ret < 0) { | ||
| 740 | dev_err(reg->dev, "preinit: " | ||
| 741 | "Failed to set FPSSRC to FPS_SRC_NONE " | ||
| 742 | "for EN2_CTRL_SD0\n"); | ||
| 743 | return ret; | ||
| 744 | } | ||
| 745 | } | ||
| 746 | } | ||
| 747 | |||
| 748 | if ((reg->id == MAX77663_REGULATOR_ID_LDO4) | ||
| 749 | && (pdata->flags & LDO4_EN_TRACKING)) { | ||
| 750 | val = TRACK4_MASK; | ||
| 751 | ret = max77663_write(parent, MAX77663_REG_LDO_CFG3, &val, 1, 0); | ||
| 752 | if (ret < 0) { | ||
| 753 | dev_err(reg->dev, "preinit: " | ||
| 754 | "Failed to set register 0x%x\n", | ||
| 755 | MAX77663_REG_LDO_CFG3); | ||
| 756 | return ret; | ||
| 757 | } | ||
| 758 | } | ||
| 759 | |||
| 760 | return 0; | ||
| 761 | } | ||
| 762 | |||
| 763 | #define REGULATOR_SD(_id, _volt_mask, _fps_reg, _min_uV, _max_uV, _step_uV) \ | ||
| 764 | [MAX77663_REGULATOR_ID_##_id] = { \ | ||
| 765 | .id = MAX77663_REGULATOR_ID_##_id, \ | ||
| 766 | .type = REGULATOR_TYPE_SD, \ | ||
| 767 | .volt_mask = _volt_mask##_VOLT_MASK, \ | ||
| 768 | .regs = { \ | ||
| 769 | [VOLT_REG] = { \ | ||
| 770 | .addr = MAX77663_REG_##_id, \ | ||
| 771 | }, \ | ||
| 772 | [CFG_REG] = { \ | ||
| 773 | .addr = MAX77663_REG_##_id##_CFG, \ | ||
| 774 | }, \ | ||
| 775 | [FPS_REG] = { \ | ||
| 776 | .addr = MAX77663_REG_FPS_##_fps_reg, \ | ||
| 777 | }, \ | ||
| 778 | }, \ | ||
| 779 | .min_uV = _min_uV, \ | ||
| 780 | .max_uV = _max_uV, \ | ||
| 781 | .step_uV = _step_uV, \ | ||
| 782 | .regulator_mode = REGULATOR_MODE_NORMAL, \ | ||
| 783 | .power_mode = POWER_MODE_NORMAL, \ | ||
| 784 | .power_mode_mask = SD_POWER_MODE_MASK, \ | ||
| 785 | .power_mode_shift = SD_POWER_MODE_SHIFT, \ | ||
| 786 | } | ||
| 787 | |||
| 788 | #define REGULATOR_LDO(_id, _type, _min_uV, _max_uV, _step_uV) \ | ||
| 789 | [MAX77663_REGULATOR_ID_##_id] = { \ | ||
| 790 | .id = MAX77663_REGULATOR_ID_##_id, \ | ||
| 791 | .type = REGULATOR_TYPE_LDO_##_type, \ | ||
| 792 | .volt_mask = LDO_VOLT_MASK, \ | ||
| 793 | .regs = { \ | ||
| 794 | [VOLT_REG] = { \ | ||
| 795 | .addr = MAX77663_REG_##_id##_CFG, \ | ||
| 796 | }, \ | ||
| 797 | [CFG_REG] = { \ | ||
| 798 | .addr = MAX77663_REG_##_id##_CFG2, \ | ||
| 799 | }, \ | ||
| 800 | [FPS_REG] = { \ | ||
| 801 | .addr = MAX77663_REG_FPS_##_id, \ | ||
| 802 | }, \ | ||
| 803 | }, \ | ||
| 804 | .min_uV = _min_uV, \ | ||
| 805 | .max_uV = _max_uV, \ | ||
| 806 | .step_uV = _step_uV, \ | ||
| 807 | .regulator_mode = REGULATOR_MODE_NORMAL, \ | ||
| 808 | .power_mode = POWER_MODE_NORMAL, \ | ||
| 809 | .power_mode_mask = LDO_POWER_MODE_MASK, \ | ||
| 810 | .power_mode_shift = LDO_POWER_MODE_SHIFT, \ | ||
| 811 | } | ||
| 812 | |||
| 813 | static struct max77663_regulator max77663_regs[MAX77663_REGULATOR_ID_NR] = { | ||
| 814 | REGULATOR_SD(SD0, SDX, SD0, 600000, 3387500, 12500), | ||
| 815 | REGULATOR_SD(DVSSD0, SDX, NONE, 600000, 3387500, 12500), | ||
| 816 | REGULATOR_SD(SD1, SD1, SD1, 800000, 1587500, 12500), | ||
| 817 | REGULATOR_SD(DVSSD1, SD1, NONE, 800000, 1587500, 12500), | ||
| 818 | REGULATOR_SD(SD2, SDX, SD2, 600000, 3387500, 12500), | ||
| 819 | REGULATOR_SD(SD3, SDX, SD3, 600000, 3387500, 12500), | ||
| 820 | REGULATOR_SD(SD4, SDX, SD4, 600000, 3387500, 12500), | ||
| 821 | |||
| 822 | REGULATOR_LDO(LDO0, N, 800000, 2350000, 25000), | ||
| 823 | REGULATOR_LDO(LDO1, N, 800000, 2350000, 25000), | ||
| 824 | REGULATOR_LDO(LDO2, P, 800000, 3950000, 50000), | ||
| 825 | REGULATOR_LDO(LDO3, P, 800000, 3950000, 50000), | ||
| 826 | REGULATOR_LDO(LDO4, P, 800000, 1587500, 12500), | ||
| 827 | REGULATOR_LDO(LDO5, P, 800000, 3950000, 50000), | ||
| 828 | REGULATOR_LDO(LDO6, P, 800000, 3950000, 50000), | ||
| 829 | REGULATOR_LDO(LDO7, N, 800000, 3950000, 50000), | ||
| 830 | REGULATOR_LDO(LDO8, N, 800000, 3950000, 50000), | ||
| 831 | }; | ||
| 832 | |||
| 833 | #define REGULATOR_DESC(_id, _name) \ | ||
| 834 | [MAX77663_REGULATOR_ID_##_id] = { \ | ||
| 835 | .name = max77663_rails(_name), \ | ||
| 836 | .id = MAX77663_REGULATOR_ID_##_id, \ | ||
| 837 | .ops = &max77663_ldo_ops, \ | ||
| 838 | .type = REGULATOR_VOLTAGE, \ | ||
| 839 | .owner = THIS_MODULE, \ | ||
| 840 | } | ||
| 841 | |||
| 842 | static struct regulator_desc max77663_rdesc[MAX77663_REGULATOR_ID_NR] = { | ||
| 843 | REGULATOR_DESC(SD0, sd0), | ||
| 844 | REGULATOR_DESC(DVSSD0, dvssd0), | ||
| 845 | REGULATOR_DESC(SD1, sd1), | ||
| 846 | REGULATOR_DESC(DVSSD1, dvssd1), | ||
| 847 | REGULATOR_DESC(SD2, sd2), | ||
| 848 | REGULATOR_DESC(SD3, sd3), | ||
| 849 | REGULATOR_DESC(SD4, sd4), | ||
| 850 | REGULATOR_DESC(LDO0, ldo0), | ||
| 851 | REGULATOR_DESC(LDO1, ldo1), | ||
| 852 | REGULATOR_DESC(LDO2, ldo2), | ||
| 853 | REGULATOR_DESC(LDO3, ldo3), | ||
| 854 | REGULATOR_DESC(LDO4, ldo4), | ||
| 855 | REGULATOR_DESC(LDO5, ldo5), | ||
| 856 | REGULATOR_DESC(LDO6, ldo6), | ||
| 857 | REGULATOR_DESC(LDO7, ldo7), | ||
| 858 | REGULATOR_DESC(LDO8, ldo8), | ||
| 859 | }; | ||
| 860 | |||
| 861 | static int max77663_regulator_probe(struct platform_device *pdev) | ||
| 862 | { | ||
| 863 | struct regulator_desc *rdesc; | ||
| 864 | struct max77663_regulator *reg; | ||
| 865 | int ret = 0; | ||
| 866 | |||
| 867 | if ((pdev->id < 0) || (pdev->id >= MAX77663_REGULATOR_ID_NR)) { | ||
| 868 | dev_err(&pdev->dev, "Invalid device id %d\n", pdev->id); | ||
| 869 | return -ENODEV; | ||
| 870 | } | ||
| 871 | |||
| 872 | rdesc = &max77663_rdesc[pdev->id]; | ||
| 873 | reg = &max77663_regs[pdev->id]; | ||
| 874 | reg->dev = &pdev->dev; | ||
| 875 | reg->pdata = dev_get_platdata(&pdev->dev); | ||
| 876 | |||
| 877 | dev_dbg(&pdev->dev, "probe: name=%s\n", rdesc->name); | ||
| 878 | |||
| 879 | ret = max77663_regulator_preinit(reg); | ||
| 880 | if (ret) { | ||
| 881 | dev_err(&pdev->dev, "probe: Failed to preinit regulator %s\n", | ||
| 882 | rdesc->name); | ||
| 883 | return ret; | ||
| 884 | } | ||
| 885 | |||
| 886 | reg->rdev = regulator_register(rdesc, &pdev->dev, | ||
| 887 | ®->pdata->init_data, reg); | ||
| 888 | if (IS_ERR(reg->rdev)) { | ||
| 889 | dev_err(&pdev->dev, "probe: Failed to register regulator %s\n", | ||
| 890 | rdesc->name); | ||
| 891 | return PTR_ERR(reg->rdev); | ||
| 892 | } | ||
| 893 | |||
| 894 | return 0; | ||
| 895 | } | ||
| 896 | |||
| 897 | static int max77663_regulator_remove(struct platform_device *pdev) | ||
| 898 | { | ||
| 899 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | ||
| 900 | |||
| 901 | regulator_unregister(rdev); | ||
| 902 | return 0; | ||
| 903 | } | ||
| 904 | |||
| 905 | static struct platform_driver max77663_regulator_driver = { | ||
| 906 | .probe = max77663_regulator_probe, | ||
| 907 | .remove = __devexit_p(max77663_regulator_remove), | ||
| 908 | .driver = { | ||
| 909 | .name = "max77663-regulator", | ||
| 910 | .owner = THIS_MODULE, | ||
| 911 | }, | ||
| 912 | }; | ||
| 913 | |||
| 914 | static int __init max77663_regulator_init(void) | ||
| 915 | { | ||
| 916 | return platform_driver_register(&max77663_regulator_driver); | ||
| 917 | } | ||
| 918 | subsys_initcall(max77663_regulator_init); | ||
| 919 | |||
| 920 | static void __exit max77663_reg_exit(void) | ||
| 921 | { | ||
| 922 | platform_driver_unregister(&max77663_regulator_driver); | ||
| 923 | } | ||
| 924 | module_exit(max77663_reg_exit); | ||
| 925 | |||
| 926 | MODULE_LICENSE("GPL v2"); | ||
| 927 | MODULE_DESCRIPTION("max77663 regulator driver"); | ||
| 928 | MODULE_VERSION("1.0"); | ||
diff --git a/drivers/regulator/max8907c-regulator.c b/drivers/regulator/max8907c-regulator.c new file mode 100644 index 00000000000..925f161d992 --- /dev/null +++ b/drivers/regulator/max8907c-regulator.c | |||
| @@ -0,0 +1,421 @@ | |||
| 1 | /* | ||
| 2 | * max8907c-regulator.c -- support regulators in max8907c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/slab.h> | ||
| 14 | #include <linux/err.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/regulator/driver.h> | ||
| 17 | #include <linux/mfd/max8907c.h> | ||
| 18 | #include <linux/regulator/max8907c-regulator.h> | ||
| 19 | |||
| 20 | #define MAX8907C_II2RR_VERSION_MASK 0xF0 | ||
| 21 | #define MAX8907C_II2RR_VERSION_REV_A 0x00 | ||
| 22 | #define MAX8907C_II2RR_VERSION_REV_B 0x10 | ||
| 23 | #define MAX8907C_II2RR_VERSION_REV_C 0x30 | ||
| 24 | |||
| 25 | #define MAX8907C_REGULATOR_CNT (ARRAY_SIZE(max8907c_regulators)) | ||
| 26 | |||
| 27 | struct max8907c_regulator_info { | ||
| 28 | u32 min_uV; | ||
| 29 | u32 max_uV; | ||
| 30 | u32 step_uV; | ||
| 31 | u8 reg_base; | ||
| 32 | struct regulator_desc desc; | ||
| 33 | struct i2c_client *i2c; | ||
| 34 | }; | ||
| 35 | |||
| 36 | #define REG_LDO(ids, base, min, max, step) \ | ||
| 37 | { \ | ||
| 38 | .min_uV = (min), \ | ||
| 39 | .max_uV = (max), \ | ||
| 40 | .step_uV = (step), \ | ||
| 41 | .reg_base = (base), \ | ||
| 42 | .desc = { \ | ||
| 43 | .name = #ids, \ | ||
| 44 | .id = MAX8907C_##ids, \ | ||
| 45 | .n_voltages = ((max) - (min)) / (step) + 1, \ | ||
| 46 | .ops = &max8907c_ldo_ops, \ | ||
| 47 | .type = REGULATOR_VOLTAGE, \ | ||
| 48 | .owner = THIS_MODULE, \ | ||
| 49 | }, \ | ||
| 50 | } | ||
| 51 | |||
| 52 | #define REG_FIXED(ids, voltage) \ | ||
| 53 | { \ | ||
| 54 | .min_uV = (voltage), \ | ||
| 55 | .max_uV = (voltage), \ | ||
| 56 | .desc = { \ | ||
| 57 | .name = #ids, \ | ||
| 58 | .id = MAX8907C_##ids, \ | ||
| 59 | .n_voltages = 1, \ | ||
| 60 | .ops = &max8907c_fixed_ops, \ | ||
| 61 | .type = REGULATOR_VOLTAGE, \ | ||
| 62 | .owner = THIS_MODULE, \ | ||
| 63 | }, \ | ||
| 64 | } | ||
| 65 | |||
| 66 | #define REG_OUT5V(ids, base, voltage) \ | ||
| 67 | { \ | ||
| 68 | .min_uV = (voltage), \ | ||
| 69 | .max_uV = (voltage), \ | ||
| 70 | .reg_base = (base), \ | ||
| 71 | .desc = { \ | ||
| 72 | .name = #ids, \ | ||
| 73 | .id = MAX8907C_##ids, \ | ||
| 74 | .n_voltages = 1, \ | ||
| 75 | .ops = &max8907c_out5v_ops, \ | ||
| 76 | .type = REGULATOR_VOLTAGE, \ | ||
| 77 | .owner = THIS_MODULE, \ | ||
| 78 | }, \ | ||
| 79 | } | ||
| 80 | |||
| 81 | #define REG_BBAT(ids, base, min, max, step) \ | ||
| 82 | { \ | ||
| 83 | .min_uV = (min), \ | ||
| 84 | .max_uV = (max), \ | ||
| 85 | .step_uV = (step), \ | ||
| 86 | .reg_base = (base), \ | ||
| 87 | .desc = { \ | ||
| 88 | .name = #ids, \ | ||
| 89 | .id = MAX8907C_##ids, \ | ||
| 90 | .n_voltages = ((max) - (min)) / (step) + 1, \ | ||
| 91 | .ops = &max8907c_bbat_ops, \ | ||
| 92 | .type = REGULATOR_VOLTAGE, \ | ||
| 93 | .owner = THIS_MODULE, \ | ||
| 94 | }, \ | ||
| 95 | } | ||
| 96 | |||
| 97 | #define REG_WLED(ids, base, voltage) \ | ||
| 98 | { \ | ||
| 99 | .min_uV = (voltage), \ | ||
| 100 | .max_uV = (voltage), \ | ||
| 101 | .reg_base = (base), \ | ||
| 102 | .desc = { \ | ||
| 103 | .name = #ids, \ | ||
| 104 | .id = MAX8907C_##ids, \ | ||
| 105 | .n_voltages = 1, \ | ||
| 106 | .ops = &max8907c_wled_ops, \ | ||
| 107 | .type = REGULATOR_CURRENT, \ | ||
| 108 | .owner = THIS_MODULE, \ | ||
| 109 | }, \ | ||
| 110 | } | ||
| 111 | |||
| 112 | #define LDO_750_50(id, base) REG_LDO(id, (base), 750000, 3900000, 50000) | ||
| 113 | #define LDO_650_25(id, base) REG_LDO(id, (base), 650000, 2225000, 25000) | ||
| 114 | |||
| 115 | static int max8907c_regulator_list_voltage(struct regulator_dev *dev, | ||
| 116 | unsigned index); | ||
| 117 | static int max8907c_regulator_ldo_set_voltage(struct regulator_dev *dev, | ||
| 118 | int min_uV, int max_uV); | ||
| 119 | static int max8907c_regulator_bbat_set_voltage(struct regulator_dev *dev, | ||
| 120 | int min_uV, int max_uV); | ||
| 121 | static int max8907c_regulator_ldo_get_voltage(struct regulator_dev *dev); | ||
| 122 | static int max8907c_regulator_fixed_get_voltage(struct regulator_dev *dev); | ||
| 123 | static int max8907c_regulator_bbat_get_voltage(struct regulator_dev *dev); | ||
| 124 | static int max8907c_regulator_wled_set_current_limit(struct regulator_dev *dev, | ||
| 125 | int min_uA, int max_uA); | ||
| 126 | static int max8907c_regulator_wled_get_current_limit(struct regulator_dev *dev); | ||
| 127 | static int max8907c_regulator_ldo_enable(struct regulator_dev *dev); | ||
| 128 | static int max8907c_regulator_out5v_enable(struct regulator_dev *dev); | ||
| 129 | static int max8907c_regulator_ldo_disable(struct regulator_dev *dev); | ||
| 130 | static int max8907c_regulator_out5v_disable(struct regulator_dev *dev); | ||
| 131 | static int max8907c_regulator_ldo_is_enabled(struct regulator_dev *dev); | ||
| 132 | static int max8907c_regulator_out5v_is_enabled(struct regulator_dev *dev); | ||
| 133 | |||
| 134 | static struct regulator_ops max8907c_ldo_ops = { | ||
| 135 | .list_voltage = max8907c_regulator_list_voltage, | ||
| 136 | .set_voltage = max8907c_regulator_ldo_set_voltage, | ||
| 137 | .get_voltage = max8907c_regulator_ldo_get_voltage, | ||
| 138 | .enable = max8907c_regulator_ldo_enable, | ||
| 139 | .disable = max8907c_regulator_ldo_disable, | ||
| 140 | .is_enabled = max8907c_regulator_ldo_is_enabled, | ||
| 141 | }; | ||
| 142 | |||
| 143 | static struct regulator_ops max8907c_fixed_ops = { | ||
| 144 | .list_voltage = max8907c_regulator_list_voltage, | ||
| 145 | .get_voltage = max8907c_regulator_fixed_get_voltage, | ||
| 146 | }; | ||
| 147 | |||
| 148 | static struct regulator_ops max8907c_out5v_ops = { | ||
| 149 | .list_voltage = max8907c_regulator_list_voltage, | ||
| 150 | .get_voltage = max8907c_regulator_fixed_get_voltage, | ||
| 151 | .enable = max8907c_regulator_out5v_enable, | ||
| 152 | .disable = max8907c_regulator_out5v_disable, | ||
| 153 | .is_enabled = max8907c_regulator_out5v_is_enabled, | ||
| 154 | }; | ||
| 155 | |||
| 156 | static struct regulator_ops max8907c_bbat_ops = { | ||
| 157 | .list_voltage = max8907c_regulator_list_voltage, | ||
| 158 | .set_voltage = max8907c_regulator_bbat_set_voltage, | ||
| 159 | .get_voltage = max8907c_regulator_bbat_get_voltage, | ||
| 160 | }; | ||
| 161 | |||
| 162 | static struct regulator_ops max8907c_wled_ops = { | ||
| 163 | .list_voltage = max8907c_regulator_list_voltage, | ||
| 164 | .set_current_limit = max8907c_regulator_wled_set_current_limit, | ||
| 165 | .get_current_limit = max8907c_regulator_wled_get_current_limit, | ||
| 166 | .get_voltage = max8907c_regulator_fixed_get_voltage, | ||
| 167 | }; | ||
| 168 | |||
| 169 | static struct max8907c_regulator_info max8907c_regulators[] = { | ||
| 170 | REG_LDO(SD1, MAX8907C_REG_SDCTL1, 650000, 2225000, 25000), | ||
| 171 | REG_LDO(SD2, MAX8907C_REG_SDCTL2, 637500, 1425000, 12500), | ||
| 172 | REG_LDO(SD3, MAX8907C_REG_SDCTL3, 750000, 3900000, 50000), | ||
| 173 | LDO_750_50(LDO1, MAX8907C_REG_LDOCTL1), | ||
| 174 | LDO_650_25(LDO2, MAX8907C_REG_LDOCTL2), | ||
| 175 | LDO_650_25(LDO3, MAX8907C_REG_LDOCTL3), | ||
| 176 | LDO_750_50(LDO4, MAX8907C_REG_LDOCTL4), | ||
| 177 | LDO_750_50(LDO5, MAX8907C_REG_LDOCTL5), | ||
| 178 | LDO_750_50(LDO6, MAX8907C_REG_LDOCTL6), | ||
| 179 | LDO_750_50(LDO7, MAX8907C_REG_LDOCTL7), | ||
| 180 | LDO_750_50(LDO8, MAX8907C_REG_LDOCTL8), | ||
| 181 | LDO_750_50(LDO9, MAX8907C_REG_LDOCTL9), | ||
| 182 | LDO_750_50(LDO10, MAX8907C_REG_LDOCTL10), | ||
| 183 | LDO_750_50(LDO11, MAX8907C_REG_LDOCTL11), | ||
| 184 | LDO_750_50(LDO12, MAX8907C_REG_LDOCTL12), | ||
| 185 | LDO_750_50(LDO13, MAX8907C_REG_LDOCTL13), | ||
| 186 | LDO_750_50(LDO14, MAX8907C_REG_LDOCTL14), | ||
| 187 | LDO_750_50(LDO15, MAX8907C_REG_LDOCTL15), | ||
| 188 | LDO_750_50(LDO16, MAX8907C_REG_LDOCTL16), | ||
| 189 | LDO_650_25(LDO17, MAX8907C_REG_LDOCTL17), | ||
| 190 | LDO_650_25(LDO18, MAX8907C_REG_LDOCTL18), | ||
| 191 | LDO_750_50(LDO19, MAX8907C_REG_LDOCTL19), | ||
| 192 | LDO_750_50(LDO20, MAX8907C_REG_LDOCTL20), | ||
| 193 | REG_OUT5V(OUT5V, MAX8907C_REG_OUT5VEN, 5000000), | ||
| 194 | REG_OUT5V(OUT33V, MAX8907C_REG_OUT33VEN, 3300000), | ||
| 195 | REG_BBAT(BBAT, MAX8907C_REG_BBAT_CNFG, 2400000, 3000000, 200000), | ||
| 196 | REG_FIXED(SDBY, 1200000), | ||
| 197 | REG_FIXED(VRTC, 3300000), | ||
| 198 | REG_WLED(WLED, MAX8907C_REG_ILED_CNTL, 0), | ||
| 199 | }; | ||
| 200 | |||
| 201 | static int max8907c_regulator_list_voltage(struct regulator_dev *rdev, | ||
| 202 | unsigned index) | ||
| 203 | { | ||
| 204 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 205 | |||
| 206 | return info->min_uV + info->step_uV * index; | ||
| 207 | } | ||
| 208 | |||
| 209 | static int max8907c_regulator_ldo_set_voltage(struct regulator_dev *rdev, | ||
| 210 | int min_uV, int max_uV) | ||
| 211 | { | ||
| 212 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 213 | int val; | ||
| 214 | |||
| 215 | if (min_uV < info->min_uV || max_uV > info->max_uV) | ||
| 216 | return -EDOM; | ||
| 217 | |||
| 218 | val = (min_uV - info->min_uV) / info->step_uV; | ||
| 219 | |||
| 220 | return max8907c_reg_write(info->i2c, info->reg_base + MAX8907C_VOUT, val); | ||
| 221 | } | ||
| 222 | |||
| 223 | static int max8907c_regulator_bbat_set_voltage(struct regulator_dev *rdev, | ||
| 224 | int min_uV, int max_uV) | ||
| 225 | { | ||
| 226 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 227 | int val; | ||
| 228 | |||
| 229 | if (min_uV < info->min_uV || max_uV > info->max_uV) | ||
| 230 | return -EDOM; | ||
| 231 | |||
| 232 | val = (min_uV - info->min_uV) / info->step_uV; | ||
| 233 | |||
| 234 | return max8907c_set_bits(info->i2c, info->reg_base, MAX8907C_MASK_VBBATTCV, | ||
| 235 | val); | ||
| 236 | } | ||
| 237 | |||
| 238 | static int max8907c_regulator_ldo_get_voltage(struct regulator_dev *rdev) | ||
| 239 | { | ||
| 240 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 241 | int val; | ||
| 242 | |||
| 243 | val = max8907c_reg_read(info->i2c, info->reg_base + MAX8907C_VOUT); | ||
| 244 | return val * info->step_uV + info->min_uV; | ||
| 245 | } | ||
| 246 | |||
| 247 | static int max8907c_regulator_fixed_get_voltage(struct regulator_dev *rdev) | ||
| 248 | { | ||
| 249 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 250 | |||
| 251 | return info->min_uV; | ||
| 252 | } | ||
| 253 | |||
| 254 | static int max8907c_regulator_bbat_get_voltage(struct regulator_dev *rdev) | ||
| 255 | { | ||
| 256 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 257 | int val; | ||
| 258 | |||
| 259 | val = | ||
| 260 | max8907c_reg_read(info->i2c, info->reg_base) & MAX8907C_MASK_VBBATTCV; | ||
| 261 | return val * info->step_uV + info->min_uV; | ||
| 262 | } | ||
| 263 | |||
| 264 | static int max8907c_regulator_wled_set_current_limit(struct regulator_dev *rdev, | ||
| 265 | int min_uA, int max_uA) | ||
| 266 | { | ||
| 267 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 268 | |||
| 269 | if (min_uA > 25500) | ||
| 270 | return -EDOM; | ||
| 271 | |||
| 272 | return max8907c_reg_write(info->i2c, info->reg_base, min_uA / 100); | ||
| 273 | } | ||
| 274 | |||
| 275 | static int max8907c_regulator_wled_get_current_limit(struct regulator_dev *rdev) | ||
| 276 | { | ||
| 277 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 278 | int val; | ||
| 279 | |||
| 280 | val = max8907c_reg_read(info->i2c, info->reg_base); | ||
| 281 | return val * 100; | ||
| 282 | } | ||
| 283 | |||
| 284 | static int max8907c_regulator_ldo_enable(struct regulator_dev *rdev) | ||
| 285 | { | ||
| 286 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 287 | |||
| 288 | return max8907c_set_bits(info->i2c, info->reg_base + MAX8907C_CTL, | ||
| 289 | MAX8907C_MASK_LDO_EN | MAX8907C_MASK_LDO_SEQ, | ||
| 290 | MAX8907C_MASK_LDO_EN | MAX8907C_MASK_LDO_SEQ); | ||
| 291 | } | ||
| 292 | |||
| 293 | static int max8907c_regulator_out5v_enable(struct regulator_dev *rdev) | ||
| 294 | { | ||
| 295 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 296 | |||
| 297 | return max8907c_set_bits(info->i2c, info->reg_base, | ||
| 298 | MAX8907C_MASK_OUT5V_VINEN | | ||
| 299 | MAX8907C_MASK_OUT5V_ENSRC | | ||
| 300 | MAX8907C_MASK_OUT5V_EN, | ||
| 301 | MAX8907C_MASK_OUT5V_ENSRC | | ||
| 302 | MAX8907C_MASK_OUT5V_EN); | ||
| 303 | } | ||
| 304 | |||
| 305 | static int max8907c_regulator_ldo_disable(struct regulator_dev *rdev) | ||
| 306 | { | ||
| 307 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 308 | |||
| 309 | return max8907c_set_bits(info->i2c, info->reg_base + MAX8907C_CTL, | ||
| 310 | MAX8907C_MASK_LDO_EN | MAX8907C_MASK_LDO_SEQ, | ||
| 311 | MAX8907C_MASK_LDO_SEQ); | ||
| 312 | } | ||
| 313 | |||
| 314 | static int max8907c_regulator_out5v_disable(struct regulator_dev *rdev) | ||
| 315 | { | ||
| 316 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 317 | |||
| 318 | return max8907c_set_bits(info->i2c, info->reg_base, | ||
| 319 | MAX8907C_MASK_OUT5V_VINEN | | ||
| 320 | MAX8907C_MASK_OUT5V_ENSRC | | ||
| 321 | MAX8907C_MASK_OUT5V_EN, | ||
| 322 | MAX8907C_MASK_OUT5V_ENSRC); | ||
| 323 | } | ||
| 324 | |||
| 325 | static int max8907c_regulator_ldo_is_enabled(struct regulator_dev *rdev) | ||
| 326 | { | ||
| 327 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 328 | int val; | ||
| 329 | |||
| 330 | val = max8907c_reg_read(info->i2c, info->reg_base + MAX8907C_CTL); | ||
| 331 | if (val < 0) | ||
| 332 | return -EDOM; | ||
| 333 | |||
| 334 | return (val & MAX8907C_MASK_LDO_EN) || !(val & MAX8907C_MASK_LDO_SEQ); | ||
| 335 | } | ||
| 336 | |||
| 337 | static int max8907c_regulator_out5v_is_enabled(struct regulator_dev *rdev) | ||
| 338 | { | ||
| 339 | const struct max8907c_regulator_info *info = rdev_get_drvdata(rdev); | ||
| 340 | int val; | ||
| 341 | |||
| 342 | val = max8907c_reg_read(info->i2c, info->reg_base); | ||
| 343 | if (val < 0) | ||
| 344 | return -EDOM; | ||
| 345 | |||
| 346 | if ((val & | ||
| 347 | (MAX8907C_MASK_OUT5V_VINEN | MAX8907C_MASK_OUT5V_ENSRC | | ||
| 348 | MAX8907C_MASK_OUT5V_EN)) | ||
| 349 | == MAX8907C_MASK_OUT5V_ENSRC) | ||
| 350 | return 1; | ||
| 351 | |||
| 352 | return 0; | ||
| 353 | } | ||
| 354 | |||
| 355 | static int max8907c_regulator_probe(struct platform_device *pdev) | ||
| 356 | { | ||
| 357 | struct max8907c *max8907c = dev_get_drvdata(pdev->dev.parent); | ||
| 358 | struct max8907c_regulator_info *info; | ||
| 359 | struct regulator_dev *rdev; | ||
| 360 | u8 version; | ||
| 361 | |||
| 362 | /* Backwards compatibility with max8907b, SD1 uses different voltages */ | ||
| 363 | version = max8907c_reg_read(max8907c->i2c_power, MAX8907C_REG_II2RR); | ||
| 364 | if ((version & MAX8907C_II2RR_VERSION_MASK) == MAX8907C_II2RR_VERSION_REV_B) { | ||
| 365 | max8907c_regulators[MAX8907C_SD1].min_uV = 637500; | ||
| 366 | max8907c_regulators[MAX8907C_SD1].max_uV = 1425000; | ||
| 367 | max8907c_regulators[MAX8907C_SD1].step_uV = 12500; | ||
| 368 | } | ||
| 369 | |||
| 370 | info = &max8907c_regulators[pdev->id]; | ||
| 371 | info->i2c = max8907c->i2c_power; | ||
| 372 | |||
| 373 | rdev = regulator_register(&info->desc, | ||
| 374 | &pdev->dev, pdev->dev.platform_data, info); | ||
| 375 | if (IS_ERR(rdev)) { | ||
| 376 | dev_err(&pdev->dev, "Cannot register regulator \"%s\", %ld\n", | ||
| 377 | info->desc.name, PTR_ERR(rdev)); | ||
| 378 | goto error; | ||
| 379 | } | ||
| 380 | |||
| 381 | platform_set_drvdata(pdev, rdev); | ||
| 382 | return 0; | ||
| 383 | |||
| 384 | error: | ||
| 385 | return PTR_ERR(rdev); | ||
| 386 | } | ||
| 387 | |||
| 388 | static int max8907c_regulator_remove(struct platform_device *pdev) | ||
| 389 | { | ||
| 390 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | ||
| 391 | |||
| 392 | regulator_unregister(rdev); | ||
| 393 | return 0; | ||
| 394 | } | ||
| 395 | |||
| 396 | static struct platform_driver max8907c_regulator_driver = { | ||
| 397 | .driver = { | ||
| 398 | .name = "max8907c-regulator", | ||
| 399 | .owner = THIS_MODULE, | ||
| 400 | }, | ||
| 401 | .probe = max8907c_regulator_probe, | ||
| 402 | .remove = __devexit_p(max8907c_regulator_remove), | ||
| 403 | }; | ||
| 404 | |||
| 405 | static int __init max8907c_regulator_init(void) | ||
| 406 | { | ||
| 407 | return platform_driver_register(&max8907c_regulator_driver); | ||
| 408 | } | ||
| 409 | |||
| 410 | subsys_initcall(max8907c_regulator_init); | ||
| 411 | |||
| 412 | static void __exit max8907c_reg_exit(void) | ||
| 413 | { | ||
| 414 | platform_driver_unregister(&max8907c_regulator_driver); | ||
| 415 | } | ||
| 416 | |||
| 417 | module_exit(max8907c_reg_exit); | ||
| 418 | |||
| 419 | MODULE_DESCRIPTION("MAX8907C regulator driver"); | ||
| 420 | MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>"); | ||
| 421 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/regulator/ricoh583-regulator.c b/drivers/regulator/ricoh583-regulator.c new file mode 100644 index 00000000000..867ffe629ed --- /dev/null +++ b/drivers/regulator/ricoh583-regulator.c | |||
| @@ -0,0 +1,412 @@ | |||
| 1 | /* | ||
| 2 | * drivers/regulator/ricoh583-regulator.c | ||
| 3 | * | ||
| 4 | * Regulator driver for RICOH583 power management chip. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2011 NVIDIA Corporation | ||
| 7 | * | ||
| 8 | * Copyright (C) 2011 RICOH COMPANY,LTD | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 18 | * more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License along | ||
| 21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 23 | * | ||
| 24 | */ | ||
| 25 | |||
| 26 | /*#define DEBUG 1*/ | ||
| 27 | /*#define VERBOSE_DEBUG 1*/ | ||
| 28 | #include <linux/module.h> | ||
| 29 | #include <linux/delay.h> | ||
| 30 | #include <linux/init.h> | ||
| 31 | #include <linux/slab.h> | ||
| 32 | #include <linux/err.h> | ||
| 33 | #include <linux/platform_device.h> | ||
| 34 | #include <linux/regulator/driver.h> | ||
| 35 | #include <linux/regulator/machine.h> | ||
| 36 | #include <linux/mfd/ricoh583.h> | ||
| 37 | #include <linux/regulator/ricoh583-regulator.h> | ||
| 38 | |||
| 39 | struct ricoh583_regulator { | ||
| 40 | int id; | ||
| 41 | int deepsleep_id; | ||
| 42 | /* Regulator register address.*/ | ||
| 43 | u8 reg_en_reg; | ||
| 44 | u8 en_bit; | ||
| 45 | u8 reg_disc_reg; | ||
| 46 | u8 disc_bit; | ||
| 47 | u8 vout_reg; | ||
| 48 | u8 vout_mask; | ||
| 49 | u8 vout_reg_cache; | ||
| 50 | u8 deepsleep_reg; | ||
| 51 | |||
| 52 | /* chip constraints on regulator behavior */ | ||
| 53 | int min_uV; | ||
| 54 | int max_uV; | ||
| 55 | int step_uV; | ||
| 56 | int nsteps; | ||
| 57 | |||
| 58 | /* regulator specific turn-on delay */ | ||
| 59 | u16 delay; | ||
| 60 | |||
| 61 | /* used by regulator core */ | ||
| 62 | struct regulator_desc desc; | ||
| 63 | |||
| 64 | /* Device */ | ||
| 65 | struct device *dev; | ||
| 66 | }; | ||
| 67 | |||
| 68 | |||
| 69 | static inline struct device *to_ricoh583_dev(struct regulator_dev *rdev) | ||
| 70 | { | ||
| 71 | return rdev_get_dev(rdev)->parent->parent; | ||
| 72 | } | ||
| 73 | |||
| 74 | static int ricoh583_regulator_enable_time(struct regulator_dev *rdev) | ||
| 75 | { | ||
| 76 | struct ricoh583_regulator *ri = rdev_get_drvdata(rdev); | ||
| 77 | |||
| 78 | return ri->delay; | ||
| 79 | } | ||
| 80 | |||
| 81 | static int ricoh583_reg_is_enabled(struct regulator_dev *rdev) | ||
| 82 | { | ||
| 83 | struct ricoh583_regulator *ri = rdev_get_drvdata(rdev); | ||
| 84 | struct device *parent = to_ricoh583_dev(rdev); | ||
| 85 | uint8_t control; | ||
| 86 | int ret; | ||
| 87 | |||
| 88 | ret = ricoh583_read(parent, ri->reg_en_reg, &control); | ||
| 89 | if (ret < 0) { | ||
| 90 | dev_err(&rdev->dev, "Error in reading the control register\n"); | ||
| 91 | return ret; | ||
| 92 | } | ||
| 93 | return (((control >> ri->en_bit) & 1) == 1); | ||
| 94 | } | ||
| 95 | |||
| 96 | static int ricoh583_reg_enable(struct regulator_dev *rdev) | ||
| 97 | { | ||
| 98 | struct ricoh583_regulator *ri = rdev_get_drvdata(rdev); | ||
| 99 | struct device *parent = to_ricoh583_dev(rdev); | ||
| 100 | int ret; | ||
| 101 | |||
| 102 | ret = ricoh583_set_bits(parent, ri->reg_en_reg, (1 << ri->en_bit)); | ||
| 103 | if (ret < 0) { | ||
| 104 | dev_err(&rdev->dev, "Error in updating the STATE register\n"); | ||
| 105 | return ret; | ||
| 106 | } | ||
| 107 | udelay(ri->delay); | ||
| 108 | return ret; | ||
| 109 | } | ||
| 110 | |||
| 111 | static int ricoh583_reg_disable(struct regulator_dev *rdev) | ||
| 112 | { | ||
| 113 | struct ricoh583_regulator *ri = rdev_get_drvdata(rdev); | ||
| 114 | struct device *parent = to_ricoh583_dev(rdev); | ||
| 115 | int ret; | ||
| 116 | |||
| 117 | ret = ricoh583_clr_bits(parent, ri->reg_en_reg, (1 << ri->en_bit)); | ||
| 118 | if (ret < 0) | ||
| 119 | dev_err(&rdev->dev, "Error in updating the STATE register\n"); | ||
| 120 | |||
| 121 | return ret; | ||
| 122 | } | ||
| 123 | |||
| 124 | static int ricoh583_list_voltage(struct regulator_dev *rdev, unsigned index) | ||
| 125 | { | ||
| 126 | struct ricoh583_regulator *ri = rdev_get_drvdata(rdev); | ||
| 127 | |||
| 128 | return ri->min_uV + (ri->step_uV * index); | ||
| 129 | } | ||
| 130 | |||
| 131 | static int __ricoh583_set_ds_voltage(struct device *parent, | ||
| 132 | struct ricoh583_regulator *ri, int min_uV, int max_uV) | ||
| 133 | { | ||
| 134 | int vsel; | ||
| 135 | int ret; | ||
| 136 | |||
| 137 | if ((min_uV < ri->min_uV) || (max_uV > ri->max_uV)) | ||
| 138 | return -EDOM; | ||
| 139 | |||
| 140 | vsel = (min_uV - ri->min_uV + ri->step_uV - 1)/ri->step_uV; | ||
| 141 | if (vsel > ri->nsteps) | ||
| 142 | return -EDOM; | ||
| 143 | |||
| 144 | ret = ricoh583_update(parent, ri->deepsleep_reg, vsel, ri->vout_mask); | ||
| 145 | if (ret < 0) | ||
| 146 | dev_err(ri->dev, "Error in writing the deepsleep register\n"); | ||
| 147 | return ret; | ||
| 148 | } | ||
| 149 | |||
| 150 | static int __ricoh583_set_voltage(struct device *parent, | ||
| 151 | struct ricoh583_regulator *ri, int min_uV, int max_uV, | ||
| 152 | unsigned *selector) | ||
| 153 | { | ||
| 154 | int vsel; | ||
| 155 | int ret; | ||
| 156 | uint8_t vout_val; | ||
| 157 | |||
| 158 | if ((min_uV < ri->min_uV) || (max_uV > ri->max_uV)) | ||
| 159 | return -EDOM; | ||
| 160 | |||
| 161 | vsel = (min_uV - ri->min_uV + ri->step_uV - 1)/ri->step_uV; | ||
| 162 | if (vsel > ri->nsteps) | ||
| 163 | return -EDOM; | ||
| 164 | |||
| 165 | if (selector) | ||
| 166 | *selector = vsel; | ||
| 167 | |||
| 168 | vout_val = (ri->vout_reg_cache & ~ri->vout_mask) | | ||
| 169 | (vsel & ri->vout_mask); | ||
| 170 | ret = ricoh583_write(parent, ri->vout_reg, vout_val); | ||
| 171 | if (ret < 0) | ||
| 172 | dev_err(ri->dev, "Error in writing the Voltage register\n"); | ||
| 173 | else | ||
| 174 | ri->vout_reg_cache = vout_val; | ||
| 175 | |||
| 176 | return ret; | ||
| 177 | } | ||
| 178 | |||
| 179 | static int ricoh583_set_voltage(struct regulator_dev *rdev, | ||
| 180 | int min_uV, int max_uV, unsigned *selector) | ||
| 181 | { | ||
| 182 | struct ricoh583_regulator *ri = rdev_get_drvdata(rdev); | ||
| 183 | struct device *parent = to_ricoh583_dev(rdev); | ||
| 184 | |||
| 185 | return __ricoh583_set_voltage(parent, ri, min_uV, max_uV, selector); | ||
| 186 | } | ||
| 187 | |||
| 188 | static int ricoh583_get_voltage(struct regulator_dev *rdev) | ||
| 189 | { | ||
| 190 | struct ricoh583_regulator *ri = rdev_get_drvdata(rdev); | ||
| 191 | uint8_t vsel; | ||
| 192 | |||
| 193 | vsel = ri->vout_reg_cache & ri->vout_mask; | ||
| 194 | return ri->min_uV + vsel * ri->step_uV; | ||
| 195 | } | ||
| 196 | |||
| 197 | static struct regulator_ops ricoh583_ops = { | ||
| 198 | .list_voltage = ricoh583_list_voltage, | ||
| 199 | .set_voltage = ricoh583_set_voltage, | ||
| 200 | .get_voltage = ricoh583_get_voltage, | ||
| 201 | .enable = ricoh583_reg_enable, | ||
| 202 | .disable = ricoh583_reg_disable, | ||
| 203 | .is_enabled = ricoh583_reg_is_enabled, | ||
| 204 | .enable_time = ricoh583_regulator_enable_time, | ||
| 205 | }; | ||
| 206 | |||
| 207 | #define RICOH583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, _vout_reg, \ | ||
| 208 | _vout_mask, _ds_reg, _min_mv, _max_mv, _step_uV, _nsteps, \ | ||
| 209 | _ops, _delay) \ | ||
| 210 | { \ | ||
| 211 | .reg_en_reg = _en_reg, \ | ||
| 212 | .en_bit = _en_bit, \ | ||
| 213 | .reg_disc_reg = _disc_reg, \ | ||
| 214 | .disc_bit = _disc_bit, \ | ||
| 215 | .vout_reg = _vout_reg, \ | ||
| 216 | .vout_mask = _vout_mask, \ | ||
| 217 | .deepsleep_reg = _ds_reg, \ | ||
| 218 | .min_uV = _min_mv * 1000, \ | ||
| 219 | .max_uV = _max_mv * 1000, \ | ||
| 220 | .step_uV = _step_uV, \ | ||
| 221 | .nsteps = _nsteps, \ | ||
| 222 | .delay = _delay, \ | ||
| 223 | .id = RICOH583_ID_##_id, \ | ||
| 224 | .deepsleep_id = RICOH583_DS_##_id, \ | ||
| 225 | .desc = { \ | ||
| 226 | .name = ricoh583_rails(_id), \ | ||
| 227 | .id = RICOH583_ID_##_id, \ | ||
| 228 | .n_voltages = _nsteps, \ | ||
| 229 | .ops = &_ops, \ | ||
| 230 | .type = REGULATOR_VOLTAGE, \ | ||
| 231 | .owner = THIS_MODULE, \ | ||
| 232 | }, \ | ||
| 233 | } | ||
| 234 | |||
| 235 | static struct ricoh583_regulator ricoh583_regulator[] = { | ||
| 236 | RICOH583_REG(DC0, 0x30, 0, 0x30, 1, 0x31, 0x7F, 0x60, | ||
| 237 | 700, 1500, 12500, 0x41, ricoh583_ops, 500), | ||
| 238 | RICOH583_REG(DC1, 0x34, 0, 0x34, 1, 0x35, 0x7F, 0x61, | ||
| 239 | 700, 1500, 12500, 0x41, ricoh583_ops, 500), | ||
| 240 | RICOH583_REG(DC2, 0x38, 0, 0x38, 1, 0x39, 0x7F, 0x62, | ||
| 241 | 900, 2400, 12500, 0x79, ricoh583_ops, 500), | ||
| 242 | RICOH583_REG(DC3, 0x3C, 0, 0x3C, 1, 0x3D, 0x7F, 0x63, | ||
| 243 | 900, 2400, 12500, 0x79, ricoh583_ops, 500), | ||
| 244 | RICOH583_REG(LDO0, 0x51, 0, 0x53, 0, 0x54, 0x7F, 0x64, | ||
| 245 | 900, 3400, 25000, 0x65, ricoh583_ops, 500), | ||
| 246 | RICOH583_REG(LDO1, 0x51, 1, 0x53, 1, 0x55, 0x7F, 0x65, | ||
| 247 | 900, 3400, 25000, 0x65, ricoh583_ops, 500), | ||
| 248 | RICOH583_REG(LDO2, 0x51, 2, 0x53, 2, 0x56, 0x7F, 0x66, | ||
| 249 | 900, 3400, 25000, 0x65, ricoh583_ops, 500), | ||
| 250 | RICOH583_REG(LDO3, 0x51, 3, 0x53, 3, 0x57, 0x7F, 0x67, | ||
| 251 | 900, 3400, 25000, 0x65, ricoh583_ops, 500), | ||
| 252 | RICOH583_REG(LDO4, 0x51, 4, 0x53, 4, 0x58, 0x3F, 0x68, | ||
| 253 | 750, 1500, 12500, 0x3D, ricoh583_ops, 500), | ||
| 254 | RICOH583_REG(LDO5, 0x51, 5, 0x53, 5, 0x59, 0x7F, 0x69, | ||
| 255 | 900, 3400, 25000, 0x65, ricoh583_ops, 500), | ||
| 256 | RICOH583_REG(LDO6, 0x51, 6, 0x53, 6, 0x5A, 0x7F, 0x6A, | ||
| 257 | 900, 3400, 25000, 0x65, ricoh583_ops, 500), | ||
| 258 | RICOH583_REG(LDO7, 0x51, 7, 0x53, 7, 0x5B, 0x7F, 0x6B, | ||
| 259 | 900, 3400, 25000, 0x65, ricoh583_ops, 500), | ||
| 260 | RICOH583_REG(LDO8, 0x50, 0, 0x52, 0, 0x5C, 0x7F, 0x6C, | ||
| 261 | 900, 3400, 25000, 0x65, ricoh583_ops, 500), | ||
| 262 | RICOH583_REG(LDO9, 0x50, 1, 0x52, 1, 0x5D, 0x7F, 0x6D, | ||
| 263 | 900, 3400, 25000, 0x65, ricoh583_ops, 500), | ||
| 264 | }; | ||
| 265 | static inline struct ricoh583_regulator *find_regulator_info(int id) | ||
| 266 | { | ||
| 267 | struct ricoh583_regulator *ri; | ||
| 268 | int i; | ||
| 269 | |||
| 270 | for (i = 0; i < ARRAY_SIZE(ricoh583_regulator); i++) { | ||
| 271 | ri = &ricoh583_regulator[i]; | ||
| 272 | if (ri->desc.id == id) | ||
| 273 | return ri; | ||
| 274 | } | ||
| 275 | return NULL; | ||
| 276 | } | ||
| 277 | |||
| 278 | static int ricoh583_regulator_preinit(struct device *parent, | ||
| 279 | struct ricoh583_regulator *ri, | ||
| 280 | struct ricoh583_regulator_platform_data *ricoh583_pdata) | ||
| 281 | { | ||
| 282 | int ret = 0; | ||
| 283 | |||
| 284 | if (ri->deepsleep_id != RICOH583_DS_NONE) { | ||
| 285 | ret = ricoh583_ext_power_req_config(parent, ri->deepsleep_id, | ||
| 286 | ricoh583_pdata->ext_pwr_req, | ||
| 287 | ricoh583_pdata->deepsleep_slots); | ||
| 288 | if (ret < 0) | ||
| 289 | return ret; | ||
| 290 | } | ||
| 291 | |||
| 292 | if (!ricoh583_pdata->init_apply) | ||
| 293 | return 0; | ||
| 294 | |||
| 295 | if (ricoh583_pdata->deepsleep_uV) { | ||
| 296 | ret = __ricoh583_set_ds_voltage(parent, ri, | ||
| 297 | ricoh583_pdata->deepsleep_uV, | ||
| 298 | ricoh583_pdata->deepsleep_uV); | ||
| 299 | if (ret < 0) { | ||
| 300 | dev_err(ri->dev, "Not able to initialize ds voltage %d" | ||
| 301 | " for rail %d err %d\n", | ||
| 302 | ricoh583_pdata->deepsleep_uV, ri->desc.id, ret); | ||
| 303 | return ret; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | if (ricoh583_pdata->init_uV >= 0) { | ||
| 308 | ret = __ricoh583_set_voltage(parent, ri, | ||
| 309 | ricoh583_pdata->init_uV, | ||
| 310 | ricoh583_pdata->init_uV, 0); | ||
| 311 | if (ret < 0) { | ||
| 312 | dev_err(ri->dev, "Not able to initialize voltage %d " | ||
| 313 | "for rail %d err %d\n", ricoh583_pdata->init_uV, | ||
| 314 | ri->desc.id, ret); | ||
| 315 | return ret; | ||
| 316 | } | ||
| 317 | } | ||
| 318 | |||
| 319 | if (ricoh583_pdata->init_enable) | ||
| 320 | ret = ricoh583_set_bits(parent, ri->reg_en_reg, | ||
| 321 | (1 << ri->en_bit)); | ||
| 322 | else | ||
| 323 | ret = ricoh583_clr_bits(parent, ri->reg_en_reg, | ||
| 324 | (1 << ri->en_bit)); | ||
| 325 | if (ret < 0) | ||
| 326 | dev_err(ri->dev, "Not able to %s rail %d err %d\n", | ||
| 327 | (ricoh583_pdata->init_enable) ? "enable" : "disable", | ||
| 328 | ri->desc.id, ret); | ||
| 329 | |||
| 330 | return ret; | ||
| 331 | } | ||
| 332 | |||
| 333 | static inline int ricoh583_cache_regulator_register(struct device *parent, | ||
| 334 | struct ricoh583_regulator *ri) | ||
| 335 | { | ||
| 336 | ri->vout_reg_cache = 0; | ||
| 337 | return ricoh583_read(parent, ri->vout_reg, &ri->vout_reg_cache); | ||
| 338 | } | ||
| 339 | |||
| 340 | static int __devinit ricoh583_regulator_probe(struct platform_device *pdev) | ||
| 341 | { | ||
| 342 | struct ricoh583_regulator *ri = NULL; | ||
| 343 | struct regulator_dev *rdev; | ||
| 344 | struct ricoh583_regulator_platform_data *tps_pdata; | ||
| 345 | int id = pdev->id; | ||
| 346 | int err; | ||
| 347 | |||
| 348 | dev_dbg(&pdev->dev, "Probing reulator %d\n", id); | ||
| 349 | |||
| 350 | ri = find_regulator_info(id); | ||
| 351 | if (ri == NULL) { | ||
| 352 | dev_err(&pdev->dev, "invalid regulator ID specified\n"); | ||
| 353 | return -EINVAL; | ||
| 354 | } | ||
| 355 | tps_pdata = pdev->dev.platform_data; | ||
| 356 | ri->dev = &pdev->dev; | ||
| 357 | |||
| 358 | err = ricoh583_cache_regulator_register(pdev->dev.parent, ri); | ||
| 359 | if (err) { | ||
| 360 | dev_err(&pdev->dev, "Fail in caching register\n"); | ||
| 361 | return err; | ||
| 362 | } | ||
| 363 | |||
| 364 | err = ricoh583_regulator_preinit(pdev->dev.parent, ri, tps_pdata); | ||
| 365 | if (err) { | ||
| 366 | dev_err(&pdev->dev, "Fail in pre-initialisation\n"); | ||
| 367 | return err; | ||
| 368 | } | ||
| 369 | rdev = regulator_register(&ri->desc, &pdev->dev, | ||
| 370 | &tps_pdata->regulator, ri); | ||
| 371 | if (IS_ERR_OR_NULL(rdev)) { | ||
| 372 | dev_err(&pdev->dev, "failed to register regulator %s\n", | ||
| 373 | ri->desc.name); | ||
| 374 | return PTR_ERR(rdev); | ||
| 375 | } | ||
| 376 | |||
| 377 | platform_set_drvdata(pdev, rdev); | ||
| 378 | return 0; | ||
| 379 | } | ||
| 380 | |||
| 381 | static int __devexit ricoh583_regulator_remove(struct platform_device *pdev) | ||
| 382 | { | ||
| 383 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | ||
| 384 | |||
| 385 | regulator_unregister(rdev); | ||
| 386 | return 0; | ||
| 387 | } | ||
| 388 | |||
| 389 | static struct platform_driver ricoh583_regulator_driver = { | ||
| 390 | .driver = { | ||
| 391 | .name = "ricoh583-regulator", | ||
| 392 | .owner = THIS_MODULE, | ||
| 393 | }, | ||
| 394 | .probe = ricoh583_regulator_probe, | ||
| 395 | .remove = __devexit_p(ricoh583_regulator_remove), | ||
| 396 | }; | ||
| 397 | |||
| 398 | static int __init ricoh583_regulator_init(void) | ||
| 399 | { | ||
| 400 | return platform_driver_register(&ricoh583_regulator_driver); | ||
| 401 | } | ||
| 402 | subsys_initcall(ricoh583_regulator_init); | ||
| 403 | |||
| 404 | static void __exit ricoh583_regulator_exit(void) | ||
| 405 | { | ||
| 406 | platform_driver_unregister(&ricoh583_regulator_driver); | ||
| 407 | } | ||
| 408 | module_exit(ricoh583_regulator_exit); | ||
| 409 | |||
| 410 | MODULE_DESCRIPTION("RICOH583 regulator driver"); | ||
| 411 | MODULE_ALIAS("platform:ricoh583-regulator"); | ||
| 412 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/regulator/tps6591x-regulator.c b/drivers/regulator/tps6591x-regulator.c new file mode 100644 index 00000000000..5336f3d8257 --- /dev/null +++ b/drivers/regulator/tps6591x-regulator.c | |||
| @@ -0,0 +1,955 @@ | |||
| 1 | /* | ||
| 2 | * driver/regulator/tps6591x-regulator.c | ||
| 3 | * | ||
| 4 | * Regulator driver for TI TPS6591x PMIC family | ||
| 5 | * | ||
| 6 | * Copyright (C) 2011 NVIDIA Corporation | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 16 | * more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License along | ||
| 19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/kernel.h> | ||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/err.h> | ||
| 28 | #include <linux/slab.h> | ||
| 29 | #include <linux/platform_device.h> | ||
| 30 | #include <linux/regulator/driver.h> | ||
| 31 | #include <linux/regulator/machine.h> | ||
| 32 | #include <linux/regulator/tps6591x-regulator.h> | ||
| 33 | #include <linux/mfd/tps6591x.h> | ||
| 34 | |||
| 35 | /* supply control and voltage setting */ | ||
| 36 | #define TPS6591X_VIO_ADD 0x20 | ||
| 37 | #define TPS6591X_VDD1_ADD 0x21 | ||
| 38 | #define TPS6591X_VDD1_OP_ADD 0x22 | ||
| 39 | #define TPS6591X_VDD1_SR_ADD 0x23 | ||
| 40 | #define TPS6591X_VDD2_ADD 0x24 | ||
| 41 | #define TPS6591X_VDD2_OP_ADD 0x25 | ||
| 42 | #define TPS6591X_VDD2_SR_ADD 0x26 | ||
| 43 | #define TPS6591X_VDDCTRL_ADD 0x27 | ||
| 44 | #define TPS6591X_VDDCTRL_OP_ADD 0x28 | ||
| 45 | #define TPS6591X_VDDCTRL_SR_ADD 0x29 | ||
| 46 | #define TPS6591X_LDO1_ADD 0x30 | ||
| 47 | #define TPS6591X_LDO2_ADD 0x31 | ||
| 48 | #define TPS6591X_LDO3_ADD 0x37 | ||
| 49 | #define TPS6591X_LDO4_ADD 0x36 | ||
| 50 | #define TPS6591X_LDO5_ADD 0x32 | ||
| 51 | #define TPS6591X_LDO6_ADD 0x35 | ||
| 52 | #define TPS6591X_LDO7_ADD 0x34 | ||
| 53 | #define TPS6591X_LDO8_ADD 0x33 | ||
| 54 | #define TPS6591X_SLEEP_SET_LDO_OFF_ADD 0x43 | ||
| 55 | #define TPS6591X_SLEEP_SET_RES_OFF_ADD 0x44 | ||
| 56 | #define TPS6591X_EN1_LDO_ADD 0x45 | ||
| 57 | #define TPS6591X_EN1_SMPS_ADD 0x46 | ||
| 58 | #define TPS6591X_EN2_LDO_ADD 0x47 | ||
| 59 | #define TPS6591X_EN2_SMPS_ADD 0x48 | ||
| 60 | #define TPS6591X_INVALID_ADD 0xFF | ||
| 61 | |||
| 62 | #define EN1_EN2_OFFSET 2 | ||
| 63 | |||
| 64 | struct tps6591x_register_info { | ||
| 65 | unsigned char addr; | ||
| 66 | unsigned char nbits; | ||
| 67 | unsigned char shift_bits; | ||
| 68 | uint8_t cache_val; | ||
| 69 | }; | ||
| 70 | |||
| 71 | enum { | ||
| 72 | supply_type_none = 0x0, | ||
| 73 | supply_type_single_reg, | ||
| 74 | supply_type_sr_op_reg | ||
| 75 | }; | ||
| 76 | |||
| 77 | struct tps6591x_regulator { | ||
| 78 | struct regulator_desc desc; | ||
| 79 | int supply_type; | ||
| 80 | |||
| 81 | struct tps6591x_register_info supply_reg; | ||
| 82 | struct tps6591x_register_info op_reg; | ||
| 83 | struct tps6591x_register_info sr_reg; | ||
| 84 | struct tps6591x_register_info en1_reg; | ||
| 85 | struct tps6591x_register_info slp_off_reg; | ||
| 86 | |||
| 87 | int *voltages; | ||
| 88 | |||
| 89 | int enable_delay; /* delay in us for regulator to stabilize */ | ||
| 90 | enum tps6591x_ext_control ectrl; | ||
| 91 | int current_volt_uv; | ||
| 92 | |||
| 93 | /* Time (micro sec) taken for 1uV change */ | ||
| 94 | int voltage_change_uv_per_us; | ||
| 95 | unsigned int config_flags; | ||
| 96 | }; | ||
| 97 | |||
| 98 | static inline struct device *to_tps6591x_dev(struct regulator_dev *rdev) | ||
| 99 | { | ||
| 100 | return rdev_get_dev(rdev)->parent->parent; | ||
| 101 | } | ||
| 102 | |||
| 103 | static int tps6591x_regulator_enable_time(struct regulator_dev *rdev) | ||
| 104 | { | ||
| 105 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 106 | |||
| 107 | return ri->enable_delay; | ||
| 108 | } | ||
| 109 | |||
| 110 | static int __tps6591x_ext_control_set(struct device *parent, | ||
| 111 | struct tps6591x_regulator *ri, | ||
| 112 | enum tps6591x_ext_control ectrl) | ||
| 113 | { | ||
| 114 | int ret; | ||
| 115 | uint8_t mask, reg_val, addr, offset; | ||
| 116 | struct tps6591x_register_info *ext_reg; | ||
| 117 | |||
| 118 | /* For regulator that has separate operational and sleep register make | ||
| 119 | sure that operational is used and clear sleep register to turn | ||
| 120 | regulator off when external control is inactive */ | ||
| 121 | if (ri->supply_type == supply_type_sr_op_reg) { | ||
| 122 | reg_val = ri->op_reg.cache_val; | ||
| 123 | if (reg_val & 0x80) { /* boot has used sr - switch to op */ | ||
| 124 | reg_val = ri->sr_reg.cache_val; | ||
| 125 | mask = ((1 << ri->sr_reg.nbits) - 1) | ||
| 126 | << ri->sr_reg.shift_bits; | ||
| 127 | reg_val &= mask; | ||
| 128 | ret = tps6591x_write(parent, ri->op_reg.addr, reg_val); | ||
| 129 | if (ret) | ||
| 130 | return ret; | ||
| 131 | ri->op_reg.cache_val = reg_val; | ||
| 132 | } | ||
| 133 | ret = tps6591x_write(parent, ri->sr_reg.addr, 0); | ||
| 134 | if (ret) | ||
| 135 | return ret; | ||
| 136 | ri->sr_reg.cache_val = 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | offset = 0; | ||
| 140 | switch (ectrl) { | ||
| 141 | case EXT_CTRL_EN2: | ||
| 142 | offset = EN1_EN2_OFFSET; | ||
| 143 | /* fall through to EXT_CTRL_EN1 */ | ||
| 144 | case EXT_CTRL_EN1: | ||
| 145 | ext_reg = &(ri->en1_reg); | ||
| 146 | break; | ||
| 147 | case EXT_CTRL_SLEEP_OFF: | ||
| 148 | ext_reg = &(ri->slp_off_reg); | ||
| 149 | break; | ||
| 150 | default: | ||
| 151 | return -EINVAL; | ||
| 152 | } | ||
| 153 | |||
| 154 | addr = ext_reg->addr + offset; | ||
| 155 | mask = ((1 << ext_reg->nbits) - 1) << ext_reg->shift_bits; | ||
| 156 | |||
| 157 | return tps6591x_update(parent, addr, mask, mask); | ||
| 158 | } | ||
| 159 | |||
| 160 | static void wait_for_voltage_change(struct tps6591x_regulator *ri, int uV) | ||
| 161 | { | ||
| 162 | int change_uv; | ||
| 163 | int change_us; | ||
| 164 | |||
| 165 | change_uv = abs(uV - ri->current_volt_uv); | ||
| 166 | change_us = change_uv/ri->voltage_change_uv_per_us + 1; | ||
| 167 | if (change_us >= 1000) { | ||
| 168 | mdelay(change_us/1000); | ||
| 169 | change_us -= (change_us/1000); | ||
| 170 | } | ||
| 171 | if (change_us) | ||
| 172 | udelay(change_us); | ||
| 173 | ri->current_volt_uv = uV; | ||
| 174 | } | ||
| 175 | |||
| 176 | static int __tps6591x_vio_set_voltage(struct device *parent, | ||
| 177 | struct tps6591x_regulator *ri, | ||
| 178 | int min_uV, int max_uV, | ||
| 179 | unsigned *selector) | ||
| 180 | { | ||
| 181 | int uV; | ||
| 182 | uint8_t mask; | ||
| 183 | uint8_t val; | ||
| 184 | int ret; | ||
| 185 | uint8_t reg_val; | ||
| 186 | |||
| 187 | for (val = 0; val < ri->desc.n_voltages; val++) { | ||
| 188 | uV = ri->voltages[val] * 1000; | ||
| 189 | |||
| 190 | /* use the first in-range value */ | ||
| 191 | if (min_uV <= uV && uV <= max_uV) { | ||
| 192 | if (selector) | ||
| 193 | *selector = val; | ||
| 194 | |||
| 195 | reg_val = ri->supply_reg.cache_val; | ||
| 196 | val <<= ri->supply_reg.shift_bits; | ||
| 197 | |||
| 198 | mask = ((1 << ri->supply_reg.nbits) - 1) << | ||
| 199 | ri->supply_reg.shift_bits; | ||
| 200 | reg_val = (reg_val & ~mask) | (val & mask); | ||
| 201 | |||
| 202 | ret = tps6591x_write(parent, ri->supply_reg.addr, | ||
| 203 | reg_val); | ||
| 204 | if (ret >= 0) { | ||
| 205 | wait_for_voltage_change(ri, uV); | ||
| 206 | ri->supply_reg.cache_val = reg_val; | ||
| 207 | } | ||
| 208 | return ret; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | return -EINVAL; | ||
| 213 | } | ||
| 214 | |||
| 215 | static int tps6591x_vio_set_voltage(struct regulator_dev *rdev, | ||
| 216 | int min_uV, int max_uV, | ||
| 217 | unsigned *selector) | ||
| 218 | { | ||
| 219 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 220 | struct device *parent = to_tps6591x_dev(rdev); | ||
| 221 | |||
| 222 | return __tps6591x_vio_set_voltage(parent, ri, min_uV, max_uV, | ||
| 223 | selector); | ||
| 224 | } | ||
| 225 | |||
| 226 | static int tps6591x_vio_get_voltage(struct regulator_dev *rdev) | ||
| 227 | { | ||
| 228 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 229 | uint8_t val, mask; | ||
| 230 | |||
| 231 | val = ri->supply_reg.cache_val; | ||
| 232 | |||
| 233 | mask = ((1 << ri->supply_reg.nbits) - 1) << ri->supply_reg.shift_bits; | ||
| 234 | val = (val & mask) >> ri->supply_reg.shift_bits; | ||
| 235 | |||
| 236 | if (val >= ri->desc.n_voltages) | ||
| 237 | BUG(); | ||
| 238 | |||
| 239 | return ri->voltages[val] * 1000; | ||
| 240 | } | ||
| 241 | |||
| 242 | |||
| 243 | static int tps6591x_ldo_list_voltage(struct regulator_dev *rdev, | ||
| 244 | unsigned selector) | ||
| 245 | { | ||
| 246 | struct tps6591x_regulator *info = rdev_get_drvdata(rdev); | ||
| 247 | |||
| 248 | return info->voltages[selector] * 1000; | ||
| 249 | } | ||
| 250 | |||
| 251 | static int __tps6591x_ldo1_set_voltage(struct device *parent, | ||
| 252 | struct tps6591x_regulator *ri, | ||
| 253 | int min_uV, int max_uV, | ||
| 254 | unsigned *selector) | ||
| 255 | { | ||
| 256 | int val, uV; | ||
| 257 | uint8_t mask; | ||
| 258 | uint8_t reg_val; | ||
| 259 | int ret; | ||
| 260 | |||
| 261 | for (val = 0; val < ri->desc.n_voltages; val++) { | ||
| 262 | uV = ri->voltages[val] * 1000; | ||
| 263 | |||
| 264 | /* use the first in-range value */ | ||
| 265 | if (min_uV <= uV && uV <= max_uV) { | ||
| 266 | if (selector) | ||
| 267 | *selector = val; | ||
| 268 | reg_val = ri->supply_reg.cache_val; | ||
| 269 | val += 4; | ||
| 270 | val <<= ri->supply_reg.shift_bits; | ||
| 271 | mask = ((1 << ri->supply_reg.nbits) - 1) << | ||
| 272 | ri->supply_reg.shift_bits; | ||
| 273 | |||
| 274 | reg_val = (reg_val & ~mask) | (val & mask); | ||
| 275 | ret = tps6591x_write(parent, ri->supply_reg.addr, | ||
| 276 | reg_val); | ||
| 277 | if (ret >= 0) { | ||
| 278 | wait_for_voltage_change(ri, uV); | ||
| 279 | ri->supply_reg.cache_val = reg_val; | ||
| 280 | } | ||
| 281 | return ret; | ||
| 282 | } | ||
| 283 | } | ||
| 284 | |||
| 285 | return -EINVAL; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int tps6591x_ldo1_set_voltage(struct regulator_dev *rdev, | ||
| 289 | int min_uV, int max_uV, | ||
| 290 | unsigned *selector) | ||
| 291 | { | ||
| 292 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 293 | struct device *parent = to_tps6591x_dev(rdev); | ||
| 294 | |||
| 295 | return __tps6591x_ldo1_set_voltage(parent, ri, min_uV, max_uV, | ||
| 296 | selector); | ||
| 297 | } | ||
| 298 | |||
| 299 | static int tps6591x_ldo1_get_voltage(struct regulator_dev *rdev) | ||
| 300 | { | ||
| 301 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 302 | uint8_t val, mask; | ||
| 303 | |||
| 304 | val = ri->supply_reg.cache_val; | ||
| 305 | mask = ((1 << ri->supply_reg.nbits) - 1) << ri->supply_reg.shift_bits; | ||
| 306 | val = (val & mask) >> ri->supply_reg.shift_bits; | ||
| 307 | |||
| 308 | if (val < 4) | ||
| 309 | return 1000 * 1000; | ||
| 310 | else if (val > 0x32) | ||
| 311 | return 3300 * 1000; | ||
| 312 | else | ||
| 313 | val -= 4; | ||
| 314 | if (val >= ri->desc.n_voltages) | ||
| 315 | BUG(); | ||
| 316 | |||
| 317 | return ri->voltages[val] * 1000; | ||
| 318 | } | ||
| 319 | |||
| 320 | static int __tps6591x_ldo3_set_voltage(struct device *parent, | ||
| 321 | struct tps6591x_regulator *ri, | ||
| 322 | int min_uV, int max_uV, | ||
| 323 | unsigned *selector) | ||
| 324 | { | ||
| 325 | int val, uV; | ||
| 326 | uint8_t mask; | ||
| 327 | int ret; | ||
| 328 | uint8_t reg_val; | ||
| 329 | |||
| 330 | for (val = 0; val < ri->desc.n_voltages; val++) { | ||
| 331 | uV = ri->voltages[val] * 1000; | ||
| 332 | |||
| 333 | /* use the first in-range value */ | ||
| 334 | if (min_uV <= uV && uV <= max_uV) { | ||
| 335 | if (selector) | ||
| 336 | *selector = val; | ||
| 337 | reg_val = ri->supply_reg.cache_val; | ||
| 338 | val += 2; | ||
| 339 | val <<= ri->supply_reg.shift_bits; | ||
| 340 | mask = ((1 << ri->supply_reg.nbits) - 1) << | ||
| 341 | ri->supply_reg.shift_bits; | ||
| 342 | |||
| 343 | reg_val = (reg_val & ~mask) | (val & mask); | ||
| 344 | |||
| 345 | ret = tps6591x_write(parent, ri->supply_reg.addr, | ||
| 346 | reg_val); | ||
| 347 | if (ret >= 0) { | ||
| 348 | wait_for_voltage_change(ri, uV); | ||
| 349 | ri->supply_reg.cache_val = reg_val; | ||
| 350 | } | ||
| 351 | return ret; | ||
| 352 | } | ||
| 353 | } | ||
| 354 | |||
| 355 | return -EINVAL; | ||
| 356 | } | ||
| 357 | |||
| 358 | static int tps6591x_ldo3_set_voltage(struct regulator_dev *rdev, | ||
| 359 | int min_uV, int max_uV, | ||
| 360 | unsigned *selector) | ||
| 361 | { | ||
| 362 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 363 | struct device *parent = to_tps6591x_dev(rdev); | ||
| 364 | |||
| 365 | return __tps6591x_ldo3_set_voltage(parent, ri, min_uV, max_uV, | ||
| 366 | selector); | ||
| 367 | } | ||
| 368 | |||
| 369 | static int tps6591x_ldo3_get_voltage(struct regulator_dev *rdev) | ||
| 370 | { | ||
| 371 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 372 | uint8_t val, mask; | ||
| 373 | |||
| 374 | val = ri->supply_reg.cache_val; | ||
| 375 | mask = ((1 << ri->supply_reg.nbits) - 1) << ri->supply_reg.shift_bits; | ||
| 376 | val = (val & mask) >> ri->supply_reg.shift_bits; | ||
| 377 | |||
| 378 | if (val < 2) | ||
| 379 | return 1000 * 1000; | ||
| 380 | else if (val > 0x19) | ||
| 381 | return 3300 * 1000; | ||
| 382 | else | ||
| 383 | val -= 2; | ||
| 384 | if (val >= ri->desc.n_voltages) | ||
| 385 | BUG(); | ||
| 386 | |||
| 387 | return ri->voltages[val] * 1000; | ||
| 388 | } | ||
| 389 | |||
| 390 | static int __tps6591x_vdd_set_voltage(struct device *parent, | ||
| 391 | struct tps6591x_regulator *ri, | ||
| 392 | int min_uV, int max_uV, | ||
| 393 | unsigned *selector) | ||
| 394 | { | ||
| 395 | int val, uV, ret; | ||
| 396 | uint8_t mask; | ||
| 397 | uint8_t op_reg_val; | ||
| 398 | uint8_t sr_reg_val; | ||
| 399 | |||
| 400 | for (val = 0; val < ri->desc.n_voltages; val++) { | ||
| 401 | uV = ri->voltages[val] * 1000; | ||
| 402 | |||
| 403 | /* use the first in-range value */ | ||
| 404 | if (min_uV <= uV && uV <= max_uV) { | ||
| 405 | if (selector) | ||
| 406 | *selector = val; | ||
| 407 | op_reg_val = ri->op_reg.cache_val; | ||
| 408 | val += 3; | ||
| 409 | if (op_reg_val & 0x80) { | ||
| 410 | sr_reg_val = ri->sr_reg.cache_val; | ||
| 411 | val <<= ri->sr_reg.shift_bits; | ||
| 412 | mask = ((1 << ri->sr_reg.nbits) - 1) | ||
| 413 | << ri->sr_reg.shift_bits; | ||
| 414 | sr_reg_val = (sr_reg_val & ~mask) | | ||
| 415 | (val & mask); | ||
| 416 | ret = tps6591x_write(parent, | ||
| 417 | ri->sr_reg.addr, sr_reg_val); | ||
| 418 | if (!ret) | ||
| 419 | ri->sr_reg.cache_val = sr_reg_val; | ||
| 420 | } else { | ||
| 421 | val <<= ri->op_reg.shift_bits; | ||
| 422 | mask = ((1 << ri->op_reg.nbits) - 1) | ||
| 423 | << ri->op_reg.shift_bits; | ||
| 424 | op_reg_val = (op_reg_val & ~mask) | | ||
| 425 | (val & mask); | ||
| 426 | ret = tps6591x_write(parent, | ||
| 427 | ri->op_reg.addr, op_reg_val); | ||
| 428 | if (!ret) | ||
| 429 | ri->op_reg.cache_val = op_reg_val; | ||
| 430 | } | ||
| 431 | if (ret >= 0) | ||
| 432 | wait_for_voltage_change(ri, uV); | ||
| 433 | return ret; | ||
| 434 | } | ||
| 435 | } | ||
| 436 | |||
| 437 | return -EINVAL; | ||
| 438 | } | ||
| 439 | |||
| 440 | static int tps6591x_vdd_set_voltage(struct regulator_dev *rdev, | ||
| 441 | int min_uV, int max_uV, | ||
| 442 | unsigned *selector) | ||
| 443 | { | ||
| 444 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 445 | struct device *parent = to_tps6591x_dev(rdev); | ||
| 446 | |||
| 447 | return __tps6591x_vdd_set_voltage(parent, ri, min_uV, max_uV, | ||
| 448 | selector); | ||
| 449 | } | ||
| 450 | |||
| 451 | static int tps6591x_vdd_get_voltage(struct regulator_dev *rdev) | ||
| 452 | { | ||
| 453 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 454 | uint8_t op_val, sr_val, val; | ||
| 455 | |||
| 456 | op_val = ri->op_reg.cache_val; | ||
| 457 | sr_val = ri->sr_reg.cache_val; | ||
| 458 | |||
| 459 | val = (op_val & 0x80) ? (sr_val & 0x7F) : (op_val & 0x7F); | ||
| 460 | |||
| 461 | if (!val) | ||
| 462 | return 0; | ||
| 463 | else if (val < 0x3) | ||
| 464 | return 600 * 1000; | ||
| 465 | else if (val > 0x4B) | ||
| 466 | return 1500 * 1000; | ||
| 467 | else | ||
| 468 | val -= 3; | ||
| 469 | |||
| 470 | if (val >= ri->desc.n_voltages) | ||
| 471 | BUG(); | ||
| 472 | |||
| 473 | return ri->voltages[val] * 1000; | ||
| 474 | } | ||
| 475 | |||
| 476 | static int tps6591x_regulator_enable(struct regulator_dev *rdev) | ||
| 477 | { | ||
| 478 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 479 | struct device *parent = to_tps6591x_dev(rdev); | ||
| 480 | uint8_t reg_val; | ||
| 481 | int ret; | ||
| 482 | |||
| 483 | reg_val = ri->supply_reg.cache_val; | ||
| 484 | reg_val |= 0x1; | ||
| 485 | |||
| 486 | ret = tps6591x_write(parent, ri->supply_reg.addr, reg_val); | ||
| 487 | if (!ret) | ||
| 488 | ri->supply_reg.cache_val = reg_val; | ||
| 489 | return ret; | ||
| 490 | } | ||
| 491 | |||
| 492 | static int tps6591x_regulator_disable(struct regulator_dev *rdev) | ||
| 493 | { | ||
| 494 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 495 | struct device *parent = to_tps6591x_dev(rdev); | ||
| 496 | uint8_t reg_val; | ||
| 497 | int ret; | ||
| 498 | |||
| 499 | reg_val = ri->supply_reg.cache_val; | ||
| 500 | reg_val &= ~0x1; | ||
| 501 | ret = tps6591x_write(parent, ri->supply_reg.addr, reg_val); | ||
| 502 | if (!ret) | ||
| 503 | ri->supply_reg.cache_val = reg_val; | ||
| 504 | return ret; | ||
| 505 | } | ||
| 506 | |||
| 507 | static int tps6591x_regulator_is_enabled(struct regulator_dev *rdev) | ||
| 508 | { | ||
| 509 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 510 | uint8_t reg_val; | ||
| 511 | |||
| 512 | reg_val = ri->supply_reg.cache_val; | ||
| 513 | reg_val &= 0x1; | ||
| 514 | return reg_val & 0x1; | ||
| 515 | } | ||
| 516 | |||
| 517 | static struct regulator_ops tps6591x_regulator_vio_ops = { | ||
| 518 | .list_voltage = tps6591x_ldo_list_voltage, | ||
| 519 | .get_voltage = tps6591x_vio_get_voltage, | ||
| 520 | .set_voltage = tps6591x_vio_set_voltage, | ||
| 521 | |||
| 522 | .enable_time = tps6591x_regulator_enable_time, | ||
| 523 | .is_enabled = tps6591x_regulator_is_enabled, | ||
| 524 | .enable = tps6591x_regulator_enable, | ||
| 525 | .disable = tps6591x_regulator_disable, | ||
| 526 | }; | ||
| 527 | |||
| 528 | static struct regulator_ops tps6591x_regulator_ldo1_ops = { | ||
| 529 | .list_voltage = tps6591x_ldo_list_voltage, | ||
| 530 | .get_voltage = tps6591x_ldo1_get_voltage, | ||
| 531 | .set_voltage = tps6591x_ldo1_set_voltage, | ||
| 532 | |||
| 533 | .enable_time = tps6591x_regulator_enable_time, | ||
| 534 | .is_enabled = tps6591x_regulator_is_enabled, | ||
| 535 | .enable = tps6591x_regulator_enable, | ||
| 536 | .disable = tps6591x_regulator_disable, | ||
| 537 | }; | ||
| 538 | |||
| 539 | static struct regulator_ops tps6591x_regulator_ldo3_ops = { | ||
| 540 | .list_voltage = tps6591x_ldo_list_voltage, | ||
| 541 | .get_voltage = tps6591x_ldo3_get_voltage, | ||
| 542 | .set_voltage = tps6591x_ldo3_set_voltage, | ||
| 543 | |||
| 544 | .enable_time = tps6591x_regulator_enable_time, | ||
| 545 | .is_enabled = tps6591x_regulator_is_enabled, | ||
| 546 | .enable = tps6591x_regulator_enable, | ||
| 547 | .disable = tps6591x_regulator_disable, | ||
| 548 | }; | ||
| 549 | |||
| 550 | static struct regulator_ops tps6591x_regulator_vdd_ops = { | ||
| 551 | .list_voltage = tps6591x_ldo_list_voltage, | ||
| 552 | .get_voltage = tps6591x_vdd_get_voltage, | ||
| 553 | .set_voltage = tps6591x_vdd_set_voltage, | ||
| 554 | |||
| 555 | .enable_time = tps6591x_regulator_enable_time, | ||
| 556 | .is_enabled = tps6591x_regulator_is_enabled, | ||
| 557 | .enable = tps6591x_regulator_enable, | ||
| 558 | .disable = tps6591x_regulator_disable, | ||
| 559 | }; | ||
| 560 | |||
| 561 | static int tps6591x_vio_voltages[] = { | ||
| 562 | 1500, 1800, 2500, 3300, | ||
| 563 | }; | ||
| 564 | |||
| 565 | /* SEL[7:2]=000100:1000mV --> 110010:3300mV */ | ||
| 566 | static int tps6591x_ldo124_voltages[] = { | ||
| 567 | 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, | ||
| 568 | 1500, 1550, 1600, 1650, 1700, 1750, 1800, 1850, 1900, 1950, | ||
| 569 | 2000, 2050, 2100, 2150, 2200, 2250, 2300, 2350, 2400, 2450, | ||
| 570 | 2500, 2550, 2600, 2650, 2700, 2750, 2800, 2850, 2900, 2950, | ||
| 571 | 3000, 3050, 3100, 3150, 3200, 3250, 3300, | ||
| 572 | }; | ||
| 573 | |||
| 574 | /* SEL[6:2]=00010:1000mv --> 11001:3300mV */ | ||
| 575 | static int tps6591x_ldo35678_voltages[] = { | ||
| 576 | 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, | ||
| 577 | 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, | ||
| 578 | 3000, 3100, 3200, 3300, | ||
| 579 | }; | ||
| 580 | |||
| 581 | static int tps6591x_vdd_voltages[] = { | ||
| 582 | 600, 612, 625, 637, 650, 662, 675, 687, 700, 712, 725, 737, | ||
| 583 | 750, 762, 775, 787, 800, 812, 825, 837, 850, 862, 875, 887, | ||
| 584 | 900, 912, 925, 937, 950, 962, 975, 987, 1000, 1012, 1025, | ||
| 585 | 1037, 1050, 1062, 1075, 1087, 1100, 1112, 1125, 1137, 1150, | ||
| 586 | 1162, 1175, 1187, 1200, 1212, 1225, 1237, 1250, 1262, 1275, | ||
| 587 | 1287, 1300, 1312, 1325, 1337, 1350, 1362, 1375, 1387, 1400, | ||
| 588 | 1412, 1425, 1437, 1450, 1462, 1475, 1487, 1500, | ||
| 589 | }; | ||
| 590 | |||
| 591 | static int tps6591x_vddctrl_voltages[] = { | ||
| 592 | 600, 612, 625, 637, 650, 662, 675, 687, 700, 712, 725, 737, | ||
| 593 | 750, 762, 775, 787, 800, 812, 825, 837, 850, 862, 875, 887, | ||
| 594 | 900, 912, 925, 937, 950, 962, 975, 987, 1000, 1012, 1025, | ||
| 595 | 1037, 1050, 1062, 1075, 1087, 1100, 1112, 1125, 1137, 1150, | ||
| 596 | 1162, 1175, 1187, 1200, 1212, 1225, 1237, 1250, 1262, 1275, | ||
| 597 | 1287, 1300, 1312, 1325, 1337, 1350, 1362, 1375, 1387, 1400, | ||
| 598 | }; | ||
| 599 | |||
| 600 | #define TPS6591X_REGULATOR(_id, vdata, _ops, s_addr, s_nbits, s_shift, \ | ||
| 601 | s_type, op_addr, op_nbits, op_shift, sr_addr, \ | ||
| 602 | sr_nbits, sr_shift, en1_addr, en1_shift, \ | ||
| 603 | slp_off_addr, slp_off_shift, en_time, \ | ||
| 604 | change_rate) \ | ||
| 605 | .desc = { \ | ||
| 606 | .name = tps6591x_rails(_id), \ | ||
| 607 | .ops = &tps6591x_regulator_##_ops, \ | ||
| 608 | .type = REGULATOR_VOLTAGE, \ | ||
| 609 | .id = TPS6591X_ID_##_id, \ | ||
| 610 | .n_voltages = ARRAY_SIZE(tps6591x_##vdata##_voltages), \ | ||
| 611 | .owner = THIS_MODULE, \ | ||
| 612 | }, \ | ||
| 613 | .supply_type = supply_type_##s_type, \ | ||
| 614 | .supply_reg = { \ | ||
| 615 | .addr = TPS6591X_##s_addr##_ADD, \ | ||
| 616 | .nbits = s_nbits, \ | ||
| 617 | .shift_bits = s_shift, \ | ||
| 618 | }, \ | ||
| 619 | .op_reg = { \ | ||
| 620 | .addr = TPS6591X_##op_addr##_ADD, \ | ||
| 621 | .nbits = op_nbits, \ | ||
| 622 | .shift_bits = op_shift, \ | ||
| 623 | }, \ | ||
| 624 | .sr_reg = { \ | ||
| 625 | .addr = TPS6591X_##sr_addr##_ADD, \ | ||
| 626 | .nbits = sr_nbits, \ | ||
| 627 | .shift_bits = sr_shift, \ | ||
| 628 | }, \ | ||
| 629 | .en1_reg = { \ | ||
| 630 | .addr = TPS6591X_##en1_addr##_ADD, \ | ||
| 631 | .nbits = 1, \ | ||
| 632 | .shift_bits = en1_shift, \ | ||
| 633 | }, \ | ||
| 634 | .slp_off_reg = { \ | ||
| 635 | .addr = TPS6591X_SLEEP_SET_##slp_off_addr##_ADD, \ | ||
| 636 | .nbits = 1, \ | ||
| 637 | .shift_bits = slp_off_shift, \ | ||
| 638 | }, \ | ||
| 639 | .voltages = tps6591x_##vdata##_voltages, \ | ||
| 640 | .enable_delay = en_time, \ | ||
| 641 | .voltage_change_uv_per_us = change_rate, | ||
| 642 | |||
| 643 | #define TPS6591X_VIO(_id, vdata, s_addr, s_nbits, s_shift, s_type, \ | ||
| 644 | en1_shift, slp_off_shift, en_time) \ | ||
| 645 | { \ | ||
| 646 | TPS6591X_REGULATOR(_id, vdata, vio_ops, s_addr, s_nbits, \ | ||
| 647 | s_shift, s_type, INVALID, 0, 0, INVALID, 0, 0, \ | ||
| 648 | EN1_SMPS, en1_shift, RES_OFF, slp_off_shift, \ | ||
| 649 | en_time, 10000) \ | ||
| 650 | } | ||
| 651 | |||
| 652 | #define TPS6591X_LDO1(_id, vdata, s_addr, s_nbits, s_shift, s_type, \ | ||
| 653 | en1_shift, slp_off_shift, en_time) \ | ||
| 654 | { \ | ||
| 655 | TPS6591X_REGULATOR(_id, vdata, ldo1_ops, s_addr, s_nbits, \ | ||
| 656 | s_shift, s_type, INVALID, 0, 0, INVALID, 0, 0, \ | ||
| 657 | EN1_LDO, en1_shift, LDO_OFF, slp_off_shift, \ | ||
| 658 | en_time, 6000) \ | ||
| 659 | } | ||
| 660 | |||
| 661 | #define TPS6591X_LDO3(_id, vdata, s_addr, s_nbits, s_shift, s_type, \ | ||
| 662 | en1_shift, slp_off_shift, en_time) \ | ||
| 663 | { \ | ||
| 664 | TPS6591X_REGULATOR(_id, vdata, ldo3_ops, s_addr, s_nbits, \ | ||
| 665 | s_shift, s_type, INVALID, 0, 0, INVALID, 0, 0, \ | ||
| 666 | EN1_LDO, en1_shift, LDO_OFF, slp_off_shift, \ | ||
| 667 | en_time, 11000) \ | ||
| 668 | } | ||
| 669 | |||
| 670 | #define TPS6591X_VDD(_id, vdata, s_addr, s_nbits, s_shift, s_type, \ | ||
| 671 | op_addr, op_nbits, op_shift, sr_addr, sr_nbits, \ | ||
| 672 | sr_shift, en1_shift, slp_off_shift, en_time) \ | ||
| 673 | { \ | ||
| 674 | TPS6591X_REGULATOR(_id, vdata, vdd_ops, s_addr, s_nbits, \ | ||
| 675 | s_shift, s_type, op_addr, op_nbits, op_shift, \ | ||
| 676 | sr_addr, sr_nbits, sr_shift, EN1_SMPS, \ | ||
| 677 | en1_shift, RES_OFF, slp_off_shift, en_time, \ | ||
| 678 | 5000) \ | ||
| 679 | } | ||
| 680 | |||
| 681 | static struct tps6591x_regulator tps6591x_regulator[] = { | ||
| 682 | TPS6591X_VIO(VIO, vio, VIO, 2, 2, single_reg, 0, 0, 350), | ||
| 683 | TPS6591X_LDO1(LDO_1, ldo124, LDO1, 6, 2, single_reg, 1, 1, 420), | ||
| 684 | TPS6591X_LDO1(LDO_2, ldo124, LDO2, 6, 2, single_reg, 2, 2, 420), | ||
| 685 | TPS6591X_LDO3(LDO_3, ldo35678, LDO3, 5, 2, single_reg, 7, 7, 230), | ||
| 686 | TPS6591X_LDO1(LDO_4, ldo124, LDO4, 6, 2, single_reg, 6, 6, 230), | ||
| 687 | TPS6591X_LDO3(LDO_5, ldo35678, LDO5, 5, 2, single_reg, 3, 3, 230), | ||
| 688 | TPS6591X_LDO3(LDO_6, ldo35678, LDO6, 5, 2, single_reg, 0, 0, 230), | ||
| 689 | TPS6591X_LDO3(LDO_7, ldo35678, LDO7, 5, 2, single_reg, 5, 5, 230), | ||
| 690 | TPS6591X_LDO3(LDO_8, ldo35678, LDO8, 5, 2, single_reg, 4, 4, 230), | ||
| 691 | TPS6591X_VDD(VDD_1, vdd, VDD1, 2, 0, sr_op_reg, VDD1_OP, | ||
| 692 | 7, 0, VDD1_SR, 7, 0, 1, 1, 350), | ||
| 693 | TPS6591X_VDD(VDD_2, vdd, VDD2, 2, 0, sr_op_reg, VDD2_OP, | ||
| 694 | 7, 0, VDD2_SR, 7, 0, 2, 2, 350), | ||
| 695 | TPS6591X_VDD(VDDCTRL, vddctrl, VDDCTRL, 2, 0, sr_op_reg, | ||
| 696 | VDDCTRL_OP, 7, 0, VDDCTRL_SR, 7, 0, 3, 3, 900), | ||
| 697 | }; | ||
| 698 | |||
| 699 | static inline int tps6591x_regulator_preinit(struct device *parent, | ||
| 700 | struct tps6591x_regulator *ri, | ||
| 701 | struct tps6591x_regulator_platform_data *tps6591x_pdata) | ||
| 702 | { | ||
| 703 | int ret; | ||
| 704 | uint8_t reg_val; | ||
| 705 | |||
| 706 | if (tps6591x_pdata->ectrl != EXT_CTRL_NONE) { | ||
| 707 | ret = __tps6591x_ext_control_set( | ||
| 708 | parent, ri, tps6591x_pdata->ectrl); | ||
| 709 | if (ret < 0) { | ||
| 710 | pr_err("Not able to configure external control %d" | ||
| 711 | " for rail %d err %d\n", tps6591x_pdata->ectrl, | ||
| 712 | ri->desc.id, ret); | ||
| 713 | return ret; | ||
| 714 | } | ||
| 715 | } | ||
| 716 | |||
| 717 | if (!tps6591x_pdata->init_apply) | ||
| 718 | return 0; | ||
| 719 | |||
| 720 | if (tps6591x_pdata->init_uV >= 0) { | ||
| 721 | switch (ri->desc.id) { | ||
| 722 | case TPS6591X_ID_VIO: | ||
| 723 | ret = __tps6591x_vio_set_voltage(parent, ri, | ||
| 724 | tps6591x_pdata->init_uV, | ||
| 725 | tps6591x_pdata->init_uV, 0); | ||
| 726 | break; | ||
| 727 | |||
| 728 | case TPS6591X_ID_LDO_1: | ||
| 729 | case TPS6591X_ID_LDO_2: | ||
| 730 | case TPS6591X_ID_LDO_4: | ||
| 731 | ret = __tps6591x_ldo1_set_voltage(parent, ri, | ||
| 732 | tps6591x_pdata->init_uV, | ||
| 733 | tps6591x_pdata->init_uV, 0); | ||
| 734 | break; | ||
| 735 | |||
| 736 | case TPS6591X_ID_LDO_3: | ||
| 737 | case TPS6591X_ID_LDO_5: | ||
| 738 | case TPS6591X_ID_LDO_6: | ||
| 739 | case TPS6591X_ID_LDO_7: | ||
| 740 | case TPS6591X_ID_LDO_8: | ||
| 741 | ret = __tps6591x_ldo3_set_voltage(parent, ri, | ||
| 742 | tps6591x_pdata->init_uV, | ||
| 743 | tps6591x_pdata->init_uV, 0); | ||
| 744 | break; | ||
| 745 | |||
| 746 | case TPS6591X_ID_VDD_1: | ||
| 747 | case TPS6591X_ID_VDD_2: | ||
| 748 | case TPS6591X_ID_VDDCTRL: | ||
| 749 | ret = __tps6591x_vdd_set_voltage(parent, ri, | ||
| 750 | tps6591x_pdata->init_uV, | ||
| 751 | tps6591x_pdata->init_uV, 0); | ||
| 752 | break; | ||
| 753 | |||
| 754 | default: | ||
| 755 | ret = -EINVAL; | ||
| 756 | break; | ||
| 757 | } | ||
| 758 | if (ret < 0) { | ||
| 759 | pr_err("Not able to initialize voltage %d for rail " | ||
| 760 | "%d err %d\n", tps6591x_pdata->init_uV, | ||
| 761 | ri->desc.id, ret); | ||
| 762 | return ret; | ||
| 763 | } | ||
| 764 | } | ||
| 765 | |||
| 766 | reg_val = ri->supply_reg.cache_val; | ||
| 767 | if (tps6591x_pdata->init_enable) | ||
| 768 | reg_val |= 0x1; | ||
| 769 | else | ||
| 770 | reg_val &= ~0x1; | ||
| 771 | ret = tps6591x_write(parent, ri->supply_reg.addr, reg_val); | ||
| 772 | |||
| 773 | if (ret < 0) | ||
| 774 | pr_err("Not able to %s rail %d err %d\n", | ||
| 775 | (tps6591x_pdata->init_enable) ? "enable" : "disable", | ||
| 776 | ri->desc.id, ret); | ||
| 777 | else | ||
| 778 | ri->supply_reg.cache_val = reg_val; | ||
| 779 | return ret; | ||
| 780 | } | ||
| 781 | |||
| 782 | static inline int tps6591x_cache_regulator_register(struct device *parent, | ||
| 783 | struct tps6591x_regulator *ri) | ||
| 784 | { | ||
| 785 | int ret; | ||
| 786 | ret = tps6591x_read(parent, ri->supply_reg.addr, | ||
| 787 | &ri->supply_reg.cache_val); | ||
| 788 | if (!ret && (ri->supply_type == supply_type_sr_op_reg)) { | ||
| 789 | ret = tps6591x_read(parent, ri->op_reg.addr, | ||
| 790 | &ri->op_reg.cache_val); | ||
| 791 | if (!ret) | ||
| 792 | ret = tps6591x_read(parent, ri->sr_reg.addr, | ||
| 793 | &ri->sr_reg.cache_val); | ||
| 794 | } | ||
| 795 | return ret; | ||
| 796 | } | ||
| 797 | |||
| 798 | static inline struct tps6591x_regulator *find_regulator_info(int id) | ||
| 799 | { | ||
| 800 | struct tps6591x_regulator *ri; | ||
| 801 | int i; | ||
| 802 | |||
| 803 | for (i = 0; i < ARRAY_SIZE(tps6591x_regulator); i++) { | ||
| 804 | ri = &tps6591x_regulator[i]; | ||
| 805 | if (ri->desc.id == id) | ||
| 806 | return ri; | ||
| 807 | } | ||
| 808 | return NULL; | ||
| 809 | } | ||
| 810 | |||
| 811 | |||
| 812 | static int __devinit tps6591x_regulator_probe(struct platform_device *pdev) | ||
| 813 | { | ||
| 814 | struct tps6591x_regulator *ri = NULL; | ||
| 815 | struct regulator_dev *rdev; | ||
| 816 | struct tps6591x_regulator_platform_data *tps_pdata; | ||
| 817 | int id = pdev->id; | ||
| 818 | int err; | ||
| 819 | |||
| 820 | dev_dbg(&pdev->dev, "Probing reulator %d\n", id); | ||
| 821 | |||
| 822 | ri = find_regulator_info(id); | ||
| 823 | if (ri == NULL) { | ||
| 824 | dev_err(&pdev->dev, "invalid regulator ID specified\n"); | ||
| 825 | return -EINVAL; | ||
| 826 | } | ||
| 827 | tps_pdata = pdev->dev.platform_data; | ||
| 828 | ri->ectrl = tps_pdata->ectrl; | ||
| 829 | ri->config_flags = tps_pdata->flags; | ||
| 830 | |||
| 831 | if (tps_pdata->slew_rate_uV_per_us) | ||
| 832 | ri->voltage_change_uv_per_us = tps_pdata->slew_rate_uV_per_us; | ||
| 833 | |||
| 834 | err = tps6591x_cache_regulator_register(pdev->dev.parent, ri); | ||
| 835 | if (err) { | ||
| 836 | dev_err(&pdev->dev, "Error in caching registers error %d\n", | ||
| 837 | err); | ||
| 838 | return err; | ||
| 839 | } | ||
| 840 | |||
| 841 | err = tps6591x_regulator_preinit(pdev->dev.parent, ri, tps_pdata); | ||
| 842 | if (err) { | ||
| 843 | dev_err(&pdev->dev, "Error in pre-initialization of regulator " | ||
| 844 | "error %d\n", err); | ||
| 845 | return err; | ||
| 846 | } | ||
| 847 | |||
| 848 | rdev = regulator_register(&ri->desc, &pdev->dev, | ||
| 849 | &tps_pdata->regulator, ri); | ||
| 850 | if (IS_ERR_OR_NULL(rdev)) { | ||
| 851 | dev_err(&pdev->dev, "failed to register regulator %s\n", | ||
| 852 | ri->desc.name); | ||
| 853 | return PTR_ERR(rdev); | ||
| 854 | } | ||
| 855 | ri->current_volt_uv = ri->desc.ops->get_voltage(rdev); | ||
| 856 | |||
| 857 | platform_set_drvdata(pdev, rdev); | ||
| 858 | |||
| 859 | return 0; | ||
| 860 | } | ||
| 861 | |||
| 862 | static int __devexit tps6591x_regulator_remove(struct platform_device *pdev) | ||
| 863 | { | ||
| 864 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | ||
| 865 | |||
| 866 | regulator_unregister(rdev); | ||
| 867 | return 0; | ||
| 868 | } | ||
| 869 | |||
| 870 | static void tps6591x_regulator_shutdown(struct platform_device *pdev) | ||
| 871 | { | ||
| 872 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | ||
| 873 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 874 | struct device *parent = to_tps6591x_dev(rdev); | ||
| 875 | int ret; | ||
| 876 | |||
| 877 | if (ri->ectrl == EXT_CTRL_EN1) { | ||
| 878 | ret = tps6591x_clr_bits(parent, ri->en1_reg.addr, | ||
| 879 | (1 << ri->en1_reg.shift_bits)); | ||
| 880 | if (ret < 0) | ||
| 881 | dev_err(&pdev->dev, "Error in clearing external control\n"); | ||
| 882 | } | ||
| 883 | } | ||
| 884 | |||
| 885 | static int tps6591x_suspend(struct platform_device *pdev, pm_message_t state) | ||
| 886 | { | ||
| 887 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | ||
| 888 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 889 | struct device *parent = to_tps6591x_dev(rdev); | ||
| 890 | int ret = 0; | ||
| 891 | uint8_t reg_val; | ||
| 892 | |||
| 893 | if (ri->config_flags & LDO_LOW_POWER_ON_SUSPEND) { | ||
| 894 | ret = tps6591x_clr_bits(parent, ri->en1_reg.addr, | ||
| 895 | (1 << ri->en1_reg.shift_bits)); | ||
| 896 | reg_val = ri->supply_reg.cache_val; | ||
| 897 | reg_val = (reg_val & ~0x3) | (0x3); | ||
| 898 | ret = tps6591x_write(parent, ri->supply_reg.addr, reg_val); | ||
| 899 | if (ret >= 0) | ||
| 900 | ri->supply_reg.cache_val = reg_val; | ||
| 901 | else | ||
| 902 | dev_err(&pdev->dev, "Error in updating the supply state\n"); | ||
| 903 | } | ||
| 904 | return ret; | ||
| 905 | } | ||
| 906 | |||
| 907 | static int tps6591x_resume(struct platform_device *pdev) | ||
| 908 | { | ||
| 909 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | ||
| 910 | struct tps6591x_regulator *ri = rdev_get_drvdata(rdev); | ||
| 911 | struct device *parent = to_tps6591x_dev(rdev); | ||
| 912 | int ret = 0; | ||
| 913 | uint8_t reg_val; | ||
| 914 | |||
| 915 | if (ri->config_flags & LDO_LOW_POWER_ON_SUSPEND) { | ||
| 916 | ret = tps6591x_clr_bits(parent, ri->en1_reg.addr, | ||
| 917 | (1 << ri->en1_reg.shift_bits)); | ||
| 918 | reg_val = ri->supply_reg.cache_val; | ||
| 919 | reg_val = (reg_val & ~0x3) | (0x1); | ||
| 920 | ret = tps6591x_write(parent, ri->supply_reg.addr, reg_val); | ||
| 921 | if (ret >= 0) | ||
| 922 | ri->supply_reg.cache_val = reg_val; | ||
| 923 | else | ||
| 924 | dev_err(&pdev->dev, "Error in updating the supply state\n"); | ||
| 925 | } | ||
| 926 | return ret; | ||
| 927 | } | ||
| 928 | |||
| 929 | static struct platform_driver tps6591x_regulator_driver = { | ||
| 930 | .driver = { | ||
| 931 | .name = "tps6591x-regulator", | ||
| 932 | .owner = THIS_MODULE, | ||
| 933 | }, | ||
| 934 | .probe = tps6591x_regulator_probe, | ||
| 935 | .remove = __devexit_p(tps6591x_regulator_remove), | ||
| 936 | .shutdown = tps6591x_regulator_shutdown, | ||
| 937 | .suspend = tps6591x_suspend, | ||
| 938 | .resume = tps6591x_resume, | ||
| 939 | }; | ||
| 940 | |||
| 941 | static int __init tps6591x_regulator_init(void) | ||
| 942 | { | ||
| 943 | return platform_driver_register(&tps6591x_regulator_driver); | ||
| 944 | } | ||
| 945 | subsys_initcall(tps6591x_regulator_init); | ||
| 946 | |||
| 947 | static void __exit tps6591x_regulator_exit(void) | ||
| 948 | { | ||
| 949 | platform_driver_unregister(&tps6591x_regulator_driver); | ||
| 950 | } | ||
| 951 | module_exit(tps6591x_regulator_exit); | ||
| 952 | |||
| 953 | MODULE_LICENSE("GPL"); | ||
| 954 | MODULE_DESCRIPTION("Regulator Driver for TI TPS6591X PMIC"); | ||
| 955 | MODULE_ALIAS("platform:tps6591x-regulator"); | ||
