diff options
Diffstat (limited to 'drivers/mfd/sec-core.c')
-rw-r--r-- | drivers/mfd/sec-core.c | 114 |
1 files changed, 104 insertions, 10 deletions
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index a139798b8065..281a82747275 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c | |||
@@ -26,7 +26,9 @@ | |||
26 | #include <linux/mfd/samsung/core.h> | 26 | #include <linux/mfd/samsung/core.h> |
27 | #include <linux/mfd/samsung/irq.h> | 27 | #include <linux/mfd/samsung/irq.h> |
28 | #include <linux/mfd/samsung/rtc.h> | 28 | #include <linux/mfd/samsung/rtc.h> |
29 | #include <linux/mfd/samsung/s2mpa01.h> | ||
29 | #include <linux/mfd/samsung/s2mps11.h> | 30 | #include <linux/mfd/samsung/s2mps11.h> |
31 | #include <linux/mfd/samsung/s2mps14.h> | ||
30 | #include <linux/mfd/samsung/s5m8763.h> | 32 | #include <linux/mfd/samsung/s5m8763.h> |
31 | #include <linux/mfd/samsung/s5m8767.h> | 33 | #include <linux/mfd/samsung/s5m8767.h> |
32 | #include <linux/regmap.h> | 34 | #include <linux/regmap.h> |
@@ -69,18 +71,53 @@ static const struct mfd_cell s2mps11_devs[] = { | |||
69 | } | 71 | } |
70 | }; | 72 | }; |
71 | 73 | ||
74 | static const struct mfd_cell s2mps14_devs[] = { | ||
75 | { | ||
76 | .name = "s2mps14-pmic", | ||
77 | }, { | ||
78 | .name = "s2mps14-rtc", | ||
79 | }, { | ||
80 | .name = "s2mps14-clk", | ||
81 | } | ||
82 | }; | ||
83 | |||
84 | static const struct mfd_cell s2mpa01_devs[] = { | ||
85 | { | ||
86 | .name = "s2mpa01-pmic", | ||
87 | }, | ||
88 | }; | ||
89 | |||
72 | #ifdef CONFIG_OF | 90 | #ifdef CONFIG_OF |
73 | static struct of_device_id sec_dt_match[] = { | 91 | static struct of_device_id sec_dt_match[] = { |
74 | { .compatible = "samsung,s5m8767-pmic", | 92 | { .compatible = "samsung,s5m8767-pmic", |
75 | .data = (void *)S5M8767X, | 93 | .data = (void *)S5M8767X, |
76 | }, | 94 | }, { |
77 | { .compatible = "samsung,s2mps11-pmic", | 95 | .compatible = "samsung,s2mps11-pmic", |
78 | .data = (void *)S2MPS11X, | 96 | .data = (void *)S2MPS11X, |
97 | }, { | ||
98 | .compatible = "samsung,s2mps14-pmic", | ||
99 | .data = (void *)S2MPS14X, | ||
100 | }, { | ||
101 | .compatible = "samsung,s2mpa01-pmic", | ||
102 | .data = (void *)S2MPA01, | ||
103 | }, { | ||
104 | /* Sentinel */ | ||
79 | }, | 105 | }, |
80 | {}, | ||
81 | }; | 106 | }; |
82 | #endif | 107 | #endif |
83 | 108 | ||
109 | static bool s2mpa01_volatile(struct device *dev, unsigned int reg) | ||
110 | { | ||
111 | switch (reg) { | ||
112 | case S2MPA01_REG_INT1M: | ||
113 | case S2MPA01_REG_INT2M: | ||
114 | case S2MPA01_REG_INT3M: | ||
115 | return false; | ||
116 | default: | ||
117 | return true; | ||
118 | } | ||
119 | } | ||
120 | |||
84 | static bool s2mps11_volatile(struct device *dev, unsigned int reg) | 121 | static bool s2mps11_volatile(struct device *dev, unsigned int reg) |
85 | { | 122 | { |
86 | switch (reg) { | 123 | switch (reg) { |
@@ -111,6 +148,15 @@ static const struct regmap_config sec_regmap_config = { | |||
111 | .val_bits = 8, | 148 | .val_bits = 8, |
112 | }; | 149 | }; |
113 | 150 | ||
151 | static const struct regmap_config s2mpa01_regmap_config = { | ||
152 | .reg_bits = 8, | ||
153 | .val_bits = 8, | ||
154 | |||
155 | .max_register = S2MPA01_REG_LDO_OVCB4, | ||
156 | .volatile_reg = s2mpa01_volatile, | ||
157 | .cache_type = REGCACHE_FLAT, | ||
158 | }; | ||
159 | |||
114 | static const struct regmap_config s2mps11_regmap_config = { | 160 | static const struct regmap_config s2mps11_regmap_config = { |
115 | .reg_bits = 8, | 161 | .reg_bits = 8, |
116 | .val_bits = 8, | 162 | .val_bits = 8, |
@@ -120,6 +166,15 @@ static const struct regmap_config s2mps11_regmap_config = { | |||
120 | .cache_type = REGCACHE_FLAT, | 166 | .cache_type = REGCACHE_FLAT, |
121 | }; | 167 | }; |
122 | 168 | ||
169 | static const struct regmap_config s2mps14_regmap_config = { | ||
170 | .reg_bits = 8, | ||
171 | .val_bits = 8, | ||
172 | |||
173 | .max_register = S2MPS14_REG_LDODSCH3, | ||
174 | .volatile_reg = s2mps11_volatile, | ||
175 | .cache_type = REGCACHE_FLAT, | ||
176 | }; | ||
177 | |||
123 | static const struct regmap_config s5m8763_regmap_config = { | 178 | static const struct regmap_config s5m8763_regmap_config = { |
124 | .reg_bits = 8, | 179 | .reg_bits = 8, |
125 | .val_bits = 8, | 180 | .val_bits = 8, |
@@ -138,9 +193,18 @@ static const struct regmap_config s5m8767_regmap_config = { | |||
138 | .cache_type = REGCACHE_FLAT, | 193 | .cache_type = REGCACHE_FLAT, |
139 | }; | 194 | }; |
140 | 195 | ||
141 | static const struct regmap_config sec_rtc_regmap_config = { | 196 | static const struct regmap_config s5m_rtc_regmap_config = { |
197 | .reg_bits = 8, | ||
198 | .val_bits = 8, | ||
199 | |||
200 | .max_register = SEC_RTC_REG_MAX, | ||
201 | }; | ||
202 | |||
203 | static const struct regmap_config s2mps14_rtc_regmap_config = { | ||
142 | .reg_bits = 8, | 204 | .reg_bits = 8, |
143 | .val_bits = 8, | 205 | .val_bits = 8, |
206 | |||
207 | .max_register = S2MPS_RTC_REG_MAX, | ||
144 | }; | 208 | }; |
145 | 209 | ||
146 | #ifdef CONFIG_OF | 210 | #ifdef CONFIG_OF |
@@ -180,24 +244,24 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( | |||
180 | } | 244 | } |
181 | #endif | 245 | #endif |
182 | 246 | ||
183 | static inline int sec_i2c_get_driver_data(struct i2c_client *i2c, | 247 | static inline unsigned long sec_i2c_get_driver_data(struct i2c_client *i2c, |
184 | const struct i2c_device_id *id) | 248 | const struct i2c_device_id *id) |
185 | { | 249 | { |
186 | #ifdef CONFIG_OF | 250 | #ifdef CONFIG_OF |
187 | if (i2c->dev.of_node) { | 251 | if (i2c->dev.of_node) { |
188 | const struct of_device_id *match; | 252 | const struct of_device_id *match; |
189 | match = of_match_node(sec_dt_match, i2c->dev.of_node); | 253 | match = of_match_node(sec_dt_match, i2c->dev.of_node); |
190 | return (int)match->data; | 254 | return (unsigned long)match->data; |
191 | } | 255 | } |
192 | #endif | 256 | #endif |
193 | return (int)id->driver_data; | 257 | return id->driver_data; |
194 | } | 258 | } |
195 | 259 | ||
196 | static int sec_pmic_probe(struct i2c_client *i2c, | 260 | static int sec_pmic_probe(struct i2c_client *i2c, |
197 | const struct i2c_device_id *id) | 261 | const struct i2c_device_id *id) |
198 | { | 262 | { |
199 | struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev); | 263 | struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev); |
200 | const struct regmap_config *regmap; | 264 | const struct regmap_config *regmap, *regmap_rtc; |
201 | struct sec_pmic_dev *sec_pmic; | 265 | struct sec_pmic_dev *sec_pmic; |
202 | int ret; | 266 | int ret; |
203 | 267 | ||
@@ -229,17 +293,34 @@ static int sec_pmic_probe(struct i2c_client *i2c, | |||
229 | } | 293 | } |
230 | 294 | ||
231 | switch (sec_pmic->device_type) { | 295 | switch (sec_pmic->device_type) { |
296 | case S2MPA01: | ||
297 | regmap = &s2mpa01_regmap_config; | ||
298 | break; | ||
232 | case S2MPS11X: | 299 | case S2MPS11X: |
233 | regmap = &s2mps11_regmap_config; | 300 | regmap = &s2mps11_regmap_config; |
301 | /* | ||
302 | * The rtc-s5m driver does not support S2MPS11 and there | ||
303 | * is no mfd_cell for S2MPS11 RTC device. | ||
304 | * However we must pass something to devm_regmap_init_i2c() | ||
305 | * so use S5M-like regmap config even though it wouldn't work. | ||
306 | */ | ||
307 | regmap_rtc = &s5m_rtc_regmap_config; | ||
308 | break; | ||
309 | case S2MPS14X: | ||
310 | regmap = &s2mps14_regmap_config; | ||
311 | regmap_rtc = &s2mps14_rtc_regmap_config; | ||
234 | break; | 312 | break; |
235 | case S5M8763X: | 313 | case S5M8763X: |
236 | regmap = &s5m8763_regmap_config; | 314 | regmap = &s5m8763_regmap_config; |
315 | regmap_rtc = &s5m_rtc_regmap_config; | ||
237 | break; | 316 | break; |
238 | case S5M8767X: | 317 | case S5M8767X: |
239 | regmap = &s5m8767_regmap_config; | 318 | regmap = &s5m8767_regmap_config; |
319 | regmap_rtc = &s5m_rtc_regmap_config; | ||
240 | break; | 320 | break; |
241 | default: | 321 | default: |
242 | regmap = &sec_regmap_config; | 322 | regmap = &sec_regmap_config; |
323 | regmap_rtc = &s5m_rtc_regmap_config; | ||
243 | break; | 324 | break; |
244 | } | 325 | } |
245 | 326 | ||
@@ -252,10 +333,13 @@ static int sec_pmic_probe(struct i2c_client *i2c, | |||
252 | } | 333 | } |
253 | 334 | ||
254 | sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); | 335 | sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); |
336 | if (!sec_pmic->rtc) { | ||
337 | dev_err(&i2c->dev, "Failed to allocate I2C for RTC\n"); | ||
338 | return -ENODEV; | ||
339 | } | ||
255 | i2c_set_clientdata(sec_pmic->rtc, sec_pmic); | 340 | i2c_set_clientdata(sec_pmic->rtc, sec_pmic); |
256 | 341 | ||
257 | sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, | 342 | sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, regmap_rtc); |
258 | &sec_rtc_regmap_config); | ||
259 | if (IS_ERR(sec_pmic->regmap_rtc)) { | 343 | if (IS_ERR(sec_pmic->regmap_rtc)) { |
260 | ret = PTR_ERR(sec_pmic->regmap_rtc); | 344 | ret = PTR_ERR(sec_pmic->regmap_rtc); |
261 | dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n", | 345 | dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n", |
@@ -283,10 +367,18 @@ static int sec_pmic_probe(struct i2c_client *i2c, | |||
283 | ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, | 367 | ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, |
284 | ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL); | 368 | ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL); |
285 | break; | 369 | break; |
370 | case S2MPA01: | ||
371 | ret = mfd_add_devices(sec_pmic->dev, -1, s2mpa01_devs, | ||
372 | ARRAY_SIZE(s2mpa01_devs), NULL, 0, NULL); | ||
373 | break; | ||
286 | case S2MPS11X: | 374 | case S2MPS11X: |
287 | ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, | 375 | ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, |
288 | ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL); | 376 | ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL); |
289 | break; | 377 | break; |
378 | case S2MPS14X: | ||
379 | ret = mfd_add_devices(sec_pmic->dev, -1, s2mps14_devs, | ||
380 | ARRAY_SIZE(s2mps14_devs), NULL, 0, NULL); | ||
381 | break; | ||
290 | default: | 382 | default: |
291 | /* If this happens the probe function is problem */ | 383 | /* If this happens the probe function is problem */ |
292 | BUG(); | 384 | BUG(); |
@@ -315,6 +407,7 @@ static int sec_pmic_remove(struct i2c_client *i2c) | |||
315 | return 0; | 407 | return 0; |
316 | } | 408 | } |
317 | 409 | ||
410 | #ifdef CONFIG_PM_SLEEP | ||
318 | static int sec_pmic_suspend(struct device *dev) | 411 | static int sec_pmic_suspend(struct device *dev) |
319 | { | 412 | { |
320 | struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); | 413 | struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); |
@@ -349,6 +442,7 @@ static int sec_pmic_resume(struct device *dev) | |||
349 | 442 | ||
350 | return 0; | 443 | return 0; |
351 | } | 444 | } |
445 | #endif /* CONFIG_PM_SLEEP */ | ||
352 | 446 | ||
353 | static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume); | 447 | static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume); |
354 | 448 | ||