diff options
-rw-r--r-- | Documentation/devicetree/bindings/arm/msm/ssbi.txt | 18 | ||||
-rw-r--r-- | arch/arm/boot/dts/msm8660-surf.dts | 6 | ||||
-rw-r--r-- | arch/arm/boot/dts/msm8960-cdp.dts | 6 | ||||
-rw-r--r-- | drivers/ssbi/ssbi.c | 81 |
4 files changed, 62 insertions, 49 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/ssbi.txt b/Documentation/devicetree/bindings/arm/msm/ssbi.txt new file mode 100644 index 000000000000..54fd5ced3401 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/msm/ssbi.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | * Qualcomm SSBI | ||
2 | |||
3 | Some Qualcomm MSM devices contain a point-to-point serial bus used to | ||
4 | communicate with a limited range of devices (mostly power management | ||
5 | chips). | ||
6 | |||
7 | These require the following properties: | ||
8 | |||
9 | - compatible: "qcom,ssbi" | ||
10 | |||
11 | - qcom,controller-type | ||
12 | indicates the SSBI bus variant the controller should use to talk | ||
13 | with the slave device. This should be one of "ssbi", "ssbi2", or | ||
14 | "pmic-arbiter". The type chosen is determined by the attached | ||
15 | slave. | ||
16 | |||
17 | The slave device should be the single child node of the ssbi device | ||
18 | with a compatible field. | ||
diff --git a/arch/arm/boot/dts/msm8660-surf.dts b/arch/arm/boot/dts/msm8660-surf.dts index 31f2157cd7d7..67f8670c4d6a 100644 --- a/arch/arm/boot/dts/msm8660-surf.dts +++ b/arch/arm/boot/dts/msm8660-surf.dts | |||
@@ -38,4 +38,10 @@ | |||
38 | <0x19c00000 0x1000>; | 38 | <0x19c00000 0x1000>; |
39 | interrupts = <0 195 0x0>; | 39 | interrupts = <0 195 0x0>; |
40 | }; | 40 | }; |
41 | |||
42 | qcom,ssbi@500000 { | ||
43 | compatible = "qcom,ssbi"; | ||
44 | reg = <0x500000 0x1000>; | ||
45 | qcom,controller-type = "pmic-arbiter"; | ||
46 | }; | ||
41 | }; | 47 | }; |
diff --git a/arch/arm/boot/dts/msm8960-cdp.dts b/arch/arm/boot/dts/msm8960-cdp.dts index 9e621b5ad3dd..c9b09a813a4b 100644 --- a/arch/arm/boot/dts/msm8960-cdp.dts +++ b/arch/arm/boot/dts/msm8960-cdp.dts | |||
@@ -38,4 +38,10 @@ | |||
38 | <0x16400000 0x1000>; | 38 | <0x16400000 0x1000>; |
39 | interrupts = <0 154 0x0>; | 39 | interrupts = <0 154 0x0>; |
40 | }; | 40 | }; |
41 | |||
42 | qcom,ssbi@500000 { | ||
43 | compatible = "qcom,ssbi"; | ||
44 | reg = <0x500000 0x1000>; | ||
45 | qcom,controller-type = "pmic-arbiter"; | ||
46 | }; | ||
41 | }; | 47 | }; |
diff --git a/drivers/ssbi/ssbi.c b/drivers/ssbi/ssbi.c index da086d49d35c..6fbcb25907ff 100644 --- a/drivers/ssbi/ssbi.c +++ b/drivers/ssbi/ssbi.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/msm_ssbi.h> | 27 | #include <linux/msm_ssbi.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/of.h> | ||
30 | #include <linux/of_device.h> | ||
29 | 31 | ||
30 | /* SSBI 2.0 controller registers */ | 32 | /* SSBI 2.0 controller registers */ |
31 | #define SSBI2_CMD 0x0008 | 33 | #define SSBI2_CMD 0x0008 |
@@ -261,56 +263,13 @@ int msm_ssbi_write(struct device *dev, u16 addr, u8 *buf, int len) | |||
261 | } | 263 | } |
262 | EXPORT_SYMBOL_GPL(msm_ssbi_write); | 264 | EXPORT_SYMBOL_GPL(msm_ssbi_write); |
263 | 265 | ||
264 | static int msm_ssbi_add_slave(struct msm_ssbi *ssbi, | ||
265 | const struct msm_ssbi_slave_info *slave) | ||
266 | { | ||
267 | struct platform_device *slave_pdev; | ||
268 | int ret; | ||
269 | |||
270 | if (ssbi->slave) { | ||
271 | pr_err("slave already attached??\n"); | ||
272 | return -EBUSY; | ||
273 | } | ||
274 | |||
275 | slave_pdev = platform_device_alloc(slave->name, -1); | ||
276 | if (!slave_pdev) { | ||
277 | pr_err("cannot allocate pdev for slave '%s'", slave->name); | ||
278 | ret = -ENOMEM; | ||
279 | goto err; | ||
280 | } | ||
281 | |||
282 | slave_pdev->dev.parent = ssbi->dev; | ||
283 | slave_pdev->dev.platform_data = slave->platform_data; | ||
284 | |||
285 | ret = platform_device_add(slave_pdev); | ||
286 | if (ret) { | ||
287 | pr_err("cannot add slave platform device for '%s'\n", | ||
288 | slave->name); | ||
289 | goto err; | ||
290 | } | ||
291 | |||
292 | ssbi->slave = &slave_pdev->dev; | ||
293 | return 0; | ||
294 | |||
295 | err: | ||
296 | if (slave_pdev) | ||
297 | platform_device_put(slave_pdev); | ||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | static int msm_ssbi_probe(struct platform_device *pdev) | 266 | static int msm_ssbi_probe(struct platform_device *pdev) |
302 | { | 267 | { |
303 | const struct msm_ssbi_platform_data *pdata = pdev->dev.platform_data; | 268 | struct device_node *np = pdev->dev.of_node; |
304 | struct resource *mem_res; | 269 | struct resource *mem_res; |
305 | struct msm_ssbi *ssbi; | 270 | struct msm_ssbi *ssbi; |
306 | int ret = 0; | 271 | int ret = 0; |
307 | 272 | const char *type; | |
308 | if (!pdata) { | ||
309 | pr_err("missing platform data\n"); | ||
310 | return -EINVAL; | ||
311 | } | ||
312 | |||
313 | pr_debug("%s\n", pdata->slave.name); | ||
314 | 273 | ||
315 | ssbi = kzalloc(sizeof(struct msm_ssbi), GFP_KERNEL); | 274 | ssbi = kzalloc(sizeof(struct msm_ssbi), GFP_KERNEL); |
316 | if (!ssbi) { | 275 | if (!ssbi) { |
@@ -334,7 +293,25 @@ static int msm_ssbi_probe(struct platform_device *pdev) | |||
334 | ssbi->dev = &pdev->dev; | 293 | ssbi->dev = &pdev->dev; |
335 | platform_set_drvdata(pdev, ssbi); | 294 | platform_set_drvdata(pdev, ssbi); |
336 | 295 | ||
337 | ssbi->controller_type = pdata->controller_type; | 296 | type = of_get_property(np, "qcom,controller-type", NULL); |
297 | if (type == NULL) { | ||
298 | pr_err("Missing qcom,controller-type property\n"); | ||
299 | ret = -EINVAL; | ||
300 | goto err_ssbi_controller; | ||
301 | } | ||
302 | dev_info(&pdev->dev, "SSBI controller type: '%s'\n", type); | ||
303 | if (strcmp(type, "ssbi") == 0) | ||
304 | ssbi->controller_type = MSM_SBI_CTRL_SSBI; | ||
305 | else if (strcmp(type, "ssbi2") == 0) | ||
306 | ssbi->controller_type = MSM_SBI_CTRL_SSBI2; | ||
307 | else if (strcmp(type, "pmic-arbiter") == 0) | ||
308 | ssbi->controller_type = MSM_SBI_CTRL_PMIC_ARBITER; | ||
309 | else { | ||
310 | pr_err("Unknown qcom,controller-type\n"); | ||
311 | ret = -EINVAL; | ||
312 | goto err_ssbi_controller; | ||
313 | } | ||
314 | |||
338 | if (ssbi->controller_type == MSM_SBI_CTRL_PMIC_ARBITER) { | 315 | if (ssbi->controller_type == MSM_SBI_CTRL_PMIC_ARBITER) { |
339 | ssbi->read = msm_ssbi_pa_read_bytes; | 316 | ssbi->read = msm_ssbi_pa_read_bytes; |
340 | ssbi->write = msm_ssbi_pa_write_bytes; | 317 | ssbi->write = msm_ssbi_pa_write_bytes; |
@@ -345,13 +322,13 @@ static int msm_ssbi_probe(struct platform_device *pdev) | |||
345 | 322 | ||
346 | spin_lock_init(&ssbi->lock); | 323 | spin_lock_init(&ssbi->lock); |
347 | 324 | ||
348 | ret = msm_ssbi_add_slave(ssbi, &pdata->slave); | 325 | ret = of_platform_populate(np, NULL, NULL, &pdev->dev); |
349 | if (ret) | 326 | if (ret) |
350 | goto err_ssbi_add_slave; | 327 | goto err_ssbi_controller; |
351 | 328 | ||
352 | return 0; | 329 | return 0; |
353 | 330 | ||
354 | err_ssbi_add_slave: | 331 | err_ssbi_controller: |
355 | platform_set_drvdata(pdev, NULL); | 332 | platform_set_drvdata(pdev, NULL); |
356 | iounmap(ssbi->base); | 333 | iounmap(ssbi->base); |
357 | err_ioremap: | 334 | err_ioremap: |
@@ -370,12 +347,18 @@ static int msm_ssbi_remove(struct platform_device *pdev) | |||
370 | return 0; | 347 | return 0; |
371 | } | 348 | } |
372 | 349 | ||
350 | static struct of_device_id ssbi_match_table[] = { | ||
351 | { .compatible = "qcom,ssbi" }, | ||
352 | {} | ||
353 | }; | ||
354 | |||
373 | static struct platform_driver msm_ssbi_driver = { | 355 | static struct platform_driver msm_ssbi_driver = { |
374 | .probe = msm_ssbi_probe, | 356 | .probe = msm_ssbi_probe, |
375 | .remove = msm_ssbi_remove, | 357 | .remove = msm_ssbi_remove, |
376 | .driver = { | 358 | .driver = { |
377 | .name = "msm_ssbi", | 359 | .name = "msm_ssbi", |
378 | .owner = THIS_MODULE, | 360 | .owner = THIS_MODULE, |
361 | .of_match_table = ssbi_match_table, | ||
379 | }, | 362 | }, |
380 | }; | 363 | }; |
381 | 364 | ||