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

regulator: add pcap driver

Add (partial) support for the voltage regulators on the PCAP2 PMIC.

Signed-off-by: Daniel Ribeiro <drwyrm@gmail.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Daniel Ribeiro and committed by
Samuel Ortiz
39b1772a b75ea16a

+326
+7
drivers/regulator/Kconfig
··· 117 117 Say Y here to support the voltage regulators and convertors 118 118 on National Semiconductors LP3971 PMIC 119 119 120 + config REGULATOR_PCAP 121 + tristate "PCAP2 regulator driver" 122 + depends on EZX_PCAP 123 + help 124 + This driver provides support for the voltage regulators of the 125 + PCAP2 PMIC. 126 + 120 127 endif
+1
drivers/regulator/Makefile
··· 16 16 obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o 17 17 obj-$(CONFIG_REGULATOR_DA903X) += da903x.o 18 18 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o 19 + obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o 19 20 20 21 ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
+318
drivers/regulator/pcap-regulator.c
··· 1 + /* 2 + * PCAP2 Regulator Driver 3 + * 4 + * Copyright (c) 2009 Daniel Ribeiro <drwyrm@gmail.com> 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License as published by the 8 + * Free Software Foundation; either version 2 of the License, or (at your 9 + * option) any later version. 10 + */ 11 + 12 + #include <linux/kernel.h> 13 + #include <linux/module.h> 14 + #include <linux/init.h> 15 + #include <linux/err.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/regulator/driver.h> 18 + #include <linux/regulator/machine.h> 19 + #include <linux/mfd/ezx-pcap.h> 20 + 21 + static const u16 V1_table[] = { 22 + 2775, 1275, 1600, 1725, 1825, 1925, 2075, 2275, 23 + }; 24 + 25 + static const u16 V2_table[] = { 26 + 2500, 2775, 27 + }; 28 + 29 + static const u16 V3_table[] = { 30 + 1075, 1275, 1550, 1725, 1876, 1950, 2075, 2275, 31 + }; 32 + 33 + static const u16 V4_table[] = { 34 + 1275, 1550, 1725, 1875, 1950, 2075, 2275, 2775, 35 + }; 36 + 37 + static const u16 V5_table[] = { 38 + 1875, 2275, 2475, 2775, 39 + }; 40 + 41 + static const u16 V6_table[] = { 42 + 2475, 2775, 43 + }; 44 + 45 + static const u16 V7_table[] = { 46 + 1875, 2775, 47 + }; 48 + 49 + #define V8_table V4_table 50 + 51 + static const u16 V9_table[] = { 52 + 1575, 1875, 2475, 2775, 53 + }; 54 + 55 + static const u16 V10_table[] = { 56 + 5000, 57 + }; 58 + 59 + static const u16 VAUX1_table[] = { 60 + 1875, 2475, 2775, 3000, 61 + }; 62 + 63 + #define VAUX2_table VAUX1_table 64 + 65 + static const u16 VAUX3_table[] = { 66 + 1200, 1200, 1200, 1200, 1400, 1600, 1800, 2000, 67 + 2200, 2400, 2600, 2800, 3000, 3200, 3400, 3600, 68 + }; 69 + 70 + static const u16 VAUX4_table[] = { 71 + 1800, 1800, 3000, 5000, 72 + }; 73 + 74 + static const u16 VSIM_table[] = { 75 + 1875, 3000, 76 + }; 77 + 78 + static const u16 VSIM2_table[] = { 79 + 1875, 80 + }; 81 + 82 + static const u16 VVIB_table[] = { 83 + 1300, 1800, 2000, 3000, 84 + }; 85 + 86 + static const u16 SW1_table[] = { 87 + 900, 950, 1000, 1050, 1100, 1150, 1200, 1250, 88 + 1300, 1350, 1400, 1450, 1500, 1600, 1875, 2250, 89 + }; 90 + 91 + #define SW2_table SW1_table 92 + 93 + static const u16 SW3_table[] = { 94 + 4000, 4500, 5000, 5500, 95 + }; 96 + 97 + struct pcap_regulator { 98 + const u8 reg; 99 + const u8 en; 100 + const u8 index; 101 + const u8 stby; 102 + const u8 lowpwr; 103 + const u8 n_voltages; 104 + const u16 *voltage_table; 105 + }; 106 + 107 + #define NA 0xff 108 + 109 + #define VREG_INFO(_vreg, _reg, _en, _index, _stby, _lowpwr) \ 110 + [_vreg] = { \ 111 + .reg = _reg, \ 112 + .en = _en, \ 113 + .index = _index, \ 114 + .stby = _stby, \ 115 + .lowpwr = _lowpwr, \ 116 + .n_voltages = ARRAY_SIZE(_vreg##_table), \ 117 + .voltage_table = _vreg##_table, \ 118 + } 119 + 120 + static struct pcap_regulator vreg_table[] = { 121 + VREG_INFO(V1, PCAP_REG_VREG1, 1, 2, 18, 0), 122 + VREG_INFO(V2, PCAP_REG_VREG1, 5, 6, 19, 22), 123 + VREG_INFO(V3, PCAP_REG_VREG1, 7, 8, 20, 23), 124 + VREG_INFO(V4, PCAP_REG_VREG1, 11, 12, 21, 24), 125 + /* V5 STBY and LOWPWR are on PCAP_REG_VREG2 */ 126 + VREG_INFO(V5, PCAP_REG_VREG1, 15, 16, 12, 19), 127 + 128 + VREG_INFO(V6, PCAP_REG_VREG2, 1, 2, 14, 20), 129 + VREG_INFO(V7, PCAP_REG_VREG2, 3, 4, 15, 21), 130 + VREG_INFO(V8, PCAP_REG_VREG2, 5, 6, 16, 22), 131 + VREG_INFO(V9, PCAP_REG_VREG2, 9, 10, 17, 23), 132 + VREG_INFO(V10, PCAP_REG_VREG2, 10, NA, 18, 24), 133 + 134 + VREG_INFO(VAUX1, PCAP_REG_AUXVREG, 1, 2, 22, 23), 135 + /* VAUX2 ... VSIM2 STBY and LOWPWR are on PCAP_REG_LOWPWR */ 136 + VREG_INFO(VAUX2, PCAP_REG_AUXVREG, 4, 5, 0, 1), 137 + VREG_INFO(VAUX3, PCAP_REG_AUXVREG, 7, 8, 2, 3), 138 + VREG_INFO(VAUX4, PCAP_REG_AUXVREG, 12, 13, 4, 5), 139 + VREG_INFO(VSIM, PCAP_REG_AUXVREG, 17, 18, NA, 6), 140 + VREG_INFO(VSIM2, PCAP_REG_AUXVREG, 16, NA, NA, 7), 141 + VREG_INFO(VVIB, PCAP_REG_AUXVREG, 19, 20, NA, NA), 142 + 143 + VREG_INFO(SW1, PCAP_REG_SWCTRL, 1, 2, NA, NA), 144 + VREG_INFO(SW2, PCAP_REG_SWCTRL, 6, 7, NA, NA), 145 + /* SW3 STBY is on PCAP_REG_AUXVREG */ 146 + VREG_INFO(SW3, PCAP_REG_SWCTRL, 11, 12, 24, NA), 147 + 148 + /* SWxS used to control SWx voltage on standby */ 149 + /* VREG_INFO(SW1S, PCAP_REG_LOWPWR, NA, 12, NA, NA), 150 + VREG_INFO(SW2S, PCAP_REG_LOWPWR, NA, 20, NA, NA), */ 151 + }; 152 + 153 + static int pcap_regulator_set_voltage(struct regulator_dev *rdev, 154 + int min_uV, int max_uV) 155 + { 156 + struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)]; 157 + void *pcap = rdev_get_drvdata(rdev); 158 + int uV; 159 + u8 i; 160 + 161 + /* the regulator doesn't support voltage switching */ 162 + if (vreg->n_voltages == 1) 163 + return -EINVAL; 164 + 165 + for (i = 0; i < vreg->n_voltages; i++) { 166 + /* For V1 the first is not the best match */ 167 + if (i == 0 && rdev_get_id(rdev) == V1) 168 + i = 1; 169 + else if (i + 1 == vreg->n_voltages && rdev_get_id(rdev) == V1) 170 + i = 0; 171 + 172 + uV = vreg->voltage_table[i] * 1000; 173 + if (min_uV <= uV && uV <= max_uV) 174 + return ezx_pcap_set_bits(pcap, vreg->reg, 175 + (vreg->n_voltages - 1) << vreg->index, 176 + i << vreg->index); 177 + 178 + if (i == 0 && rdev_get_id(rdev) == V1) 179 + i = vreg->n_voltages - 1; 180 + } 181 + 182 + /* the requested voltage range is not supported by this regulator */ 183 + return -EINVAL; 184 + } 185 + 186 + static int pcap_regulator_get_voltage(struct regulator_dev *rdev) 187 + { 188 + struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)]; 189 + void *pcap = rdev_get_drvdata(rdev); 190 + u32 tmp; 191 + int mV; 192 + 193 + if (vreg->n_voltages == 1) 194 + return vreg->voltage_table[0] * 1000; 195 + 196 + ezx_pcap_read(pcap, vreg->reg, &tmp); 197 + tmp = ((tmp >> vreg->index) & (vreg->n_voltages - 1)); 198 + mV = vreg->voltage_table[tmp]; 199 + 200 + return mV * 1000; 201 + } 202 + 203 + static int pcap_regulator_enable(struct regulator_dev *rdev) 204 + { 205 + struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)]; 206 + void *pcap = rdev_get_drvdata(rdev); 207 + 208 + if (vreg->en == NA) 209 + return -EINVAL; 210 + 211 + return ezx_pcap_set_bits(pcap, vreg->reg, 1 << vreg->en, 1 << vreg->en); 212 + } 213 + 214 + static int pcap_regulator_disable(struct regulator_dev *rdev) 215 + { 216 + struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)]; 217 + void *pcap = rdev_get_drvdata(rdev); 218 + 219 + if (vreg->en == NA) 220 + return -EINVAL; 221 + 222 + return ezx_pcap_set_bits(pcap, vreg->reg, 1 << vreg->en, 0); 223 + } 224 + 225 + static int pcap_regulator_is_enabled(struct regulator_dev *rdev) 226 + { 227 + struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)]; 228 + void *pcap = rdev_get_drvdata(rdev); 229 + u32 tmp; 230 + 231 + if (vreg->en == NA) 232 + return -EINVAL; 233 + 234 + ezx_pcap_read(pcap, vreg->reg, &tmp); 235 + return (tmp >> vreg->en) & 1; 236 + } 237 + 238 + static int pcap_regulator_list_voltage(struct regulator_dev *rdev, 239 + unsigned int index) 240 + { 241 + struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)]; 242 + 243 + return vreg->voltage_table[index] * 1000; 244 + } 245 + 246 + static struct regulator_ops pcap_regulator_ops = { 247 + .list_voltage = pcap_regulator_list_voltage, 248 + .set_voltage = pcap_regulator_set_voltage, 249 + .get_voltage = pcap_regulator_get_voltage, 250 + .enable = pcap_regulator_enable, 251 + .disable = pcap_regulator_disable, 252 + .is_enabled = pcap_regulator_is_enabled, 253 + }; 254 + 255 + #define VREG(_vreg) \ 256 + [_vreg] = { \ 257 + .name = #_vreg, \ 258 + .id = _vreg, \ 259 + .n_voltages = ARRAY_SIZE(_vreg##_table), \ 260 + .ops = &pcap_regulator_ops, \ 261 + .type = REGULATOR_VOLTAGE, \ 262 + .owner = THIS_MODULE, \ 263 + } 264 + 265 + static struct regulator_desc pcap_regulators[] = { 266 + VREG(V1), VREG(V2), VREG(V3), VREG(V4), VREG(V5), VREG(V6), VREG(V7), 267 + VREG(V8), VREG(V9), VREG(V10), VREG(VAUX1), VREG(VAUX2), VREG(VAUX3), 268 + VREG(VAUX4), VREG(VSIM), VREG(VSIM2), VREG(VVIB), VREG(SW1), VREG(SW2), 269 + }; 270 + 271 + static int __devinit pcap_regulator_probe(struct platform_device *pdev) 272 + { 273 + struct regulator_dev *rdev; 274 + void *pcap = platform_get_drvdata(pdev); 275 + 276 + rdev = regulator_register(&pcap_regulators[pdev->id], &pdev->dev, 277 + pdev->dev.platform_data, pcap); 278 + if (IS_ERR(rdev)) 279 + return PTR_ERR(rdev); 280 + 281 + platform_set_drvdata(pdev, rdev); 282 + 283 + return 0; 284 + } 285 + 286 + static int __devexit pcap_regulator_remove(struct platform_device *pdev) 287 + { 288 + struct regulator_dev *rdev = platform_get_drvdata(pdev); 289 + 290 + regulator_unregister(rdev); 291 + 292 + return 0; 293 + } 294 + 295 + static struct platform_driver pcap_regulator_driver = { 296 + .driver = { 297 + .name = "pcap-regulator", 298 + }, 299 + .probe = pcap_regulator_probe, 300 + .remove = __devexit_p(pcap_regulator_remove), 301 + }; 302 + 303 + static int __init pcap_regulator_init(void) 304 + { 305 + return platform_driver_register(&pcap_regulator_driver); 306 + } 307 + 308 + static void __exit pcap_regulator_exit(void) 309 + { 310 + platform_driver_unregister(&pcap_regulator_driver); 311 + } 312 + 313 + module_init(pcap_regulator_init); 314 + module_exit(pcap_regulator_exit); 315 + 316 + MODULE_AUTHOR("Daniel Ribeiro <drwyrm@gmail.com>"); 317 + MODULE_DESCRIPTION("PCAP2 Regulator Driver"); 318 + MODULE_LICENSE("GPL");