diff options
author | Axel Lin <axel.lin@ingics.com> | 2012-11-27 21:41:04 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-11-28 14:21:00 -0500 |
commit | 05cf34c1af48e2e1308a03fbc778039243bebd3a (patch) | |
tree | d9b041473e6fd6a3b94ba5e1d870cf8d162b622d /drivers/regulator/pcf50633-regulator.c | |
parent | 6b1f8a45666877d4885c03d9472657fd73edfa8b (diff) |
regulator: pcf50633: Use linear_min_sel and regulator_[map|list]_voltage_linear
This driver can be converted to use linear_min_sel and
regulator_[map|list]_voltage_linear.
Below shows the equation (from Datasheet) for each LDOs.
For AUTOOUT:
VO(prog) = 0.625 + auto_out x 0.025 V; e.g.
(00000000 to 00101110: reserved)
00101111: 1.8 V (min)
01010011: 2.7 V
01101010: 3.275 V
01101011: 3.300 V
01101100: 3.325 V
01111111 : 3.800 V (max)
The linear mapping start from 0x2f selector.
Thus we convert this equation to:
VO(prog) = 1.8 + (selector - linear_min_sel) x 0.025 V
(min_uV = 1800000, uV_step = 25000, linear_min_sel = 0x2f)
For DOWNxOUT:
VO(prog) = 0.625 + downx_out x 0.025 V; e.g.
00000000 : 0.625 V (min)
00010111 : 1.200 V
00101111 : 1.800 V
01011111 : 3.000 V (max)
For xLDOOUT:
VO(prog) = 0.9 + xldo_out x 0.1 V; e.g.
00000: 0.9 V
00001: 1.0 V
11000 : 3.3 V
11011 : 3.6 V
Signed-off-by: Axel Lin <axel.lin@ingics.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/regulator/pcf50633-regulator.c')
-rw-r--r-- | drivers/regulator/pcf50633-regulator.c | 176 |
1 files changed, 28 insertions, 148 deletions
diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 092e5cb848a1..769272afff2a 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c | |||
@@ -24,12 +24,15 @@ | |||
24 | #include <linux/mfd/pcf50633/core.h> | 24 | #include <linux/mfd/pcf50633/core.h> |
25 | #include <linux/mfd/pcf50633/pmic.h> | 25 | #include <linux/mfd/pcf50633/pmic.h> |
26 | 26 | ||
27 | #define PCF50633_REGULATOR(_name, _id, _n) \ | 27 | #define PCF50633_REGULATOR(_name, _id, _min_uV, _uV_step, _min_sel, _n) \ |
28 | { \ | 28 | { \ |
29 | .name = _name, \ | 29 | .name = _name, \ |
30 | .id = PCF50633_REGULATOR_##_id, \ | 30 | .id = PCF50633_REGULATOR_##_id, \ |
31 | .ops = &pcf50633_regulator_ops, \ | 31 | .ops = &pcf50633_regulator_ops, \ |
32 | .n_voltages = _n, \ | 32 | .n_voltages = _n, \ |
33 | .min_uV = _min_uV, \ | ||
34 | .uV_step = _uV_step, \ | ||
35 | .linear_min_sel = _min_sel, \ | ||
33 | .type = REGULATOR_VOLTAGE, \ | 36 | .type = REGULATOR_VOLTAGE, \ |
34 | .owner = THIS_MODULE, \ | 37 | .owner = THIS_MODULE, \ |
35 | .vsel_reg = PCF50633_REG_##_id##OUT, \ | 38 | .vsel_reg = PCF50633_REG_##_id##OUT, \ |
@@ -38,162 +41,39 @@ | |||
38 | .enable_mask = PCF50633_REGULATOR_ON, \ | 41 | .enable_mask = PCF50633_REGULATOR_ON, \ |
39 | } | 42 | } |
40 | 43 | ||
41 | /* Bits from voltage value */ | ||
42 | static u8 auto_voltage_bits(unsigned int millivolts) | ||
43 | { | ||
44 | if (millivolts < 1800) | ||
45 | return 0x2f; | ||
46 | if (millivolts > 3800) | ||
47 | return 0xff; | ||
48 | |||
49 | millivolts -= 625; | ||
50 | |||
51 | return millivolts / 25; | ||
52 | } | ||
53 | |||
54 | static u8 down_voltage_bits(unsigned int millivolts) | ||
55 | { | ||
56 | if (millivolts < 625) | ||
57 | return 0; | ||
58 | else if (millivolts > 3000) | ||
59 | return 0xff; | ||
60 | |||
61 | millivolts -= 625; | ||
62 | |||
63 | return millivolts / 25; | ||
64 | } | ||
65 | |||
66 | static u8 ldo_voltage_bits(unsigned int millivolts) | ||
67 | { | ||
68 | if (millivolts < 900) | ||
69 | return 0; | ||
70 | else if (millivolts > 3600) | ||
71 | return 0x1f; | ||
72 | |||
73 | millivolts -= 900; | ||
74 | return millivolts / 100; | ||
75 | } | ||
76 | |||
77 | /* Obtain voltage value from bits */ | ||
78 | static unsigned int auto_voltage_value(u8 bits) | ||
79 | { | ||
80 | /* AUTOOUT: 00000000 to 00101110 are reserved. | ||
81 | * Return 0 for bits in reserved range, which means this selector code | ||
82 | * can't be used on this system */ | ||
83 | if (bits < 0x2f) | ||
84 | return 0; | ||
85 | |||
86 | return 625 + (bits * 25); | ||
87 | } | ||
88 | |||
89 | |||
90 | static unsigned int down_voltage_value(u8 bits) | ||
91 | { | ||
92 | return 625 + (bits * 25); | ||
93 | } | ||
94 | |||
95 | |||
96 | static unsigned int ldo_voltage_value(u8 bits) | ||
97 | { | ||
98 | bits &= 0x1f; | ||
99 | |||
100 | return 900 + (bits * 100); | ||
101 | } | ||
102 | |||
103 | static int pcf50633_regulator_map_voltage(struct regulator_dev *rdev, | ||
104 | int min_uV, int max_uV) | ||
105 | { | ||
106 | struct pcf50633 *pcf; | ||
107 | int regulator_id, millivolts; | ||
108 | u8 volt_bits; | ||
109 | |||
110 | pcf = rdev_get_drvdata(rdev); | ||
111 | |||
112 | regulator_id = rdev_get_id(rdev); | ||
113 | if (regulator_id >= PCF50633_NUM_REGULATORS) | ||
114 | return -EINVAL; | ||
115 | |||
116 | millivolts = min_uV / 1000; | ||
117 | |||
118 | switch (regulator_id) { | ||
119 | case PCF50633_REGULATOR_AUTO: | ||
120 | volt_bits = auto_voltage_bits(millivolts); | ||
121 | break; | ||
122 | case PCF50633_REGULATOR_DOWN1: | ||
123 | case PCF50633_REGULATOR_DOWN2: | ||
124 | volt_bits = down_voltage_bits(millivolts); | ||
125 | break; | ||
126 | case PCF50633_REGULATOR_LDO1: | ||
127 | case PCF50633_REGULATOR_LDO2: | ||
128 | case PCF50633_REGULATOR_LDO3: | ||
129 | case PCF50633_REGULATOR_LDO4: | ||
130 | case PCF50633_REGULATOR_LDO5: | ||
131 | case PCF50633_REGULATOR_LDO6: | ||
132 | case PCF50633_REGULATOR_HCLDO: | ||
133 | case PCF50633_REGULATOR_MEMLDO: | ||
134 | volt_bits = ldo_voltage_bits(millivolts); | ||
135 | break; | ||
136 | default: | ||
137 | return -EINVAL; | ||
138 | } | ||
139 | |||
140 | return volt_bits; | ||
141 | } | ||
142 | |||
143 | static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, | ||
144 | unsigned int index) | ||
145 | { | ||
146 | int regulator_id = rdev_get_id(rdev); | ||
147 | |||
148 | int millivolts; | ||
149 | |||
150 | switch (regulator_id) { | ||
151 | case PCF50633_REGULATOR_AUTO: | ||
152 | millivolts = auto_voltage_value(index); | ||
153 | break; | ||
154 | case PCF50633_REGULATOR_DOWN1: | ||
155 | case PCF50633_REGULATOR_DOWN2: | ||
156 | millivolts = down_voltage_value(index); | ||
157 | break; | ||
158 | case PCF50633_REGULATOR_LDO1: | ||
159 | case PCF50633_REGULATOR_LDO2: | ||
160 | case PCF50633_REGULATOR_LDO3: | ||
161 | case PCF50633_REGULATOR_LDO4: | ||
162 | case PCF50633_REGULATOR_LDO5: | ||
163 | case PCF50633_REGULATOR_LDO6: | ||
164 | case PCF50633_REGULATOR_HCLDO: | ||
165 | case PCF50633_REGULATOR_MEMLDO: | ||
166 | millivolts = ldo_voltage_value(index); | ||
167 | break; | ||
168 | default: | ||
169 | return -EINVAL; | ||
170 | } | ||
171 | |||
172 | return millivolts * 1000; | ||
173 | } | ||
174 | |||
175 | static struct regulator_ops pcf50633_regulator_ops = { | 44 | static struct regulator_ops pcf50633_regulator_ops = { |
176 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 45 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
177 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 46 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
178 | .list_voltage = pcf50633_regulator_list_voltage, | 47 | .list_voltage = regulator_list_voltage_linear, |
179 | .map_voltage = pcf50633_regulator_map_voltage, | 48 | .map_voltage = regulator_map_voltage_linear, |
180 | .enable = regulator_enable_regmap, | 49 | .enable = regulator_enable_regmap, |
181 | .disable = regulator_disable_regmap, | 50 | .disable = regulator_disable_regmap, |
182 | .is_enabled = regulator_is_enabled_regmap, | 51 | .is_enabled = regulator_is_enabled_regmap, |
183 | }; | 52 | }; |
184 | 53 | ||
185 | static const struct regulator_desc regulators[] = { | 54 | static const struct regulator_desc regulators[] = { |
186 | [PCF50633_REGULATOR_AUTO] = PCF50633_REGULATOR("auto", AUTO, 128), | 55 | [PCF50633_REGULATOR_AUTO] = |
187 | [PCF50633_REGULATOR_DOWN1] = PCF50633_REGULATOR("down1", DOWN1, 96), | 56 | PCF50633_REGULATOR("auto", AUTO, 1800000, 25000, 0x2f, 128), |
188 | [PCF50633_REGULATOR_DOWN2] = PCF50633_REGULATOR("down2", DOWN2, 96), | 57 | [PCF50633_REGULATOR_DOWN1] = |
189 | [PCF50633_REGULATOR_LDO1] = PCF50633_REGULATOR("ldo1", LDO1, 28), | 58 | PCF50633_REGULATOR("down1", DOWN1, 625000, 25000, 0, 96), |
190 | [PCF50633_REGULATOR_LDO2] = PCF50633_REGULATOR("ldo2", LDO2, 28), | 59 | [PCF50633_REGULATOR_DOWN2] = |
191 | [PCF50633_REGULATOR_LDO3] = PCF50633_REGULATOR("ldo3", LDO3, 28), | 60 | PCF50633_REGULATOR("down2", DOWN2, 625000, 25000, 0, 96), |
192 | [PCF50633_REGULATOR_LDO4] = PCF50633_REGULATOR("ldo4", LDO4, 28), | 61 | [PCF50633_REGULATOR_LDO1] = |
193 | [PCF50633_REGULATOR_LDO5] = PCF50633_REGULATOR("ldo5", LDO5, 28), | 62 | PCF50633_REGULATOR("ldo1", LDO1, 900000, 100000, 0, 28), |
194 | [PCF50633_REGULATOR_LDO6] = PCF50633_REGULATOR("ldo6", LDO6, 28), | 63 | [PCF50633_REGULATOR_LDO2] = |
195 | [PCF50633_REGULATOR_HCLDO] = PCF50633_REGULATOR("hcldo", HCLDO, 28), | 64 | PCF50633_REGULATOR("ldo2", LDO2, 900000, 100000, 0, 28), |
196 | [PCF50633_REGULATOR_MEMLDO] = PCF50633_REGULATOR("memldo", MEMLDO, 28), | 65 | [PCF50633_REGULATOR_LDO3] = |
66 | PCF50633_REGULATOR("ldo3", LDO3, 900000, 100000, 0, 28), | ||
67 | [PCF50633_REGULATOR_LDO4] = | ||
68 | PCF50633_REGULATOR("ldo4", LDO4, 900000, 100000, 0, 28), | ||
69 | [PCF50633_REGULATOR_LDO5] = | ||
70 | PCF50633_REGULATOR("ldo5", LDO5, 900000, 100000, 0, 28), | ||
71 | [PCF50633_REGULATOR_LDO6] = | ||
72 | PCF50633_REGULATOR("ldo6", LDO6, 900000, 100000, 0, 28), | ||
73 | [PCF50633_REGULATOR_HCLDO] = | ||
74 | PCF50633_REGULATOR("hcldo", HCLDO, 900000, 100000, 0, 28), | ||
75 | [PCF50633_REGULATOR_MEMLDO] = | ||
76 | PCF50633_REGULATOR("memldo", MEMLDO, 900000, 100000, 0, 28), | ||
197 | }; | 77 | }; |
198 | 78 | ||
199 | static int __devinit pcf50633_regulator_probe(struct platform_device *pdev) | 79 | static int __devinit pcf50633_regulator_probe(struct platform_device *pdev) |