blob: 0ffc19483c153fc317b94fa751a76c3651659547 [file] [log] [blame]
Ke Liue7150d12013-12-10 10:59:57 -08001/* Copyright (c) 2010-2014, Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
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
Stephen Boyd8704c7f2012-02-05 01:07:45 -080013#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
14
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070015#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/device.h>
18#include <linux/slab.h>
19#include <linux/module.h>
20#include <linux/clk.h>
21#include <linux/radix-tree.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070022#include <mach/board.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070023#include "msm_bus_core.h"
24
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070025enum {
26 SLAVE_NODE,
27 MASTER_NODE,
Gagan Macb0295972012-08-18 17:05:28 -060028 CLK_NODE,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070029};
30
31enum {
32 DISABLE,
33 ENABLE,
34};
35
36struct msm_bus_fabric {
37 struct msm_bus_fabric_device fabdev;
38 int ahb;
39 void *cdata[NUM_CTX];
40 bool arb_dirty;
41 bool clk_dirty;
42 struct radix_tree_root fab_tree;
43 int num_nodes;
44 struct list_head gateways;
45 struct msm_bus_inode_info info;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070046 struct msm_bus_fabric_registration *pdata;
Gagan Mac47a999a2012-01-18 20:36:12 -070047 void *hw_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070048};
49#define to_msm_bus_fabric(d) container_of(d, \
50 struct msm_bus_fabric, d)
51
52/**
53 * msm_bus_fabric_add_node() - Add a node to the fabric structure
54 * @fabric: Fabric device to which the node should be added
55 * @info: The node to be added
56 */
57static int msm_bus_fabric_add_node(struct msm_bus_fabric *fabric,
58 struct msm_bus_inode_info *info)
59{
Gagan Macb0295972012-08-18 17:05:28 -060060 int status = -ENOMEM, ctx;
Gagan Mac60569172011-11-09 16:17:12 -070061 MSM_BUS_DBG("msm_bus_fabric_add_node: ID %d Gw: %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070062 info->node_info->priv_id, info->node_info->gateway);
63 status = radix_tree_preload(GFP_ATOMIC);
64 if (status)
65 goto out;
Gagan Maccbf9e242011-08-03 15:42:25 -060066
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070067 status = radix_tree_insert(&fabric->fab_tree, info->node_info->priv_id,
68 info);
Gagan Maccbf9e242011-08-03 15:42:25 -060069 radix_tree_preload_end();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070070 if (IS_SLAVE(info->node_info->priv_id))
71 radix_tree_tag_set(&fabric->fab_tree, info->node_info->priv_id,
72 SLAVE_NODE);
73
Gagan Macb0295972012-08-18 17:05:28 -060074 for (ctx = 0; ctx < NUM_CTX; ctx++) {
75 if (info->node_info->slaveclk[ctx]) {
76 radix_tree_tag_set(&fabric->fab_tree,
77 info->node_info->priv_id, CLK_NODE);
78 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070079 }
Gagan Macb0295972012-08-18 17:05:28 -060080
81 info->nodeclk[ctx].enable = false;
82 info->nodeclk[ctx].dirty = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070083 }
Gagan Maccbf9e242011-08-03 15:42:25 -060084
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070085out:
86 return status;
87}
88
89/**
90 * msm_bus_add_fab() - Add a fabric (gateway) to the current fabric
91 * @fabric: Fabric device to which the gateway info should be added
92 * @info: Gateway node to be added to the fabric
93 */
94static int msm_bus_fabric_add_fab(struct msm_bus_fabric *fabric,
95 struct msm_bus_inode_info *info)
96{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070097 struct msm_bus_fabnodeinfo *fabnodeinfo;
Gagan Mac60569172011-11-09 16:17:12 -070098 MSM_BUS_DBG("msm_bus_fabric_add_fab: ID %d Gw: %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070099 info->node_info->priv_id, info->node_info->gateway);
100 fabnodeinfo = kzalloc(sizeof(struct msm_bus_fabnodeinfo), GFP_KERNEL);
Gagan Macdde34072011-09-20 15:43:25 -0600101 if (fabnodeinfo == NULL) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700102 MSM_FAB_ERR("msm_bus_fabric_add_fab: "
103 "No Node Info\n");
104 MSM_FAB_ERR("axi: Cannot register fabric!\n");
Gagan Macdde34072011-09-20 15:43:25 -0600105 return -ENOMEM;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700106 }
107
108 fabnodeinfo->info = info;
109 fabnodeinfo->info->num_pnodes = -1;
110 list_add_tail(&fabnodeinfo->list, &fabric->gateways);
Gagan Macdde34072011-09-20 15:43:25 -0600111 return 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700112}
113
114/**
115 * register_fabric_info() - Create the internal fabric structure and
116 * build the topology tree from platform specific data
Gagan Mac47a999a2012-01-18 20:36:12 -0700117 * @pdev: Platform device for getting base addresses
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700118 * @fabric: Fabric to which the gateways, nodes should be added
119 *
120 * This function is called from probe. Iterates over the platform data,
121 * and builds the topology
122 */
Gagan Mac47a999a2012-01-18 20:36:12 -0700123static int register_fabric_info(struct platform_device *pdev,
124 struct msm_bus_fabric *fabric)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700125{
Gagan Mac47a999a2012-01-18 20:36:12 -0700126 int i = 0, ret = 0, err = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700127
Gagan Mac60569172011-11-09 16:17:12 -0700128 MSM_BUS_DBG("id:%d pdata-id: %d len: %d\n", fabric->fabdev.id,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700129 fabric->pdata->id, fabric->pdata->len);
Gagan Mac47a999a2012-01-18 20:36:12 -0700130 fabric->hw_data = fabric->fabdev.hw_algo.allocate_hw_data(pdev,
131 fabric->pdata);
Gagan Mac4bd0b1c2012-06-18 17:14:44 -0600132 if (ZERO_OR_NULL_PTR(fabric->hw_data) && fabric->pdata->ahb == 0) {
Gagan Mac47a999a2012-01-18 20:36:12 -0700133 MSM_BUS_ERR("Couldn't allocate hw_data for fab: %d\n",
134 fabric->fabdev.id);
135 goto error;
136 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700137
138 for (i = 0; i < fabric->pdata->len; i++) {
139 struct msm_bus_inode_info *info;
Gagan Macd1e22f02012-08-10 15:44:53 -0600140 int ctx, j;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700141
142 info = kzalloc(sizeof(struct msm_bus_inode_info), GFP_KERNEL);
Gagan Macdde34072011-09-20 15:43:25 -0600143 if (info == NULL) {
144 MSM_BUS_ERR("Error allocating info\n");
145 return -ENOMEM;
146 }
147
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700148 info->node_info = fabric->pdata->info + i;
149 info->commit_index = -1;
150 info->num_pnodes = -1;
151
152 for (ctx = 0; ctx < NUM_CTX; ctx++) {
153 if (info->node_info->slaveclk[ctx]) {
Matt Wagantallb2710b82011-11-16 19:55:17 -0800154 info->nodeclk[ctx].clk = clk_get_sys("msm_bus",
155 info->node_info->slaveclk[ctx]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700156 if (IS_ERR(info->nodeclk[ctx].clk)) {
157 MSM_BUS_ERR("Couldn't get clk %s\n",
158 info->node_info->slaveclk[ctx]);
159 err = -EINVAL;
160 }
161 info->nodeclk[ctx].enable = false;
162 info->nodeclk[ctx].dirty = false;
163 }
Gagan Mac66a84b52012-06-29 00:08:11 -0600164
165 if (info->node_info->memclk[ctx]) {
166 info->memclk[ctx].clk = clk_get_sys("msm_bus",
167 info->node_info->memclk[ctx]);
168 if (IS_ERR(info->memclk[ctx].clk)) {
169 MSM_BUS_ERR("Couldn't get clk %s\n",
170 info->node_info->memclk[ctx]);
171 err = -EINVAL;
172 }
173 info->memclk[ctx].enable = false;
174 info->memclk[ctx].dirty = false;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700175 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700176 }
177
Gagan Macf095ded2012-10-16 16:37:39 -0600178 if (info->node_info->iface_clk_node) {
179 info->iface_clk.clk = clk_get_sys(info->node_info->
180 iface_clk_node, "iface_clk");
181 if (IS_ERR(info->iface_clk.clk)) {
182 MSM_BUS_ERR("ERR: Couldn't get clk %s\n",
183 info->node_info->iface_clk_node);
184 }
185 }
186
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700187 ret = info->node_info->gateway ?
188 msm_bus_fabric_add_fab(fabric, info) :
189 msm_bus_fabric_add_node(fabric, info);
190 if (ret) {
191 MSM_BUS_ERR("Unable to add node info, ret: %d\n", ret);
192 kfree(info);
193 goto error;
194 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700195
Gagan Mac47a999a2012-01-18 20:36:12 -0700196 if (fabric->fabdev.hw_algo.node_init == NULL)
197 continue;
198
Gagan Macf095ded2012-10-16 16:37:39 -0600199 if (info->iface_clk.clk) {
200 MSM_BUS_DBG("Enabled iface clock for node init: %d\n",
201 info->node_info->priv_id);
202 clk_prepare_enable(info->iface_clk.clk);
203 }
204
Gagan Macd1e22f02012-08-10 15:44:53 -0600205 for (j = 0; j < NUM_CTX; j++)
206 clk_prepare_enable(fabric->info.nodeclk[j].clk);
207
Gagan Mac47a999a2012-01-18 20:36:12 -0700208 fabric->fabdev.hw_algo.node_init(fabric->hw_data, info);
209 if (ret) {
210 MSM_BUS_ERR("Unable to init node info, ret: %d\n", ret);
211 kfree(info);
212 }
Gagan Macd1e22f02012-08-10 15:44:53 -0600213
214 for (j = 0; j < NUM_CTX; j++)
215 clk_disable_unprepare(fabric->info.nodeclk[j].clk);
Gagan Macf095ded2012-10-16 16:37:39 -0600216
217 if (info->iface_clk.clk) {
218 MSM_BUS_DBG("Disable iface_clk after node init: %d\n",
219 info->node_info->priv_id);
220 clk_disable_unprepare(info->iface_clk.clk);
221 }
222
223
Gagan Mac47a999a2012-01-18 20:36:12 -0700224 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700225
Gagan Mac60569172011-11-09 16:17:12 -0700226 MSM_BUS_DBG("Fabric: %d nmasters: %d nslaves: %d\n"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700227 " ntieredslaves: %d, rpm_enabled: %d\n",
228 fabric->fabdev.id, fabric->pdata->nmasters,
229 fabric->pdata->nslaves, fabric->pdata->ntieredslaves,
230 fabric->pdata->rpm_enabled);
Gagan Mac60569172011-11-09 16:17:12 -0700231 MSM_BUS_DBG("msm_bus_register_fabric_info i: %d\n", i);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700232 fabric->num_nodes = fabric->pdata->len;
233error:
234 fabric->num_nodes = i;
235 msm_bus_dbg_commit_data(fabric->fabdev.name, NULL, 0, 0, 0,
236 MSM_BUS_DBG_REGISTER);
237 return ret | err;
238}
239
240/**
241 * msm_bus_fabric_update_clks() - Set the clocks for fabrics and slaves
242 * @fabric: Fabric for which the clocks need to be updated
243 * @slave: The node for which the clocks need to be updated
244 * @index: The index for which the current clocks are set
245 * @curr_clk_hz:Current clock value
246 * @req_clk_hz: Requested clock value
247 * @bwsum: Bandwidth Sum
248 * @clk_flag: Flag determining whether fabric clock or the slave clock has to
249 * be set. If clk_flag is set, fabric clock is set, else slave clock is set.
250 */
251static int msm_bus_fabric_update_clks(struct msm_bus_fabric_device *fabdev,
252 struct msm_bus_inode_info *slave, int index,
Gagan Macb2372ae2012-08-20 19:24:32 -0600253 uint64_t curr_clk_hz, uint64_t req_clk_hz,
254 uint64_t bwsum_hz, int clk_flag, int ctx,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700255 unsigned int cl_active_flag)
256{
257 int i, status = 0;
Gagan Macb2372ae2012-08-20 19:24:32 -0600258 uint64_t max_pclk = 0, rate;
259 uint64_t *pclk = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700260 struct msm_bus_fabric *fabric = to_msm_bus_fabric(fabdev);
261 struct nodeclk *nodeclk;
262
Gagan Mac2235a402012-01-14 15:23:57 -0700263 /**
264 * Integration for clock rates is not required if context is not
265 * same as client's active-only flag
266 */
267 if (ctx != cl_active_flag)
268 goto skip_set_clks;
269
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700270 /* Maximum for this gateway */
271 for (i = 0; i <= slave->num_pnodes; i++) {
272 if (i == index && (req_clk_hz < curr_clk_hz))
273 continue;
274 slave->pnode[i].sel_clk = &slave->pnode[i].clk[ctx];
275 max_pclk = max(max_pclk, *slave->pnode[i].sel_clk);
276 }
277
278 *slave->link_info.sel_clk =
279 max(max_pclk, max(bwsum_hz, req_clk_hz));
280 /* Is this gateway or slave? */
281 if (clk_flag && (!fabric->ahb)) {
282 struct msm_bus_fabnodeinfo *fabgw = NULL;
283 struct msm_bus_inode_info *info = NULL;
284 /* Maximum of all gateways set at fabric */
285 list_for_each_entry(fabgw, &fabric->gateways, list) {
286 info = fabgw->info;
287 if (!info)
288 continue;
289 info->link_info.sel_clk = &info->link_info.clk[ctx];
290 max_pclk = max(max_pclk, *info->link_info.sel_clk);
291 }
Gagan Macb2372ae2012-08-20 19:24:32 -0600292 MSM_BUS_DBG("max_pclk from gateways: %llu\n", max_pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700293
294 /* Maximum of all slave clocks. */
295
296 for (i = 0; i < fabric->pdata->len; i++) {
297 if (fabric->pdata->info[i].gateway ||
298 (fabric->pdata->info[i].id < SLAVE_ID_KEY))
299 continue;
300 info = radix_tree_lookup(&fabric->fab_tree,
301 fabric->pdata->info[i].priv_id);
302 if (!info)
303 continue;
304 info->link_info.sel_clk = &info->link_info.clk[ctx];
305 max_pclk = max(max_pclk, *info->link_info.sel_clk);
306 }
307
308
Gagan Macb2372ae2012-08-20 19:24:32 -0600309 MSM_BUS_DBG("max_pclk from slaves & gws: %llu\n", max_pclk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700310 fabric->info.link_info.sel_clk =
311 &fabric->info.link_info.clk[ctx];
312 pclk = fabric->info.link_info.sel_clk;
313 } else {
314 slave->link_info.sel_clk = &slave->link_info.clk[ctx];
315 pclk = slave->link_info.sel_clk;
316 }
317
318
319 *pclk = max(max_pclk, max(bwsum_hz, req_clk_hz));
320
321 if (!fabric->pdata->rpm_enabled)
322 goto skip_set_clks;
323
324 if (clk_flag) {
325 nodeclk = &fabric->info.nodeclk[ctx];
Gagan Mac2235a402012-01-14 15:23:57 -0700326 if (nodeclk->clk) {
Gagan Macb2372ae2012-08-20 19:24:32 -0600327 MSM_BUS_DBG("clks: id: %d set-clk: %llu bws_hz:%llu\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700328 fabric->fabdev.id, *pclk, bwsum_hz);
329 if (nodeclk->rate != *pclk) {
330 nodeclk->dirty = true;
331 nodeclk->rate = *pclk;
332 }
333 fabric->clk_dirty = true;
334 }
335 } else {
336 nodeclk = &slave->nodeclk[ctx];
Gagan Mac2235a402012-01-14 15:23:57 -0700337 if (nodeclk->clk) {
Gagan Macc7c0db62011-07-20 13:07:29 -0600338 rate = *pclk;
Gagan Macb2372ae2012-08-20 19:24:32 -0600339 MSM_BUS_DBG("clks: id: %d set-clk: %llu bws_hz: %llu\n",
340 slave->node_info->priv_id, rate,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700341 bwsum_hz);
Gagan Macc7c0db62011-07-20 13:07:29 -0600342 if (nodeclk->rate != rate) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700343 nodeclk->dirty = true;
344 nodeclk->rate = rate;
345 }
346 }
Gagan Mac66a84b52012-06-29 00:08:11 -0600347 if (!status && slave->memclk[ctx].clk) {
Gagan Macc7c0db62011-07-20 13:07:29 -0600348 rate = *slave->link_info.sel_clk;
Gagan Mac66a84b52012-06-29 00:08:11 -0600349 if (slave->memclk[ctx].rate != rate) {
350 slave->memclk[ctx].rate = rate;
351 slave->memclk[ctx].dirty = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700352 }
Gagan Mac66a84b52012-06-29 00:08:11 -0600353 slave->memclk[ctx].rate = rate;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700354 fabric->clk_dirty = true;
355 }
356 }
357skip_set_clks:
358 return status;
359}
360
361void msm_bus_fabric_update_bw(struct msm_bus_fabric_device *fabdev,
362 struct msm_bus_inode_info *hop, struct msm_bus_inode_info *info,
Gagan Macb2372ae2012-08-20 19:24:32 -0600363 int64_t add_bw, int *master_tiers, int ctx)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700364{
365 struct msm_bus_fabric *fabric = to_msm_bus_fabric(fabdev);
366 void *sel_cdata;
Dan Sneddon2c0fbcc2013-11-05 13:16:21 -0700367 long rounded_rate, cur_rate;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700368
369 sel_cdata = fabric->cdata[ctx];
370
371 /* If it's an ahb fabric, don't calculate arb values */
372 if (fabric->ahb) {
Gagan Mac60569172011-11-09 16:17:12 -0700373 MSM_BUS_DBG("AHB fabric, skipping bw calculation\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700374 return;
375 }
376 if (!add_bw) {
377 MSM_BUS_DBG("No bandwidth delta. Skipping commit\n");
378 return;
379 }
380
Gagan Macf095ded2012-10-16 16:37:39 -0600381 /* Enable clocks before accessing QoS registers */
Dan Sneddon2c0fbcc2013-11-05 13:16:21 -0700382 if (fabric->info.nodeclk[DUAL_CTX].clk) {
Gagan Mac9bdb4d12013-02-28 13:33:42 -0700383 if (fabric->info.nodeclk[DUAL_CTX].rate == 0) {
Dan Sneddon2c0fbcc2013-11-05 13:16:21 -0700384 cur_rate = clk_get_rate(
385 fabric->info.nodeclk[DUAL_CTX].clk);
386 rounded_rate = clk_round_rate(
387 fabric->info.nodeclk[DUAL_CTX].clk,
388 cur_rate ? cur_rate : 1);
Gagan Mac9bdb4d12013-02-28 13:33:42 -0700389 if (clk_set_rate(fabric->info.nodeclk[DUAL_CTX].clk,
390 rounded_rate))
391 MSM_BUS_ERR("Error: clk: en: Node: %d rate: %ld",
392 fabric->fabdev.id, rounded_rate);
393
394 clk_prepare_enable(fabric->info.nodeclk[DUAL_CTX].clk);
Dan Sneddon2c0fbcc2013-11-05 13:16:21 -0700395 }
Gagan Mac9bdb4d12013-02-28 13:33:42 -0700396 }
Gagan Macd1e22f02012-08-10 15:44:53 -0600397
Gagan Macf095ded2012-10-16 16:37:39 -0600398 if (info->iface_clk.clk)
399 clk_prepare_enable(info->iface_clk.clk);
400
401 if (hop->iface_clk.clk)
402 clk_prepare_enable(hop->iface_clk.clk);
403
Gagan Mac47a999a2012-01-18 20:36:12 -0700404 fabdev->hw_algo.update_bw(hop, info, fabric->pdata, sel_cdata,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700405 master_tiers, add_bw);
Gagan Macf095ded2012-10-16 16:37:39 -0600406
407 /* Disable clocks after accessing QoS registers */
Gagan Mac9bdb4d12013-02-28 13:33:42 -0700408 if (fabric->info.nodeclk[DUAL_CTX].clk &&
409 fabric->info.nodeclk[DUAL_CTX].rate == 0)
410 clk_disable_unprepare(fabric->info.nodeclk[DUAL_CTX].clk);
Gagan Macd1e22f02012-08-10 15:44:53 -0600411
Gagan Macf095ded2012-10-16 16:37:39 -0600412 if (info->iface_clk.clk) {
413 MSM_BUS_DBG("Commented: Will disable clock for info: %d\n",
414 info->node_info->priv_id);
415 clk_disable_unprepare(info->iface_clk.clk);
416 }
417
418 if (hop->iface_clk.clk) {
419 MSM_BUS_DBG("Commented Will disable clock for hop: %d\n",
420 hop->node_info->priv_id);
421 clk_disable_unprepare(hop->iface_clk.clk);
422 }
423
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700424 fabric->arb_dirty = true;
425}
426
427static int msm_bus_fabric_clk_set(int enable, struct msm_bus_inode_info *info)
428{
429 int i, status = 0;
Gagan Macb6ff86b2012-06-15 12:26:11 -0600430 long rounded_rate;
431
Gagan Mac66a84b52012-06-29 00:08:11 -0600432 for (i = 0; i < NUM_CTX; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700433 if (info->nodeclk[i].dirty) {
Gagan Macb6ff86b2012-06-15 12:26:11 -0600434 if (info->nodeclk[i].rate != 0) {
435 rounded_rate = clk_round_rate(info->
436 nodeclk[i].clk, info->nodeclk[i].rate);
437 status = clk_set_rate(info->nodeclk[i].clk,
438 rounded_rate);
439 MSM_BUS_DBG("AXI: node: %d set_rate: %ld\n",
440 info->node_info->id, rounded_rate);
441 }
442
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700443 if (enable && !(info->nodeclk[i].enable)) {
Gagan Mac5434bd72012-03-20 13:21:00 -0600444 clk_prepare_enable(info->nodeclk[i].clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700445 info->nodeclk[i].dirty = false;
446 info->nodeclk[i].enable = true;
447 } else if ((info->nodeclk[i].rate == 0) && (!enable)
448 && (info->nodeclk[i].enable)) {
Gagan Mac5434bd72012-03-20 13:21:00 -0600449 clk_disable_unprepare(info->nodeclk[i].clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700450 info->nodeclk[i].dirty = false;
451 info->nodeclk[i].enable = false;
452 }
453 }
454
Gagan Mac66a84b52012-06-29 00:08:11 -0600455 if (info->memclk[i].dirty) {
Gagan Macb6ff86b2012-06-15 12:26:11 -0600456 if (info->nodeclk[i].rate != 0) {
457 rounded_rate = clk_round_rate(info->
458 memclk[i].clk, info->memclk[i].rate);
459 status = clk_set_rate(info->memclk[i].clk,
460 rounded_rate);
461 MSM_BUS_DBG("AXI: node: %d set_rate: %ld\n",
462 info->node_info->id, rounded_rate);
463 }
464
Gagan Mac66a84b52012-06-29 00:08:11 -0600465 if (enable && !(info->memclk[i].enable)) {
466 clk_prepare_enable(info->memclk[i].clk);
467 info->memclk[i].dirty = false;
468 info->memclk[i].enable = true;
469 } else if (info->memclk[i].rate == 0 && (!enable) &&
470 (info->memclk[i].enable)) {
471 clk_disable_unprepare(info->memclk[i].clk);
472 info->memclk[i].dirty = false;
473 info->memclk[i].enable = false;
474 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700475 }
476 }
477
478 return status;
479}
480
481/**
482 * msm_bus_fabric_clk_commit() - Call clock enable and update clock
483 * values.
484*/
485static int msm_bus_fabric_clk_commit(int enable, struct msm_bus_fabric *fabric)
486{
487 unsigned int i, nfound = 0, status = 0;
488 struct msm_bus_inode_info *info[fabric->pdata->nslaves];
489
Gagan Macb0295972012-08-18 17:05:28 -0600490 if (fabric->clk_dirty == true)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700491 status = msm_bus_fabric_clk_set(enable, &fabric->info);
492
493 if (status)
494 MSM_BUS_WARN("Error setting clocks on fabric: %d\n",
495 fabric->fabdev.id);
496
497 nfound = radix_tree_gang_lookup_tag(&fabric->fab_tree, (void **)&info,
Gagan Macb0295972012-08-18 17:05:28 -0600498 fabric->fabdev.id, fabric->pdata->nslaves, CLK_NODE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700499 if (nfound == 0) {
Gagan Macb0295972012-08-18 17:05:28 -0600500 MSM_BUS_DBG("No clock nodes found for fabric: %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700501 fabric->fabdev.id);
502 goto out;
503 }
504
505 for (i = 0; i < nfound; i++) {
506 status = msm_bus_fabric_clk_set(enable, info[i]);
507 if (status)
508 MSM_BUS_WARN("Error setting clocks for node: %d\n",
509 info[i]->node_info->id);
510 }
511
512out:
513 return status;
514}
515
Gagan Mac068e84d2013-05-28 18:22:33 -0600516static void msm_bus_fabric_config_master(
517 struct msm_bus_fabric_device *fabdev,
518 struct msm_bus_inode_info *info, uint64_t req_clk, uint64_t req_bw)
519{
520 struct msm_bus_fabric *fabric = to_msm_bus_fabric(fabdev);
Dan Sneddon2c0fbcc2013-11-05 13:16:21 -0700521 long rounded_rate, cur_rate;
Gagan Mac068e84d2013-05-28 18:22:33 -0600522
523 if (fabdev->hw_algo.config_master == NULL)
524 return;
525
526 /* Enable clocks before accessing QoS registers */
Dan Sneddon2c0fbcc2013-11-05 13:16:21 -0700527 if (fabric->info.nodeclk[DUAL_CTX].clk) {
Gagan Mac068e84d2013-05-28 18:22:33 -0600528 if (fabric->info.nodeclk[DUAL_CTX].rate == 0) {
Dan Sneddon2c0fbcc2013-11-05 13:16:21 -0700529 cur_rate = clk_get_rate(
530 fabric->info.nodeclk[DUAL_CTX].clk);
531 rounded_rate = clk_round_rate(
532 fabric->info.nodeclk[DUAL_CTX].clk,
533 cur_rate ? cur_rate : 1);
Gagan Mac068e84d2013-05-28 18:22:33 -0600534 if (clk_set_rate(fabric->info.nodeclk[DUAL_CTX].clk,
535 rounded_rate))
536 MSM_BUS_ERR("Error: clk: en: Node: %d rate: %ld",
537 fabric->fabdev.id, rounded_rate);
538
539 clk_prepare_enable(fabric->info.nodeclk[DUAL_CTX].clk);
Dan Sneddon2c0fbcc2013-11-05 13:16:21 -0700540 }
Gagan Mac068e84d2013-05-28 18:22:33 -0600541 }
542
543 if (info->iface_clk.clk)
544 clk_prepare_enable(info->iface_clk.clk);
545
546 fabdev->hw_algo.config_master(fabric->pdata, info, req_clk, req_bw);
547
548 /* Disable clocks after accessing QoS registers */
549 if (fabric->info.nodeclk[DUAL_CTX].clk &&
550 fabric->info.nodeclk[DUAL_CTX].rate == 0)
551 clk_disable_unprepare(fabric->info.nodeclk[DUAL_CTX].clk);
552
553 if (info->iface_clk.clk) {
554 MSM_BUS_DBG("Commented: Will disable clock for info: %d\n",
555 info->node_info->priv_id);
556 clk_disable_unprepare(info->iface_clk.clk);
557 }
558}
559
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700560/**
Gagan Mac47a999a2012-01-18 20:36:12 -0700561 * msm_bus_fabric_hw_commit() - Commit the arbitration data to Hardware.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700562 * @fabric: Fabric for which the data should be committed
563 * */
Gagan Mac47a999a2012-01-18 20:36:12 -0700564static int msm_bus_fabric_hw_commit(struct msm_bus_fabric_device *fabdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700565{
566 int status = 0;
567 struct msm_bus_fabric *fabric = to_msm_bus_fabric(fabdev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700568
569 /*
570 * For a non-zero bandwidth request, clocks should be enabled before
571 * sending the arbitration data to RPM, but should be disabled only
572 * after commiting the data.
573 */
574 status = msm_bus_fabric_clk_commit(ENABLE, fabric);
575 if (status)
576 MSM_BUS_DBG("Error setting clocks on fabric: %d\n",
577 fabric->fabdev.id);
578
579 if (!fabric->arb_dirty) {
580 MSM_BUS_DBG("Not committing as fabric not arb_dirty\n");
581 goto skip_arb;
582 }
583
Gagan Mac47a999a2012-01-18 20:36:12 -0700584 status = fabdev->hw_algo.commit(fabric->pdata, fabric->hw_data,
Gagan Mac8661a0e2011-10-19 18:35:48 -0600585 (void **)fabric->cdata);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700586 if (status)
587 MSM_BUS_DBG("Error committing arb data for fabric: %d\n",
588 fabric->fabdev.id);
589
590 fabric->arb_dirty = false;
591skip_arb:
592 /*
593 * If the bandwidth request is 0 for a fabric, the clocks
594 * should be disabled after arbitration data is committed.
595 */
596 status = msm_bus_fabric_clk_commit(DISABLE, fabric);
597 if (status)
Gagan Macb0295972012-08-18 17:05:28 -0600598 MSM_BUS_WARN("Error disabling clocks on fabric: %d\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700599 fabric->fabdev.id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700600 fabric->clk_dirty = false;
601 return status;
602}
603
604/**
605 * msm_bus_fabric_port_halt() - Used to halt a master port
606 * @fabric: Fabric on which the current master node is present
607 * @portid: Port id of the master
608 */
609int msm_bus_fabric_port_halt(struct msm_bus_fabric_device *fabdev, int iid)
610{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700611 struct msm_bus_inode_info *info = NULL;
Gagan Macc7c0db62011-07-20 13:07:29 -0600612 uint8_t mport;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700613 uint32_t haltid = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700614 struct msm_bus_fabric *fabric = to_msm_bus_fabric(fabdev);
615
616 info = fabdev->algo->find_node(fabdev, iid);
617 if (!info) {
618 MSM_BUS_ERR("Error: Info not found for id: %u", iid);
619 return -EINVAL;
620 }
621
622 haltid = fabric->pdata->haltid;
Gagan Macc7c0db62011-07-20 13:07:29 -0600623 mport = info->node_info->masterp[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700624
Gagan Mac47a999a2012-01-18 20:36:12 -0700625 return fabdev->hw_algo.port_halt(haltid, mport);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700626}
627
628/**
629 * msm_bus_fabric_port_unhalt() - Used to unhalt a master port
630 * @fabric: Fabric on which the current master node is present
631 * @portid: Port id of the master
632 */
633int msm_bus_fabric_port_unhalt(struct msm_bus_fabric_device *fabdev, int iid)
634{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700635 struct msm_bus_inode_info *info = NULL;
Gagan Macc7c0db62011-07-20 13:07:29 -0600636 uint8_t mport;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700637 uint32_t haltid = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700638 struct msm_bus_fabric *fabric = to_msm_bus_fabric(fabdev);
639
640 info = fabdev->algo->find_node(fabdev, iid);
641 if (!info) {
642 MSM_BUS_ERR("Error: Info not found for id: %u", iid);
643 return -EINVAL;
644 }
645
646 haltid = fabric->pdata->haltid;
Gagan Macc7c0db62011-07-20 13:07:29 -0600647 mport = info->node_info->masterp[0];
Gagan Mac47a999a2012-01-18 20:36:12 -0700648 return fabdev->hw_algo.port_unhalt(haltid, mport);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700649}
650
651/**
652 * msm_bus_fabric_find_gw_node() - This function finds the gateway node
653 * attached on a given fabric
654 * @id: ID of the gateway node
655 * @fabric: Fabric to find the gateway node on
656 * Function returns: Pointer to the gateway node
657 */
658static struct msm_bus_inode_info *msm_bus_fabric_find_gw_node(struct
659 msm_bus_fabric_device * fabdev, int id)
660{
661 struct msm_bus_inode_info *info = NULL;
662 struct msm_bus_fabnodeinfo *fab;
663 struct msm_bus_fabric *fabric;
664 if (!fabdev) {
665 MSM_BUS_ERR("No fabric device found!\n");
666 return NULL;
667 }
668
669 fabric = to_msm_bus_fabric(fabdev);
670 if (!fabric || IS_ERR(fabric)) {
671 MSM_BUS_ERR("No fabric type found!\n");
672 return NULL;
673 }
674 list_for_each_entry(fab, &fabric->gateways, list) {
675 if (fab->info->node_info->priv_id == id) {
676 info = fab->info;
677 break;
678 }
679 }
680
681 return info;
682}
683
684static struct msm_bus_inode_info *msm_bus_fabric_find_node(struct
685 msm_bus_fabric_device * fabdev, int id)
686{
687 struct msm_bus_inode_info *info = NULL;
688 struct msm_bus_fabric *fabric = to_msm_bus_fabric(fabdev);
689 info = radix_tree_lookup(&fabric->fab_tree, id);
690 if (!info)
Gagan Mac60569172011-11-09 16:17:12 -0700691 MSM_BUS_ERR("Null info found for id %d\n", id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700692 return info;
693}
694
695static struct list_head *msm_bus_fabric_get_gw_list(struct msm_bus_fabric_device
696 *fabdev)
697{
698 struct msm_bus_fabric *fabric = to_msm_bus_fabric(fabdev);
699 if (!fabric || IS_ERR(fabric)) {
700 MSM_BUS_ERR("No fabric found from fabdev\n");
701 return NULL;
702 }
703 return &fabric->gateways;
704
705}
706static struct msm_bus_fab_algorithm msm_bus_algo = {
707 .update_clks = msm_bus_fabric_update_clks,
708 .update_bw = msm_bus_fabric_update_bw,
709 .port_halt = msm_bus_fabric_port_halt,
710 .port_unhalt = msm_bus_fabric_port_unhalt,
Gagan Mac47a999a2012-01-18 20:36:12 -0700711 .commit = msm_bus_fabric_hw_commit,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700712 .find_node = msm_bus_fabric_find_node,
713 .find_gw_node = msm_bus_fabric_find_gw_node,
714 .get_gw_list = msm_bus_fabric_get_gw_list,
Gagan Mac068e84d2013-05-28 18:22:33 -0600715 .config_master = msm_bus_fabric_config_master,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700716};
717
Gagan Mac47a999a2012-01-18 20:36:12 -0700718static int msm_bus_fabric_hw_init(struct msm_bus_fabric_registration *pdata,
719 struct msm_bus_hw_algorithm *hw_algo)
720{
721 int ret = 0;
Gagan Mac47a999a2012-01-18 20:36:12 -0700722
Gagan Mac8cbbb802012-02-08 15:35:54 -0700723 switch (pdata->hw_sel) {
724 case MSM_BUS_NOC:
725 msm_bus_noc_hw_init(pdata, hw_algo);
726 break;
727 case MSM_BUS_BIMC:
728 msm_bus_bimc_hw_init(pdata, hw_algo);
729 break;
730 default:
731 ret = msm_bus_rpm_hw_init(pdata, hw_algo);
732 if (ret) {
733 MSM_BUS_ERR("RPM initialization failed\n");
734 ret = -EINVAL;
735 }
736 break;
737 }
Gagan Mac47a999a2012-01-18 20:36:12 -0700738 return ret;
739}
740
Gagan Mac7fbccf92012-12-12 23:49:58 -0700741static int __devinit msm_bus_fabric_probe(struct platform_device *pdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700742{
743 int ctx, ret = 0;
744 struct msm_bus_fabric *fabric;
745 struct msm_bus_fabric_registration *pdata;
746
747 fabric = kzalloc(sizeof(struct msm_bus_fabric), GFP_KERNEL);
Gagan Mac6dcc6702011-10-04 11:56:27 -0600748 if (!fabric) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700749 MSM_BUS_ERR("Fabric alloc failed\n");
750 return -ENOMEM;
751 }
752
753 INIT_LIST_HEAD(&fabric->gateways);
754 INIT_RADIX_TREE(&fabric->fab_tree, GFP_ATOMIC);
755 fabric->num_nodes = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700756 fabric->fabdev.visited = false;
757
758 fabric->info.node_info = kzalloc(sizeof(struct msm_bus_node_info),
759 GFP_KERNEL);
Gagan Macdde34072011-09-20 15:43:25 -0600760 if (ZERO_OR_NULL_PTR(fabric->info.node_info)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700761 MSM_BUS_ERR("Fabric node info alloc failed\n");
762 kfree(fabric);
763 return -ENOMEM;
764 }
Gagan Mac7fbccf92012-12-12 23:49:58 -0700765
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700766 fabric->info.num_pnodes = -1;
767 fabric->info.link_info.clk[DUAL_CTX] = 0;
768 fabric->info.link_info.bw[DUAL_CTX] = 0;
769 fabric->info.link_info.clk[ACTIVE_CTX] = 0;
770 fabric->info.link_info.bw[ACTIVE_CTX] = 0;
771
Gagan Mac7fbccf92012-12-12 23:49:58 -0700772 /* If possible, get pdata from device-tree */
773 if (pdev->dev.of_node) {
Gagan Mac7c7e5542012-12-19 19:28:47 -0700774 pdata = msm_bus_of_get_fab_data(pdev);
Gagan Mac7fbccf92012-12-12 23:49:58 -0700775 if (IS_ERR(pdata) || ZERO_OR_NULL_PTR(pdata)) {
776 pr_err("Null platform data\n");
Syed Rameez Mustafaa62baec2013-10-16 15:27:07 -0700777 kfree(fabric->info.node_info);
778 kfree(fabric);
Gagan Mac7fbccf92012-12-12 23:49:58 -0700779 return PTR_ERR(pdata);
780 }
Gagan Mac7c7e5542012-12-19 19:28:47 -0700781 msm_bus_board_init(pdata);
Gagan Mac7fbccf92012-12-12 23:49:58 -0700782 fabric->fabdev.id = pdata->id;
783 } else {
784 pdata = (struct msm_bus_fabric_registration *)pdev->
785 dev.platform_data;
786 fabric->fabdev.id = pdev->id;
787 }
788
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700789 fabric->fabdev.name = pdata->name;
790 fabric->fabdev.algo = &msm_bus_algo;
Gagan Mac7fbccf92012-12-12 23:49:58 -0700791 fabric->info.node_info->priv_id = fabric->fabdev.id;
792 fabric->info.node_info->id = fabric->fabdev.id;
Gagan Mac47a999a2012-01-18 20:36:12 -0700793 ret = msm_bus_fabric_hw_init(pdata, &fabric->fabdev.hw_algo);
794 if (ret) {
795 MSM_BUS_ERR("Error initializing hardware for fabric: %d\n",
796 fabric->fabdev.id);
797 goto err;
798 }
799
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700800 fabric->ahb = pdata->ahb;
801 fabric->pdata = pdata;
Gagan Macae154c4b2011-10-05 19:24:43 -0600802 fabric->pdata->board_algo->assign_iids(fabric->pdata,
803 fabric->fabdev.id);
804 fabric->fabdev.board_algo = fabric->pdata->board_algo;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700805
Matt Wagantallb2710b82011-11-16 19:55:17 -0800806 /*
807 * clk and bw for fabric->info will contain the max bw and clk
808 * it will allow. This info will come from the boards file.
809 */
810 ret = msm_bus_fabric_device_register(&fabric->fabdev);
811 if (ret) {
812 MSM_BUS_ERR("Error registering fabric %d ret %d\n",
813 fabric->fabdev.id, ret);
814 goto err;
815 }
816
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700817 for (ctx = 0; ctx < NUM_CTX; ctx++) {
818 if (pdata->fabclk[ctx]) {
Matt Wagantallb2710b82011-11-16 19:55:17 -0800819 fabric->info.nodeclk[ctx].clk = clk_get(
820 &fabric->fabdev.dev, pdata->fabclk[ctx]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700821 if (IS_ERR(fabric->info.nodeclk[ctx].clk)) {
822 MSM_BUS_ERR("Couldn't get clock %s\n",
823 pdata->fabclk[ctx]);
824 ret = -EINVAL;
825 goto err;
826 }
827 fabric->info.nodeclk[ctx].enable = false;
828 fabric->info.nodeclk[ctx].dirty = false;
829 }
830 }
831
832 /* Find num. of slaves, masters, populate gateways, radix tree */
Gagan Mac47a999a2012-01-18 20:36:12 -0700833 ret = register_fabric_info(pdev, fabric);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700834 if (ret) {
835 MSM_BUS_ERR("Could not register fabric %d info, ret: %d\n",
836 fabric->fabdev.id, ret);
837 goto err;
838 }
839 if (!fabric->ahb) {
840 /* Allocate memory for commit data */
841 for (ctx = 0; ctx < NUM_CTX; ctx++) {
Gagan Mac47a999a2012-01-18 20:36:12 -0700842 ret = fabric->fabdev.hw_algo.allocate_commit_data(
843 fabric->pdata, &fabric->cdata[ctx], ctx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700844 if (ret) {
845 MSM_BUS_ERR("Failed to alloc commit data for "
846 "fab: %d, ret = %d\n",
847 fabric->fabdev.id, ret);
848 goto err;
849 }
850 }
851 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700852
Gagan Macccd14022013-01-30 17:18:14 -0700853 if (msmbus_coresight_init(pdev))
854 pr_warn("Coresight support absent for bus: %d\n", pdata->id);
855
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700856 return ret;
857err:
858 kfree(fabric->info.node_info);
859 kfree(fabric);
860 return ret;
861}
862
863static int msm_bus_fabric_remove(struct platform_device *pdev)
864{
865 struct msm_bus_fabric_device *fabdev = NULL;
866 struct msm_bus_fabric *fabric;
867 int i;
868 int ret = 0;
869
870 fabdev = platform_get_drvdata(pdev);
Gagan Macccd14022013-01-30 17:18:14 -0700871 msmbus_coresight_remove(pdev);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700872 msm_bus_fabric_device_unregister(fabdev);
873 fabric = to_msm_bus_fabric(fabdev);
874 msm_bus_dbg_commit_data(fabric->fabdev.name, NULL, 0, 0, 0,
875 MSM_BUS_DBG_UNREGISTER);
876 for (i = 0; i < fabric->pdata->nmasters; i++)
877 radix_tree_delete(&fabric->fab_tree, fabric->fabdev.id + i);
878 for (i = (fabric->fabdev.id + SLAVE_ID_KEY); i <
879 fabric->pdata->nslaves; i++)
880 radix_tree_delete(&fabric->fab_tree, i);
881 if (!fabric->ahb) {
Gagan Mac47a999a2012-01-18 20:36:12 -0700882 fabdev->hw_algo.free_commit_data(fabric->cdata[DUAL_CTX]);
883 fabdev->hw_algo.free_commit_data(fabric->cdata[ACTIVE_CTX]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700884 }
885
886 kfree(fabric->info.node_info);
Gagan Mac47a999a2012-01-18 20:36:12 -0700887 kfree(fabric->hw_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700888 kfree(fabric);
889 return ret;
890}
891
Gagan Mac7fbccf92012-12-12 23:49:58 -0700892static struct of_device_id fabric_match[] = {
Gagan Mac7c7e5542012-12-19 19:28:47 -0700893 {.compatible = "msm-bus-fabric"},
Gagan Mac7fbccf92012-12-12 23:49:58 -0700894 {}
895};
896
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700897static struct platform_driver msm_bus_fabric_driver = {
898 .probe = msm_bus_fabric_probe,
899 .remove = msm_bus_fabric_remove,
900 .driver = {
Gagan Mac7e28f182013-02-14 17:16:34 -0700901 .name = "msm_bus_fabric",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700902 .owner = THIS_MODULE,
Gagan Mac7fbccf92012-12-12 23:49:58 -0700903 .of_match_table = fabric_match,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700904 },
905};
906
Ke Liue7150d12013-12-10 10:59:57 -0800907int __init msm_bus_fabric_init_driver(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700908{
Ke Liue7150d12013-12-10 10:59:57 -0800909 static bool initialized;
910
911 if (initialized)
912 return 0;
913 else
914 initialized = true;
915
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700916 MSM_BUS_ERR("msm_bus_fabric_init_driver\n");
917 return platform_driver_register(&msm_bus_fabric_driver);
918}
Ke Liue7150d12013-12-10 10:59:57 -0800919EXPORT_SYMBOL(msm_bus_fabric_init_driver);
Gagan Mac51b1bbf2013-01-02 15:29:38 -0700920subsys_initcall(msm_bus_fabric_init_driver);