blob: 3c51297fcac1204a60587d02439ac354304043fd [file] [log] [blame]
Duy Truong790f06d2013-02-13 16:38:12 -08001/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
Michael Bohan86e30dc2012-01-05 14:16:43 -08002 *
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#include <linux/spmi.h>
14#include <linux/irq.h>
15#include <linux/of.h>
16#include <linux/of_address.h>
17#include <linux/of_irq.h>
18#include <linux/of_spmi.h>
19#include <linux/slab.h>
20#include <linux/module.h>
Michael Bohan86622b32012-02-08 16:59:00 -080021#include <linux/types.h>
Michael Bohan86e30dc2012-01-05 14:16:43 -080022
Michael Bohan11926c92012-02-08 11:01:24 -080023struct of_spmi_dev_info {
24 struct spmi_controller *ctrl;
25 struct spmi_boardinfo b_info;
26};
27
28struct of_spmi_res_info {
29 struct device_node *node;
30 uint32_t num_reg;
31 uint32_t num_irq;
32};
33
Michael Bohan86622b32012-02-08 16:59:00 -080034/*
35 * Initialize r_info structure for safe usage
36 */
37static inline void of_spmi_init_resource(struct of_spmi_res_info *r_info,
38 struct device_node *node)
39{
40 r_info->node = node;
41 r_info->num_reg = 0;
42 r_info->num_irq = 0;
43}
44
45/*
Michael Bohan86622b32012-02-08 16:59:00 -080046 * Calculate the number of resources to allocate
47 *
48 * The caller is responsible for initializing the of_spmi_res_info structure.
49 */
Michael Bohan978d3352012-05-25 15:02:38 -070050static void of_spmi_sum_resources(struct of_spmi_res_info *r_info,
51 bool has_reg)
Michael Bohan86e30dc2012-01-05 14:16:43 -080052{
Michael Bohan11926c92012-02-08 11:01:24 -080053 struct of_irq oirq;
Michael Bohan86e30dc2012-01-05 14:16:43 -080054 uint64_t size;
55 uint32_t flags;
Michael Bohan86622b32012-02-08 16:59:00 -080056 int i = 0;
Michael Bohan11926c92012-02-08 11:01:24 -080057
Michael Bohan86622b32012-02-08 16:59:00 -080058 while (of_irq_map_one(r_info->node, i, &oirq) == 0)
59 i++;
60
61 r_info->num_irq += i;
Michael Bohan11926c92012-02-08 11:01:24 -080062
63 if (!has_reg)
64 return;
65
66 /*
67 * We can't use of_address_to_resource here since it includes
68 * address translation; and address translation assumes that no
69 * parent buses have a size-cell of 0. But SPMI does have a
70 * size-cell of 0.
71 */
Michael Bohan86622b32012-02-08 16:59:00 -080072 i = 0;
73 while (of_get_address(r_info->node, i, &size, &flags) != NULL)
74 i++;
75
76 r_info->num_reg += i;
Michael Bohan11926c92012-02-08 11:01:24 -080077}
78
Michael Bohan86622b32012-02-08 16:59:00 -080079/*
Michael Bohan978d3352012-05-25 15:02:38 -070080 * Allocate dev_node array for spmi_device - used with spmi-dev-container
Michael Bohan11926c92012-02-08 11:01:24 -080081 */
Michael Bohan978d3352012-05-25 15:02:38 -070082static inline int of_spmi_alloc_devnode_store(struct of_spmi_dev_info *d_info,
83 uint32_t num_dev_node)
84{
85 d_info->b_info.num_dev_node = num_dev_node;
86 d_info->b_info.dev_node = kzalloc(sizeof(struct spmi_resource) *
87 num_dev_node, GFP_KERNEL);
88 if (!d_info->b_info.dev_node)
89 return -ENOMEM;
90
91 return 0;
92}
93
94/*
95 * Allocate enough memory to handle the resources associated with the
96 * primary node.
97 */
98static int of_spmi_allocate_node_resources(struct of_spmi_dev_info *d_info,
99 struct of_spmi_res_info *r_info)
100{
101 uint32_t num_irq = r_info->num_irq, num_reg = r_info->num_reg;
102 struct resource *res = NULL;
103
104 if (num_irq || num_reg) {
105 res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
106 if (!res)
107 return -ENOMEM;
108 }
109 d_info->b_info.res.num_resources = num_reg + num_irq;
110 d_info->b_info.res.resource = res;
111
112 return 0;
113}
114
115/*
116 * Allocate enough memory to handle the resources associated with the
117 * spmi-dev-container nodes.
118 */
119static int of_spmi_allocate_devnode_resources(struct of_spmi_dev_info *d_info,
120 struct of_spmi_res_info *r_info,
121 uint32_t idx)
122{
123 uint32_t num_irq = r_info->num_irq, num_reg = r_info->num_reg;
124 struct resource *res = NULL;
125
126 if (num_irq || num_reg) {
127 res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
128 if (!res)
129 return -ENOMEM;
130 }
131 d_info->b_info.dev_node[idx].num_resources = num_reg + num_irq;
132 d_info->b_info.dev_node[idx].resource = res;
133
134 return 0;
135}
136
137/*
138 * free node resources - used with primary node
139 */
140static void of_spmi_free_node_resources(struct of_spmi_dev_info *d_info)
141{
142 kfree(d_info->b_info.res.resource);
143}
144
145/*
146 * free devnode resources - used with spmi-dev-container
147 */
148static void of_spmi_free_devnode_resources(struct of_spmi_dev_info *d_info)
Michael Bohan86622b32012-02-08 16:59:00 -0800149{
150 int i;
151
152 for (i = 0; i < d_info->b_info.num_dev_node; i++)
153 kfree(d_info->b_info.dev_node[i].resource);
154
155 kfree(d_info->b_info.dev_node);
156}
157
Michael Bohan978d3352012-05-25 15:02:38 -0700158static void of_spmi_populate_resources(struct of_spmi_dev_info *d_info,
159 struct of_spmi_res_info *r_info,
160 struct resource *res)
Michael Bohan11926c92012-02-08 11:01:24 -0800161
162{
163 uint32_t num_irq = r_info->num_irq, num_reg = r_info->num_reg;
164 int i;
Michael Bohan86e30dc2012-01-05 14:16:43 -0800165 const __be32 *addrp;
Michael Bohan11926c92012-02-08 11:01:24 -0800166 uint64_t size;
167 uint32_t flags;
Michael Bohan86e30dc2012-01-05 14:16:43 -0800168
Michael Bohan86622b32012-02-08 16:59:00 -0800169 if ((num_irq || num_reg) && (res != NULL)) {
Michael Bohan86e30dc2012-01-05 14:16:43 -0800170 for (i = 0; i < num_reg; i++, res++) {
171 /* Addresses are always 16 bits */
Michael Bohan11926c92012-02-08 11:01:24 -0800172 addrp = of_get_address(r_info->node, i, &size, &flags);
Michael Bohan86e30dc2012-01-05 14:16:43 -0800173 BUG_ON(!addrp);
174 res->start = be32_to_cpup(addrp);
175 res->end = res->start + size - 1;
176 res->flags = flags;
Michael Bohana6a354d2012-05-21 17:47:11 -0700177 of_property_read_string_index(r_info->node, "reg-names",
178 i, &res->name);
Michael Bohan86e30dc2012-01-05 14:16:43 -0800179 }
Michael Bohan11926c92012-02-08 11:01:24 -0800180 WARN_ON(of_irq_to_resource_table(r_info->node, res, num_irq) !=
Michael Bohan86e30dc2012-01-05 14:16:43 -0800181 num_irq);
182 }
Michael Bohan86622b32012-02-08 16:59:00 -0800183}
184
185/*
Michael Bohan978d3352012-05-25 15:02:38 -0700186 * Gather primary node resources and populate.
Michael Bohan86622b32012-02-08 16:59:00 -0800187 */
Michael Bohan978d3352012-05-25 15:02:38 -0700188static void of_spmi_populate_node_resources(struct of_spmi_dev_info *d_info,
189 struct of_spmi_res_info *r_info)
190
Michael Bohan86622b32012-02-08 16:59:00 -0800191{
Michael Bohan978d3352012-05-25 15:02:38 -0700192 struct resource *res;
Michael Bohan86622b32012-02-08 16:59:00 -0800193
Michael Bohan978d3352012-05-25 15:02:38 -0700194 res = d_info->b_info.res.resource;
195 d_info->b_info.res.of_node = r_info->node;
196 of_property_read_string(r_info->node, "label",
197 &d_info->b_info.res.label);
198 of_spmi_populate_resources(d_info, r_info, res);
199}
Michael Bohan86e30dc2012-01-05 14:16:43 -0800200
Michael Bohan978d3352012-05-25 15:02:38 -0700201/*
202 * Gather node devnode resources and populate - used with spmi-dev-container.
203 */
204static void of_spmi_populate_devnode_resources(struct of_spmi_dev_info *d_info,
205 struct of_spmi_res_info *r_info,
206 int idx)
207
208{
209 struct resource *res;
210
211 res = d_info->b_info.dev_node[idx].resource;
212 d_info->b_info.dev_node[idx].of_node = r_info->node;
213 of_property_read_string(r_info->node, "label",
214 &d_info->b_info.dev_node[idx].label);
215 of_spmi_populate_resources(d_info, r_info, res);
Michael Bohan86e30dc2012-01-05 14:16:43 -0800216}
217
Michael Bohan86622b32012-02-08 16:59:00 -0800218/*
219 * create a single spmi_device
220 */
Michael Bohan11926c92012-02-08 11:01:24 -0800221static int of_spmi_create_device(struct of_spmi_dev_info *d_info,
222 struct device_node *node)
Michael Bohan86e30dc2012-01-05 14:16:43 -0800223{
Michael Bohan11926c92012-02-08 11:01:24 -0800224 struct spmi_controller *ctrl = d_info->ctrl;
225 struct spmi_boardinfo *b_info = &d_info->b_info;
Michael Bohan86e30dc2012-01-05 14:16:43 -0800226 void *result;
227 int rc;
228
Michael Bohan11926c92012-02-08 11:01:24 -0800229 rc = of_modalias_node(node, b_info->name, sizeof(b_info->name));
Michael Bohan86e30dc2012-01-05 14:16:43 -0800230 if (rc < 0) {
231 dev_err(&ctrl->dev, "of_spmi modalias failure on %s\n",
232 node->full_name);
233 return rc;
234 }
235
Michael Bohan11926c92012-02-08 11:01:24 -0800236 b_info->of_node = of_node_get(node);
237 result = spmi_new_device(ctrl, b_info);
Michael Bohan86e30dc2012-01-05 14:16:43 -0800238
239 if (result == NULL) {
240 dev_err(&ctrl->dev, "of_spmi: Failure registering %s\n",
241 node->full_name);
242 of_node_put(node);
243 return -ENODEV;
244 }
245
246 return 0;
247}
248
Michael Bohan86622b32012-02-08 16:59:00 -0800249/*
250 * Walks all children of a node containing the spmi-dev-container
251 * binding. This special type of spmi_device can include resources
252 * from more than one device node.
253 */
254static void of_spmi_walk_dev_container(struct of_spmi_dev_info *d_info,
255 struct device_node *container)
256{
257 struct of_spmi_res_info r_info = {};
258 struct spmi_controller *ctrl = d_info->ctrl;
259 struct device_node *node;
260 int rc, i, num_dev_node = 0;
261
Michael Bohan677dbbd2012-04-03 14:55:11 -0700262 if (!of_device_is_available(container))
263 return;
264
Michael Bohan87436bd2012-04-03 14:45:03 -0700265 /*
266 * Count the total number of device_nodes so we know how much
267 * device_store to allocate.
268 */
Michael Bohan677dbbd2012-04-03 14:55:11 -0700269 for_each_child_of_node(container, node) {
270 if (!of_device_is_available(node))
271 continue;
Michael Bohan86622b32012-02-08 16:59:00 -0800272 num_dev_node++;
Michael Bohan677dbbd2012-04-03 14:55:11 -0700273 }
Michael Bohan86622b32012-02-08 16:59:00 -0800274
Michael Bohan978d3352012-05-25 15:02:38 -0700275 rc = of_spmi_alloc_devnode_store(d_info, num_dev_node);
Michael Bohan86622b32012-02-08 16:59:00 -0800276 if (rc) {
Michael Bohan978d3352012-05-25 15:02:38 -0700277 dev_err(&ctrl->dev, "%s: unable to allocate devnode resources\n",
278 __func__);
Michael Bohan86622b32012-02-08 16:59:00 -0800279 return;
280 }
281
Michael Bohan86622b32012-02-08 16:59:00 -0800282 i = 0;
283 for_each_child_of_node(container, node) {
Michael Bohan677dbbd2012-04-03 14:55:11 -0700284 if (!of_device_is_available(node))
285 continue;
Michael Bohan86622b32012-02-08 16:59:00 -0800286 of_spmi_init_resource(&r_info, node);
Michael Bohan978d3352012-05-25 15:02:38 -0700287 of_spmi_sum_resources(&r_info, true);
288 rc = of_spmi_allocate_devnode_resources(d_info, &r_info, i);
Michael Bohan86622b32012-02-08 16:59:00 -0800289 if (rc) {
290 dev_err(&ctrl->dev, "%s: unable to allocate"
291 " resources\n", __func__);
Michael Bohan978d3352012-05-25 15:02:38 -0700292 of_spmi_free_devnode_resources(d_info);
Michael Bohan86622b32012-02-08 16:59:00 -0800293 return;
294 }
Michael Bohan978d3352012-05-25 15:02:38 -0700295 of_spmi_populate_devnode_resources(d_info, &r_info, i);
Michael Bohan86622b32012-02-08 16:59:00 -0800296 i++;
297 }
298
Michael Bohan978d3352012-05-25 15:02:38 -0700299 of_spmi_init_resource(&r_info, container);
300 of_spmi_sum_resources(&r_info, true);
301
302 rc = of_spmi_allocate_node_resources(d_info, &r_info);
303 if (rc) {
304 dev_err(&ctrl->dev, "%s: unable to allocate resources\n",
305 __func__);
306 of_spmi_free_node_resources(d_info);
307 }
308
309 of_spmi_populate_node_resources(d_info, &r_info);
310
311
Michael Bohan86622b32012-02-08 16:59:00 -0800312 rc = of_spmi_create_device(d_info, container);
313 if (rc) {
314 dev_err(&ctrl->dev, "%s: unable to create device for"
315 " node %s\n", __func__, container->full_name);
Michael Bohan978d3352012-05-25 15:02:38 -0700316 of_spmi_free_devnode_resources(d_info);
Michael Bohan86622b32012-02-08 16:59:00 -0800317 return;
318 }
319}
320
321/*
322 * Walks all children of a node containing the spmi-slave-container
323 * binding. This indicates that all spmi_devices created from this
324 * point all share the same slave_id.
325 */
Michael Bohan11926c92012-02-08 11:01:24 -0800326static void of_spmi_walk_slave_container(struct of_spmi_dev_info *d_info,
Michael Bohan978d3352012-05-25 15:02:38 -0700327 struct device_node *container)
Michael Bohan86e30dc2012-01-05 14:16:43 -0800328{
Michael Bohan11926c92012-02-08 11:01:24 -0800329 struct spmi_controller *ctrl = d_info->ctrl;
Michael Bohan86e30dc2012-01-05 14:16:43 -0800330 struct device_node *node;
Michael Bohan86e30dc2012-01-05 14:16:43 -0800331 int rc;
332
333 for_each_child_of_node(container, node) {
Michael Bohan11926c92012-02-08 11:01:24 -0800334 struct of_spmi_res_info r_info;
Michael Bohan86e30dc2012-01-05 14:16:43 -0800335
Michael Bohan677dbbd2012-04-03 14:55:11 -0700336 if (!of_device_is_available(node))
337 continue;
338
Michael Bohan86622b32012-02-08 16:59:00 -0800339 /**
340 * Check to see if this node contains children which
341 * should be all created as the same spmi_device.
342 */
343 if (of_get_property(node, "spmi-dev-container", NULL)) {
344 of_spmi_walk_dev_container(d_info, node);
345 continue;
346 }
Michael Bohan11926c92012-02-08 11:01:24 -0800347
Michael Bohan86622b32012-02-08 16:59:00 -0800348 of_spmi_init_resource(&r_info, node);
Michael Bohan978d3352012-05-25 15:02:38 -0700349 of_spmi_sum_resources(&r_info, true);
Michael Bohan86622b32012-02-08 16:59:00 -0800350
Michael Bohan978d3352012-05-25 15:02:38 -0700351 rc = of_spmi_allocate_node_resources(d_info, &r_info);
Michael Bohan86e30dc2012-01-05 14:16:43 -0800352 if (rc) {
353 dev_err(&ctrl->dev, "%s: unable to allocate"
354 " resources\n", __func__);
Michael Bohan86622b32012-02-08 16:59:00 -0800355 goto slave_err;
Michael Bohan86e30dc2012-01-05 14:16:43 -0800356 }
Michael Bohan86622b32012-02-08 16:59:00 -0800357
Michael Bohan978d3352012-05-25 15:02:38 -0700358 of_spmi_populate_node_resources(d_info, &r_info);
Michael Bohan86622b32012-02-08 16:59:00 -0800359
Michael Bohan11926c92012-02-08 11:01:24 -0800360 rc = of_spmi_create_device(d_info, node);
Michael Bohan86e30dc2012-01-05 14:16:43 -0800361 if (rc) {
362 dev_err(&ctrl->dev, "%s: unable to create device for"
363 " node %s\n", __func__, node->full_name);
Michael Bohan86622b32012-02-08 16:59:00 -0800364 goto slave_err;
Michael Bohan86e30dc2012-01-05 14:16:43 -0800365 }
366 }
Michael Bohan86622b32012-02-08 16:59:00 -0800367 return;
368
369slave_err:
Michael Bohan978d3352012-05-25 15:02:38 -0700370 of_spmi_free_node_resources(d_info);
Michael Bohan86e30dc2012-01-05 14:16:43 -0800371}
372
373int of_spmi_register_devices(struct spmi_controller *ctrl)
374{
Michael Bohan86622b32012-02-08 16:59:00 -0800375 struct device_node *node = ctrl->dev.of_node;
Michael Bohan86e30dc2012-01-05 14:16:43 -0800376
377 /* Only register child devices if the ctrl has a node pointer set */
Michael Bohan86622b32012-02-08 16:59:00 -0800378 if (!node)
Michael Bohan86e30dc2012-01-05 14:16:43 -0800379 return -ENODEV;
380
Michael Bohan86622b32012-02-08 16:59:00 -0800381 if (of_get_property(node, "spmi-slave-container", NULL)) {
382 dev_err(&ctrl->dev, "%s: structural error: spmi-slave-container"
383 " is prohibited at the root level\n", __func__);
384 return -EINVAL;
385 } else if (of_get_property(node, "spmi-dev-container", NULL)) {
386 dev_err(&ctrl->dev, "%s: structural error: spmi-dev-container"
387 " is prohibited at the root level\n", __func__);
388 return -EINVAL;
389 }
390
391 /**
392 * Make best effort to launch as many nodes as possible. If there are
393 * syntax errors, we will simply ignore that subtree and keep going.
394 */
Michael Bohan86e30dc2012-01-05 14:16:43 -0800395 for_each_child_of_node(ctrl->dev.of_node, node) {
Michael Bohan11926c92012-02-08 11:01:24 -0800396 struct of_spmi_dev_info d_info = {};
Michael Bohan86e30dc2012-01-05 14:16:43 -0800397 const __be32 *slave_id;
Michael Bohan86622b32012-02-08 16:59:00 -0800398 int len, rc, have_dev_container = 0;
Michael Bohan86e30dc2012-01-05 14:16:43 -0800399
400 slave_id = of_get_property(node, "reg", &len);
401 if (!slave_id) {
Michael Bohan86622b32012-02-08 16:59:00 -0800402 dev_err(&ctrl->dev, "%s: invalid sid "
403 "on %s\n", __func__, node->full_name);
Michael Bohan86e30dc2012-01-05 14:16:43 -0800404 continue;
405 }
406
Michael Bohan11926c92012-02-08 11:01:24 -0800407 d_info.b_info.slave_id = be32_to_cpup(slave_id);
408 d_info.ctrl = ctrl;
Michael Bohan86e30dc2012-01-05 14:16:43 -0800409
Michael Bohan86622b32012-02-08 16:59:00 -0800410 if (of_get_property(node, "spmi-dev-container", NULL))
411 have_dev_container = 1;
Michael Bohan11926c92012-02-08 11:01:24 -0800412 if (of_get_property(node, "spmi-slave-container", NULL)) {
Michael Bohan86622b32012-02-08 16:59:00 -0800413 if (have_dev_container)
414 of_spmi_walk_dev_container(&d_info, node);
415 else
416 of_spmi_walk_slave_container(&d_info, node);
Michael Bohan86e30dc2012-01-05 14:16:43 -0800417 } else {
Michael Bohan11926c92012-02-08 11:01:24 -0800418 struct of_spmi_res_info r_info;
419
Michael Bohan86622b32012-02-08 16:59:00 -0800420 /**
421 * A dev container at the second level without a slave
422 * container is considered an error.
423 */
424 if (have_dev_container) {
425 dev_err(&ctrl->dev, "%s: structural error,"
426 " node %s has spmi-dev-container without"
427 " specifying spmi-slave-container\n",
428 __func__, node->full_name);
Michael Bohan86e30dc2012-01-05 14:16:43 -0800429 continue;
Michael Bohan86622b32012-02-08 16:59:00 -0800430 }
431
Michael Bohan677dbbd2012-04-03 14:55:11 -0700432 if (!of_device_is_available(node))
433 continue;
434
Michael Bohan86622b32012-02-08 16:59:00 -0800435 of_spmi_init_resource(&r_info, node);
Michael Bohan978d3352012-05-25 15:02:38 -0700436 of_spmi_sum_resources(&r_info, false);
437 rc = of_spmi_allocate_node_resources(&d_info, &r_info);
Michael Bohan86622b32012-02-08 16:59:00 -0800438 if (rc) {
439 dev_err(&ctrl->dev, "%s: unable to allocate"
440 " resources\n", __func__);
Michael Bohan978d3352012-05-25 15:02:38 -0700441 of_spmi_free_node_resources(&d_info);
Michael Bohan86622b32012-02-08 16:59:00 -0800442 continue;
443 }
444
Michael Bohan978d3352012-05-25 15:02:38 -0700445 of_spmi_populate_node_resources(&d_info, &r_info);
Michael Bohan86622b32012-02-08 16:59:00 -0800446
447 rc = of_spmi_create_device(&d_info, node);
448 if (rc) {
449 dev_err(&ctrl->dev, "%s: unable to create"
450 " device\n", __func__);
Michael Bohan978d3352012-05-25 15:02:38 -0700451 of_spmi_free_node_resources(&d_info);
Michael Bohan86622b32012-02-08 16:59:00 -0800452 continue;
453 }
Michael Bohan86e30dc2012-01-05 14:16:43 -0800454 }
455 }
456
457 return 0;
458}
459EXPORT_SYMBOL(of_spmi_register_devices);
460
Michael Bohan978d3352012-05-25 15:02:38 -0700461MODULE_LICENSE("GPL v2");