OSDN Git Service

Merge "ARM: dts: msm: Add support for MSM8996 Mizar platform"
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / drivers / of / of_slimbus.c
1 /* Copyright (c) 2012, The Linux Foundation. All rights reserved.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 and
5  * only version 2 as published by the Free Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  */
12
13 /* OF helpers for SLIMbus */
14 #include <linux/slimbus/slimbus.h>
15 #include <linux/irq.h>
16 #include <linux/slab.h>
17 #include <linux/of.h>
18 #include <linux/of_irq.h>
19 #include <linux/of_slimbus.h>
20
21 int of_register_slim_devices(struct slim_controller *ctrl)
22 {
23         struct device_node *node;
24         struct slim_boardinfo *binfo = NULL;
25         struct slim_boardinfo *temp;
26         int n = 0;
27         int ret = 0;
28
29         if (!ctrl->dev.of_node)
30                 return -EINVAL;
31
32         for_each_child_of_node(ctrl->dev.of_node, node) {
33                 struct property *prop;
34                 struct slim_device *slim;
35                 char *name;
36                 prop = of_find_property(node, "elemental-addr", NULL);
37                 if (!prop || prop->length != 6) {
38                         dev_err(&ctrl->dev, "of_slim: invalid E-addr");
39                         continue;
40                 }
41                 name = kzalloc(SLIMBUS_NAME_SIZE, GFP_KERNEL);
42                 if (!name) {
43                         dev_err(&ctrl->dev, "of_slim: out of memory");
44                         ret = -ENOMEM;
45                         goto of_slim_err;
46                 }
47                 if (of_modalias_node(node, name, SLIMBUS_NAME_SIZE) < 0) {
48                         dev_err(&ctrl->dev, "of_slim: modalias failure on %s\n",
49                                 node->full_name);
50                         kfree(name);
51                         continue;
52                 }
53                 slim = kzalloc(sizeof(struct slim_device), GFP_KERNEL);
54                 if (!slim) {
55                         dev_err(&ctrl->dev, "of_slim: out of memory");
56                         ret = -ENOMEM;
57                         kfree(name);
58                         goto of_slim_err;
59                 }
60                 memcpy(slim->e_addr, prop->value, 6);
61
62                 temp = krealloc(binfo, (n + 1) * sizeof(struct slim_boardinfo),
63                                         GFP_KERNEL);
64                 if (!temp) {
65                         dev_err(&ctrl->dev, "out of memory");
66                         kfree(name);
67                         kfree(slim);
68                         ret = -ENOMEM;
69                         goto of_slim_err;
70                 }
71                 binfo = temp;
72
73                 slim->dev.of_node = of_node_get(node);
74                 slim->name = (const char *)name;
75                 binfo[n].bus_num = ctrl->nr;
76                 binfo[n].slim_slave = slim;
77                 n++;
78         }
79         ret = slim_register_board_info(binfo, n);
80         if (!ret)
81                 goto of_slim_ret;
82 of_slim_err:
83         while (n-- > 0) {
84                 kfree(binfo[n].slim_slave->name);
85                 kfree(binfo[n].slim_slave);
86         }
87 of_slim_ret:
88         kfree(binfo);
89         return ret;
90 }