diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-02-19 07:43:08 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-02-19 07:43:08 -0500 |
commit | 178a097d5e6ae57d67310ff18bef0afb5589f2dd (patch) | |
tree | f64a80af7069b46bea3f55c5f2d90e9881565a36 /drivers/mfd | |
parent | 728088871c867f912f8a33ea049b7c4135c95637 (diff) | |
parent | e81d7bc89c9623ea000890fb4cdf7e731dc21f71 (diff) |
Merge remote-tracking branch 'regulator/topic/s5m8767' into regulator-next
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/sec-core.c | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 49d361a618d0..77ee26ef5941 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/of_irq.h> | ||
20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
21 | #include <linux/pm_runtime.h> | 22 | #include <linux/pm_runtime.h> |
22 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
@@ -60,6 +61,15 @@ static struct mfd_cell s2mps11_devs[] = { | |||
60 | }, | 61 | }, |
61 | }; | 62 | }; |
62 | 63 | ||
64 | #ifdef CONFIG_OF | ||
65 | static struct of_device_id sec_dt_match[] = { | ||
66 | { .compatible = "samsung,s5m8767-pmic", | ||
67 | .data = (void *)S5M8767X, | ||
68 | }, | ||
69 | {}, | ||
70 | }; | ||
71 | #endif | ||
72 | |||
63 | int sec_reg_read(struct sec_pmic_dev *sec_pmic, u8 reg, void *dest) | 73 | int sec_reg_read(struct sec_pmic_dev *sec_pmic, u8 reg, void *dest) |
64 | { | 74 | { |
65 | return regmap_read(sec_pmic->regmap, reg, dest); | 75 | return regmap_read(sec_pmic->regmap, reg, dest); |
@@ -95,6 +105,57 @@ static struct regmap_config sec_regmap_config = { | |||
95 | .val_bits = 8, | 105 | .val_bits = 8, |
96 | }; | 106 | }; |
97 | 107 | ||
108 | |||
109 | #ifdef CONFIG_OF | ||
110 | /* | ||
111 | * Only the common platform data elements for s5m8767 are parsed here from the | ||
112 | * device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and | ||
113 | * others have to parse their own platform data elements from device tree. | ||
114 | * | ||
115 | * The s5m8767 platform data structure is instantiated here and the drivers for | ||
116 | * the sub-modules need not instantiate another instance while parsing their | ||
117 | * platform data. | ||
118 | */ | ||
119 | static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( | ||
120 | struct device *dev) | ||
121 | { | ||
122 | struct sec_platform_data *pd; | ||
123 | |||
124 | pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); | ||
125 | if (!pd) { | ||
126 | dev_err(dev, "could not allocate memory for pdata\n"); | ||
127 | return ERR_PTR(-ENOMEM); | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * ToDo: the 'wakeup' member in the platform data is more of a linux | ||
132 | * specfic information. Hence, there is no binding for that yet and | ||
133 | * not parsed here. | ||
134 | */ | ||
135 | |||
136 | return pd; | ||
137 | } | ||
138 | #else | ||
139 | static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( | ||
140 | struct device *dev) | ||
141 | { | ||
142 | return 0; | ||
143 | } | ||
144 | #endif | ||
145 | |||
146 | static inline int sec_i2c_get_driver_data(struct i2c_client *i2c, | ||
147 | const struct i2c_device_id *id) | ||
148 | { | ||
149 | #ifdef CONFIG_OF | ||
150 | if (i2c->dev.of_node) { | ||
151 | const struct of_device_id *match; | ||
152 | match = of_match_node(sec_dt_match, i2c->dev.of_node); | ||
153 | return (int)match->data; | ||
154 | } | ||
155 | #endif | ||
156 | return (int)id->driver_data; | ||
157 | } | ||
158 | |||
98 | static int sec_pmic_probe(struct i2c_client *i2c, | 159 | static int sec_pmic_probe(struct i2c_client *i2c, |
99 | const struct i2c_device_id *id) | 160 | const struct i2c_device_id *id) |
100 | { | 161 | { |
@@ -111,13 +172,22 @@ static int sec_pmic_probe(struct i2c_client *i2c, | |||
111 | sec_pmic->dev = &i2c->dev; | 172 | sec_pmic->dev = &i2c->dev; |
112 | sec_pmic->i2c = i2c; | 173 | sec_pmic->i2c = i2c; |
113 | sec_pmic->irq = i2c->irq; | 174 | sec_pmic->irq = i2c->irq; |
114 | sec_pmic->type = id->driver_data; | 175 | sec_pmic->type = sec_i2c_get_driver_data(i2c, id); |
115 | 176 | ||
177 | if (sec_pmic->dev->of_node) { | ||
178 | pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev); | ||
179 | if (IS_ERR(pdata)) { | ||
180 | ret = PTR_ERR(pdata); | ||
181 | return ret; | ||
182 | } | ||
183 | pdata->device_type = sec_pmic->type; | ||
184 | } | ||
116 | if (pdata) { | 185 | if (pdata) { |
117 | sec_pmic->device_type = pdata->device_type; | 186 | sec_pmic->device_type = pdata->device_type; |
118 | sec_pmic->ono = pdata->ono; | 187 | sec_pmic->ono = pdata->ono; |
119 | sec_pmic->irq_base = pdata->irq_base; | 188 | sec_pmic->irq_base = pdata->irq_base; |
120 | sec_pmic->wakeup = pdata->wakeup; | 189 | sec_pmic->wakeup = pdata->wakeup; |
190 | sec_pmic->pdata = pdata; | ||
121 | } | 191 | } |
122 | 192 | ||
123 | sec_pmic->regmap = devm_regmap_init_i2c(i2c, &sec_regmap_config); | 193 | sec_pmic->regmap = devm_regmap_init_i2c(i2c, &sec_regmap_config); |
@@ -192,6 +262,7 @@ static struct i2c_driver sec_pmic_driver = { | |||
192 | .driver = { | 262 | .driver = { |
193 | .name = "sec_pmic", | 263 | .name = "sec_pmic", |
194 | .owner = THIS_MODULE, | 264 | .owner = THIS_MODULE, |
265 | .of_match_table = of_match_ptr(sec_dt_match), | ||
195 | }, | 266 | }, |
196 | .probe = sec_pmic_probe, | 267 | .probe = sec_pmic_probe, |
197 | .remove = sec_pmic_remove, | 268 | .remove = sec_pmic_remove, |