blob: c00749c76031897da28cf9bb0ab4ac619f3f7289 [file] [log] [blame]
David Dai3734dab2018-01-09 11:21:11 -08001/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
David Dai04ce4202016-09-26 16:24:13 -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
13#include <linux/clk.h>
14#include <linux/device.h>
15#include <linux/init.h>
16#include <linux/io.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/slab.h>
David Dai0d014432016-11-10 12:57:44 -080020#include <soc/qcom/cmd-db.h>
21#include <soc/qcom/rpmh.h>
22#include <soc/qcom/tcs.h>
David Dai04ce4202016-09-26 16:24:13 -070023#include <trace/events/trace_msm_bus.h>
24#include "msm_bus_core.h"
25#include "msm_bus_rpmh.h"
26#include "msm_bus_noc.h"
27#include "msm_bus_bimc.h"
28
29#define BCM_TCS_CMD_COMMIT_SHFT 30
David Dai0d014432016-11-10 12:57:44 -080030#define BCM_TCS_CMD_COMMIT_MASK 0x40000000
David Dai04ce4202016-09-26 16:24:13 -070031#define BCM_TCS_CMD_VALID_SHFT 29
David Dai0d014432016-11-10 12:57:44 -080032#define BCM_TCS_CMD_VALID_MASK 0x20000000
David Dai04ce4202016-09-26 16:24:13 -070033#define BCM_TCS_CMD_VOTE_X_SHFT 14
David Dai04ce4202016-09-26 16:24:13 -070034#define BCM_TCS_CMD_VOTE_MASK 0x3FFF
David Dai0d014432016-11-10 12:57:44 -080035#define BCM_TCS_CMD_VOTE_Y_SHFT 0
36#define BCM_TCS_CMD_VOTE_Y_MASK 0xFFFC000
David Dai04ce4202016-09-26 16:24:13 -070037
David Dai04ce4202016-09-26 16:24:13 -070038#define BCM_TCS_CMD(commit, valid, vote_x, vote_y) \
39 (((commit & 0x1) << BCM_TCS_CMD_COMMIT_SHFT) |\
40 ((valid & 0x1) << BCM_TCS_CMD_VALID_SHFT) |\
41 ((vote_x & BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_X_SHFT) |\
42 ((vote_y & BCM_TCS_CMD_VOTE_MASK) << BCM_TCS_CMD_VOTE_Y_SHFT))
43
44static int msm_bus_dev_init_qos(struct device *dev, void *data);
45
David Dai1999c042017-02-27 12:51:09 -080046static struct list_head bcm_query_list_inorder[VCD_MAX_CNT];
47static struct msm_bus_node_device_type *cur_rsc;
David Dai62c04a62017-04-12 19:05:49 -070048static bool init_time = true;
David Dai04ce4202016-09-26 16:24:13 -070049
David Dai0d014432016-11-10 12:57:44 -080050struct bcm_db {
51 uint32_t unit_size;
52 uint16_t width;
53 uint8_t clk_domain;
54 uint8_t reserved;
David Dai04ce4202016-09-26 16:24:13 -070055};
56
57ssize_t bw_show(struct device *dev, struct device_attribute *attr,
58 char *buf)
59{
60 struct msm_bus_node_info_type *node_info = NULL;
61 struct msm_bus_node_device_type *bus_node = NULL;
62 int i;
63 int off = 0;
64
65 bus_node = to_msm_bus_node(dev);
66 if (!bus_node)
67 return -EINVAL;
68
69 node_info = bus_node->node_info;
70
71 for (i = 0; i < bus_node->num_lnodes; i++) {
72 if (!bus_node->lnode_list[i].in_use)
73 continue;
74 off += scnprintf((buf + off), PAGE_SIZE,
75 "[%d]:%s:Act_IB %llu Act_AB %llu Slp_IB %llu Slp_AB %llu\n",
76 i, bus_node->lnode_list[i].cl_name,
77 bus_node->lnode_list[i].lnode_ib[ACTIVE_CTX],
78 bus_node->lnode_list[i].lnode_ab[ACTIVE_CTX],
79 bus_node->lnode_list[i].lnode_ib[DUAL_CTX],
80 bus_node->lnode_list[i].lnode_ab[DUAL_CTX]);
81 trace_printk(
82 "[%d]:%s:Act_IB %llu Act_AB %llu Slp_IB %llu Slp_AB %llu\n",
83 i, bus_node->lnode_list[i].cl_name,
84 bus_node->lnode_list[i].lnode_ib[ACTIVE_CTX],
85 bus_node->lnode_list[i].lnode_ab[ACTIVE_CTX],
86 bus_node->lnode_list[i].lnode_ib[DUAL_CTX],
87 bus_node->lnode_list[i].lnode_ab[DUAL_CTX]);
88 }
89 off += scnprintf((buf + off), PAGE_SIZE,
90 "Max_Act_IB %llu Sum_Act_AB %llu Act_Util_fact %d Act_Vrail_comp %d\n",
91 bus_node->node_bw[ACTIVE_CTX].max_ib,
92 bus_node->node_bw[ACTIVE_CTX].sum_ab,
93 bus_node->node_bw[ACTIVE_CTX].util_used,
94 bus_node->node_bw[ACTIVE_CTX].vrail_used);
95 off += scnprintf((buf + off), PAGE_SIZE,
96 "Max_Slp_IB %llu Sum_Slp_AB %llu Slp_Util_fact %d Slp_Vrail_comp %d\n",
97 bus_node->node_bw[DUAL_CTX].max_ib,
98 bus_node->node_bw[DUAL_CTX].sum_ab,
99 bus_node->node_bw[DUAL_CTX].util_used,
100 bus_node->node_bw[DUAL_CTX].vrail_used);
101 trace_printk(
102 "Max_Act_IB %llu Sum_Act_AB %llu Act_Util_fact %d Act_Vrail_comp %d\n",
103 bus_node->node_bw[ACTIVE_CTX].max_ib,
104 bus_node->node_bw[ACTIVE_CTX].sum_ab,
105 bus_node->node_bw[ACTIVE_CTX].util_used,
106 bus_node->node_bw[ACTIVE_CTX].vrail_used);
107 trace_printk(
108 "Max_Slp_IB %llu Sum_Slp_AB %lluSlp_Util_fact %d Slp_Vrail_comp %d\n",
109 bus_node->node_bw[DUAL_CTX].max_ib,
110 bus_node->node_bw[DUAL_CTX].sum_ab,
111 bus_node->node_bw[DUAL_CTX].util_used,
112 bus_node->node_bw[DUAL_CTX].vrail_used);
113 return off;
114}
115
116ssize_t bw_store(struct device *dev, struct device_attribute *attr,
117 const char *buf, size_t count)
118{
119 return count;
120}
121
122DEVICE_ATTR(bw, 0600, bw_show, bw_store);
123
124struct static_rules_type {
125 int num_rules;
126 struct bus_rule_type *rules;
127};
128
129static struct static_rules_type static_rules;
130
131static int bus_get_reg(struct nodeclk *nclk, struct device *dev)
132{
133 int ret = 0;
134 struct msm_bus_node_device_type *node_dev;
135
136 if (!(dev && nclk))
137 return -ENXIO;
138
139 node_dev = to_msm_bus_node(dev);
140 if (!strlen(nclk->reg_name)) {
141 dev_dbg(dev, "No regulator exist for node %d\n",
142 node_dev->node_info->id);
143 goto exit_of_get_reg;
144 } else {
145 if (!(IS_ERR_OR_NULL(nclk->reg)))
146 goto exit_of_get_reg;
147
148 nclk->reg = devm_regulator_get(dev, nclk->reg_name);
149 if (IS_ERR_OR_NULL(nclk->reg)) {
150 ret =
151 (IS_ERR(nclk->reg) ? PTR_ERR(nclk->reg) : -ENXIO);
152 dev_err(dev, "Error: Failed to get regulator %s:%d\n",
153 nclk->reg_name, ret);
154 } else {
155 dev_dbg(dev, "Successfully got regulator for %d\n",
156 node_dev->node_info->id);
157 }
158 }
159
160exit_of_get_reg:
161 return ret;
162}
163
164static int bus_enable_reg(struct nodeclk *nclk)
165{
166 int ret = 0;
167
168 if (!nclk) {
169 ret = -ENXIO;
170 goto exit_bus_enable_reg;
171 }
172
173 if ((IS_ERR_OR_NULL(nclk->reg))) {
174 ret = -ENXIO;
175 goto exit_bus_enable_reg;
176 }
177
178 ret = regulator_enable(nclk->reg);
179 if (ret) {
180 MSM_BUS_ERR("Failed to enable regulator for %s\n",
181 nclk->reg_name);
182 goto exit_bus_enable_reg;
183 }
184 pr_debug("%s: Enabled Reg\n", __func__);
185exit_bus_enable_reg:
186 return ret;
187}
188
189static int bus_disable_reg(struct nodeclk *nclk)
190{
191 int ret = 0;
192
193 if (!nclk) {
194 ret = -ENXIO;
195 goto exit_bus_disable_reg;
196 }
197
198 if ((IS_ERR_OR_NULL(nclk->reg))) {
199 ret = -ENXIO;
200 goto exit_bus_disable_reg;
201 }
202
203 regulator_disable(nclk->reg);
204 pr_debug("%s: Disabled Reg\n", __func__);
205exit_bus_disable_reg:
206 return ret;
207}
208
209static int enable_nodeclk(struct nodeclk *nclk, struct device *dev)
210{
211 int ret = 0;
212
213 if (!nclk->enable && !nclk->setrate_only_clk) {
214 if (dev && strlen(nclk->reg_name)) {
215 if (IS_ERR_OR_NULL(nclk->reg)) {
216 ret = bus_get_reg(nclk, dev);
217 if (ret) {
218 dev_dbg(dev,
219 "Failed to get reg.Err %d\n",
220 ret);
221 goto exit_enable_nodeclk;
222 }
223 }
224
225 ret = bus_enable_reg(nclk);
226 if (ret) {
227 dev_dbg(dev, "Failed to enable reg. Err %d\n",
228 ret);
229 goto exit_enable_nodeclk;
230 }
231 }
232 ret = clk_prepare_enable(nclk->clk);
233
234 if (ret) {
235 MSM_BUS_ERR("%s: failed to enable clk ", __func__);
236 nclk->enable = false;
237 } else
238 nclk->enable = true;
239 }
240exit_enable_nodeclk:
241 return ret;
242}
243
244static int disable_nodeclk(struct nodeclk *nclk)
245{
246 int ret = 0;
247
248 if (nclk->enable && !nclk->setrate_only_clk) {
249 clk_disable_unprepare(nclk->clk);
250 nclk->enable = false;
251 bus_disable_reg(nclk);
252 }
253 return ret;
254}
255
256static int setrate_nodeclk(struct nodeclk *nclk, long rate)
257{
258 int ret = 0;
259
260 if (!nclk->enable_only_clk)
261 ret = clk_set_rate(nclk->clk, rate);
262
263 if (ret)
264 MSM_BUS_ERR("%s: failed to setrate clk", __func__);
265 return ret;
266}
267
268static int tcs_cmd_gen(struct msm_bus_node_device_type *cur_bcm,
David Daibee66232017-03-31 19:05:39 -0700269 struct tcs_cmd *cmd, uint64_t vec_a,
270 uint64_t vec_b, bool commit)
David Dai04ce4202016-09-26 16:24:13 -0700271{
272 int ret = 0;
David Dai04ce4202016-09-26 16:24:13 -0700273 bool valid = true;
274
David Daib4aff8b2017-04-11 19:36:53 -0700275 if (!cmd)
276 return ret;
277
David Daibee66232017-03-31 19:05:39 -0700278 if (vec_a == 0 && vec_b == 0)
David Dai04ce4202016-09-26 16:24:13 -0700279 valid = false;
David Dai04ce4202016-09-26 16:24:13 -0700280
David Daibee66232017-03-31 19:05:39 -0700281 if (vec_a > BCM_TCS_CMD_VOTE_MASK)
282 vec_a = BCM_TCS_CMD_VOTE_MASK;
David Dai04ce4202016-09-26 16:24:13 -0700283
David Daibee66232017-03-31 19:05:39 -0700284 if (vec_b > BCM_TCS_CMD_VOTE_MASK)
285 vec_b = BCM_TCS_CMD_VOTE_MASK;
David Dai04ce4202016-09-26 16:24:13 -0700286
David Dai0d014432016-11-10 12:57:44 -0800287 cmd->addr = cur_bcm->bcmdev->addr;
David Daibee66232017-03-31 19:05:39 -0700288 cmd->data = BCM_TCS_CMD(commit, valid, vec_a, vec_b);
David Dai0d014432016-11-10 12:57:44 -0800289 cmd->complete = commit;
David Dai04ce4202016-09-26 16:24:13 -0700290
291 return ret;
292}
293
David Dai0d014432016-11-10 12:57:44 -0800294static int tcs_cmd_list_gen(int *n_active,
295 int *n_wake,
296 int *n_sleep,
297 struct tcs_cmd *cmdlist_active,
298 struct tcs_cmd *cmdlist_wake,
David Dai1999c042017-02-27 12:51:09 -0800299 struct tcs_cmd *cmdlist_sleep,
300 struct list_head *cur_bcm_clist)
David Dai04ce4202016-09-26 16:24:13 -0700301{
302 struct msm_bus_node_device_type *cur_bcm = NULL;
David Dai04ce4202016-09-26 16:24:13 -0700303 int i = 0;
David Dai04ce4202016-09-26 16:24:13 -0700304 int k = 0;
David Dai0d014432016-11-10 12:57:44 -0800305 int idx = 0;
306 int last_tcs = -1;
307 bool commit = false;
David Dai04ce4202016-09-26 16:24:13 -0700308
David Dai0d014432016-11-10 12:57:44 -0800309 if (!cmdlist_active)
310 goto exit_tcs_cmd_list_gen;
David Dai04ce4202016-09-26 16:24:13 -0700311
312 for (i = 0; i < VCD_MAX_CNT; i++) {
David Dai0d014432016-11-10 12:57:44 -0800313 last_tcs = -1;
David Dai1999c042017-02-27 12:51:09 -0800314 if (list_empty(&cur_bcm_clist[i]))
David Dai04ce4202016-09-26 16:24:13 -0700315 continue;
David Dai1999c042017-02-27 12:51:09 -0800316 list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) {
David Dai903f6832017-04-20 18:14:26 -0700317 if (cur_bcm->updated ||
318 (cur_bcm->node_vec[DUAL_CTX].vec_a == 0 &&
319 cur_bcm->node_vec[ACTIVE_CTX].vec_a == 0 &&
320 cur_bcm->node_vec[DUAL_CTX].vec_b == 0 &&
321 cur_bcm->node_vec[ACTIVE_CTX].vec_b == 0 &&
322 init_time == true)) {
David Dai0d014432016-11-10 12:57:44 -0800323 if (last_tcs != -1 &&
324 list_is_last(&cur_bcm->link,
David Dai1999c042017-02-27 12:51:09 -0800325 &cur_bcm_clist[i])) {
David Dai0d014432016-11-10 12:57:44 -0800326 cmdlist_active[last_tcs].data |=
327 BCM_TCS_CMD_COMMIT_MASK;
328 cmdlist_active[last_tcs].complete
329 = true;
330 }
331 continue;
David Dai04ce4202016-09-26 16:24:13 -0700332 }
David Dai0d014432016-11-10 12:57:44 -0800333 n_active[idx]++;
334 commit = false;
335 if (list_is_last(&cur_bcm->link,
David Dai1999c042017-02-27 12:51:09 -0800336 &cur_bcm_clist[i])) {
David Dai0d014432016-11-10 12:57:44 -0800337 commit = true;
338 idx++;
339 }
340 tcs_cmd_gen(cur_bcm, &cmdlist_active[k],
David Daibee66232017-03-31 19:05:39 -0700341 cur_bcm->node_vec[ACTIVE_CTX].vec_a,
342 cur_bcm->node_vec[ACTIVE_CTX].vec_b, commit);
David Dai0d014432016-11-10 12:57:44 -0800343 last_tcs = k;
David Dai2cff2562017-05-02 17:15:49 -0700344 k++;
David Dai1999c042017-02-27 12:51:09 -0800345 cur_bcm->updated = true;
David Dai0d014432016-11-10 12:57:44 -0800346 }
347 }
348
349 if (!cmdlist_wake || !cmdlist_sleep)
350 goto exit_tcs_cmd_list_gen;
351
352 k = 0;
353 idx = 0;
354 for (i = 0; i < VCD_MAX_CNT; i++) {
355 last_tcs = -1;
David Dai1999c042017-02-27 12:51:09 -0800356 if (list_empty(&cur_bcm_clist[i]))
David Dai0d014432016-11-10 12:57:44 -0800357 continue;
David Dai1999c042017-02-27 12:51:09 -0800358 list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) {
David Dai0d014432016-11-10 12:57:44 -0800359 commit = false;
David Daibee66232017-03-31 19:05:39 -0700360 if ((cur_bcm->node_vec[DUAL_CTX].vec_a ==
361 cur_bcm->node_vec[ACTIVE_CTX].vec_a) &&
362 (cur_bcm->node_vec[DUAL_CTX].vec_b ==
363 cur_bcm->node_vec[ACTIVE_CTX].vec_b)) {
David Dai0d014432016-11-10 12:57:44 -0800364 if (last_tcs != -1 &&
365 list_is_last(&cur_bcm->link,
David Dai1999c042017-02-27 12:51:09 -0800366 &cur_bcm_clist[i])) {
David Dai903f6832017-04-20 18:14:26 -0700367 cmdlist_wake[last_tcs].data |=
David Dai0d014432016-11-10 12:57:44 -0800368 BCM_TCS_CMD_COMMIT_MASK;
David Dai903f6832017-04-20 18:14:26 -0700369 cmdlist_sleep[last_tcs].data |=
David Dai0d014432016-11-10 12:57:44 -0800370 BCM_TCS_CMD_COMMIT_MASK;
David Dai903f6832017-04-20 18:14:26 -0700371 cmdlist_wake[last_tcs].complete = true;
372 cmdlist_sleep[last_tcs].complete = true;
David Dai0d014432016-11-10 12:57:44 -0800373 idx++;
374 }
David Dai04ce4202016-09-26 16:24:13 -0700375 continue;
David Dai0d014432016-11-10 12:57:44 -0800376 }
377 last_tcs = k;
378 n_sleep[idx]++;
David Dai903f6832017-04-20 18:14:26 -0700379 n_wake[idx]++;
David Dai0d014432016-11-10 12:57:44 -0800380 if (list_is_last(&cur_bcm->link,
David Dai1999c042017-02-27 12:51:09 -0800381 &cur_bcm_clist[i])) {
David Dai0d014432016-11-10 12:57:44 -0800382 commit = true;
383 idx++;
384 }
David Dai04ce4202016-09-26 16:24:13 -0700385
David Dai0d014432016-11-10 12:57:44 -0800386 tcs_cmd_gen(cur_bcm, &cmdlist_wake[k],
David Daibee66232017-03-31 19:05:39 -0700387 cur_bcm->node_vec[ACTIVE_CTX].vec_a,
388 cur_bcm->node_vec[ACTIVE_CTX].vec_b, commit);
David Daif76f3e12017-06-30 11:58:09 -0700389
390 if (cur_rsc->rscdev->req_state == RPMH_AWAKE_STATE)
391 commit = false;
392
David Dai0d014432016-11-10 12:57:44 -0800393 tcs_cmd_gen(cur_bcm, &cmdlist_sleep[k],
David Daibee66232017-03-31 19:05:39 -0700394 cur_bcm->node_vec[DUAL_CTX].vec_a,
395 cur_bcm->node_vec[DUAL_CTX].vec_b, commit);
David Dai04ce4202016-09-26 16:24:13 -0700396 k++;
397 }
398 }
David Dai0d014432016-11-10 12:57:44 -0800399
400exit_tcs_cmd_list_gen:
401 return k;
David Dai04ce4202016-09-26 16:24:13 -0700402}
403
David Dai9d66f3f2016-11-23 15:33:06 -0800404static int tcs_cmd_query_list_gen(struct tcs_cmd *cmdlist_active)
405{
406 struct msm_bus_node_device_type *cur_bcm = NULL;
407 struct list_head *bcm_list_inorder = NULL;
408 int i = 0;
409 int k = 0;
410 bool commit = false;
411 int ret = 0;
412
413 if (!cmdlist_active)
414 goto exit_tcs_cmd_list_gen;
415
416 bcm_list_inorder = bcm_query_list_inorder;
417
418 for (i = 0; i < VCD_MAX_CNT; i++) {
419 if (list_empty(&bcm_list_inorder[i]))
420 continue;
421 list_for_each_entry(cur_bcm, &bcm_list_inorder[i], query_link) {
422 commit = false;
423 if (list_is_last(&cur_bcm->query_link,
424 &bcm_list_inorder[i])) {
425 commit = true;
426 }
427 tcs_cmd_gen(cur_bcm, &cmdlist_active[k],
David Daia55b46e2017-05-08 10:31:31 -0700428 cur_bcm->node_vec[ACTIVE_CTX].query_vec_a,
429 cur_bcm->node_vec[ACTIVE_CTX].query_vec_b,
David Dai9d66f3f2016-11-23 15:33:06 -0800430 commit);
431 k++;
432 }
433 }
434
435exit_tcs_cmd_list_gen:
436 return ret;
437}
438
David Dai04ce4202016-09-26 16:24:13 -0700439static int bcm_clist_add(struct msm_bus_node_device_type *cur_dev)
440{
441 int ret = 0;
442 int cur_vcd = 0;
David Daia55b46e2017-05-08 10:31:31 -0700443 int i = 0;
David Dai04ce4202016-09-26 16:24:13 -0700444 struct msm_bus_node_device_type *cur_bcm = NULL;
David Dai04ce4202016-09-26 16:24:13 -0700445
446 if (!cur_dev->node_info->num_bcm_devs)
447 goto exit_bcm_clist_add;
448
David Daia55b46e2017-05-08 10:31:31 -0700449 for (i = 0; i < cur_dev->node_info->num_bcm_devs; i++) {
450 cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[i]);
451 cur_vcd = cur_bcm->bcmdev->clk_domain;
David Dai04ce4202016-09-26 16:24:13 -0700452
David Daia55b46e2017-05-08 10:31:31 -0700453 if (!cur_bcm->node_info->num_rsc_devs)
454 goto exit_bcm_clist_add;
David Dai1999c042017-02-27 12:51:09 -0800455
David Daia55b46e2017-05-08 10:31:31 -0700456 if (!cur_rsc)
457 cur_rsc = to_msm_bus_node(cur_bcm->node_info->
458 rsc_devs[0]);
David Dai1999c042017-02-27 12:51:09 -0800459
David Daia55b46e2017-05-08 10:31:31 -0700460 if (!cur_bcm->dirty) {
461 list_add_tail(&cur_bcm->link,
David Dai1999c042017-02-27 12:51:09 -0800462 &cur_rsc->rscdev->bcm_clist[cur_vcd]);
David Daia55b46e2017-05-08 10:31:31 -0700463 cur_bcm->dirty = true;
464 }
465 cur_bcm->updated = false;
David Dai1999c042017-02-27 12:51:09 -0800466 }
David Dai0d014432016-11-10 12:57:44 -0800467
468exit_bcm_clist_add:
469 return ret;
470}
471
David Dai9d66f3f2016-11-23 15:33:06 -0800472static int bcm_query_list_add(struct msm_bus_node_device_type *cur_dev)
473{
474 int ret = 0;
475 int cur_vcd = 0;
David Daia55b46e2017-05-08 10:31:31 -0700476 int i = 0;
David Dai9d66f3f2016-11-23 15:33:06 -0800477 struct msm_bus_node_device_type *cur_bcm = NULL;
478
479 if (!cur_dev->node_info->num_bcm_devs)
480 goto exit_bcm_query_list_add;
481
David Daia55b46e2017-05-08 10:31:31 -0700482 for (i = 0; i < cur_dev->node_info->num_bcm_devs; i++) {
483 cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[i]);
484 cur_vcd = cur_bcm->bcmdev->clk_domain;
David Dai9d66f3f2016-11-23 15:33:06 -0800485
David Daia55b46e2017-05-08 10:31:31 -0700486 if (!cur_bcm->query_dirty)
487 list_add_tail(&cur_bcm->query_link,
David Dai9d66f3f2016-11-23 15:33:06 -0800488 &bcm_query_list_inorder[cur_vcd]);
David Daia55b46e2017-05-08 10:31:31 -0700489 }
David Dai9d66f3f2016-11-23 15:33:06 -0800490
491exit_bcm_query_list_add:
492 return ret;
493}
494
David Dai0d014432016-11-10 12:57:44 -0800495static int bcm_clist_clean(struct msm_bus_node_device_type *cur_dev)
496{
497 int ret = 0;
David Daia55b46e2017-05-08 10:31:31 -0700498 int i = 0;
David Dai0d014432016-11-10 12:57:44 -0800499 struct msm_bus_node_device_type *cur_bcm = NULL;
500
501 if (!cur_dev->node_info->num_bcm_devs)
David Dai1999c042017-02-27 12:51:09 -0800502 goto exit_bcm_clist_clean;
David Dai0d014432016-11-10 12:57:44 -0800503
David Daia55b46e2017-05-08 10:31:31 -0700504 for (i = 0; i < cur_dev->node_info->num_bcm_devs; i++) {
505 cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[i]);
David Dai0d014432016-11-10 12:57:44 -0800506
David Daia55b46e2017-05-08 10:31:31 -0700507 if (cur_bcm->node_vec[DUAL_CTX].vec_a == 0 &&
David Daibee66232017-03-31 19:05:39 -0700508 cur_bcm->node_vec[ACTIVE_CTX].vec_a == 0 &&
509 cur_bcm->node_vec[DUAL_CTX].vec_b == 0 &&
David Dai62c04a62017-04-12 19:05:49 -0700510 cur_bcm->node_vec[ACTIVE_CTX].vec_b == 0 &&
511 init_time == false) {
David Daia55b46e2017-05-08 10:31:31 -0700512 cur_bcm->dirty = false;
513 list_del_init(&cur_bcm->link);
514 }
David Dai0d014432016-11-10 12:57:44 -0800515 }
David Dai04ce4202016-09-26 16:24:13 -0700516
David Dai1999c042017-02-27 12:51:09 -0800517exit_bcm_clist_clean:
David Dai04ce4202016-09-26 16:24:13 -0700518 return ret;
519}
520
David Dai9d66f3f2016-11-23 15:33:06 -0800521static int bcm_query_list_clean(struct msm_bus_node_device_type *cur_dev)
522{
523 int ret = 0;
David Daia55b46e2017-05-08 10:31:31 -0700524 int i = 0;
David Dai9d66f3f2016-11-23 15:33:06 -0800525 struct msm_bus_node_device_type *cur_bcm = NULL;
526
527 if (!cur_dev->node_info->num_bcm_devs)
528 goto exit_bcm_clist_add;
529
David Daia55b46e2017-05-08 10:31:31 -0700530 for (i = 0; i < cur_dev->node_info->num_bcm_devs; i++) {
531 cur_bcm = to_msm_bus_node(cur_dev->node_info->bcm_devs[i]);
David Dai9d66f3f2016-11-23 15:33:06 -0800532
David Daia55b46e2017-05-08 10:31:31 -0700533 cur_bcm->query_dirty = false;
534 list_del_init(&cur_bcm->query_link);
535 }
David Dai9d66f3f2016-11-23 15:33:06 -0800536
537exit_bcm_clist_add:
538 return ret;
539}
540
David Dai04ce4202016-09-26 16:24:13 -0700541int msm_bus_commit_data(struct list_head *clist)
542{
543 int ret = 0;
544 int bcm_cnt;
David Dai0d014432016-11-10 12:57:44 -0800545 struct msm_bus_node_device_type *node = NULL;
546 struct msm_bus_node_device_type *node_tmp = NULL;
547 struct msm_bus_node_device_type *cur_bcm = NULL;
548 struct tcs_cmd *cmdlist_active = NULL;
549 struct tcs_cmd *cmdlist_wake = NULL;
550 struct tcs_cmd *cmdlist_sleep = NULL;
David Dai1408be02017-02-02 18:44:05 -0800551 struct rpmh_client *cur_mbox = NULL;
David Dai1999c042017-02-27 12:51:09 -0800552 struct list_head *cur_bcm_clist = NULL;
David Dai3734dab2018-01-09 11:21:11 -0800553 int n_active[VCD_MAX_CNT];
554 int n_wake[VCD_MAX_CNT];
555 int n_sleep[VCD_MAX_CNT];
David Dai0d014432016-11-10 12:57:44 -0800556 int cnt_vcd = 0;
557 int cnt_active = 0;
558 int cnt_wake = 0;
559 int cnt_sleep = 0;
560 int i = 0;
David Dai04ce4202016-09-26 16:24:13 -0700561
David Daib68eece2017-07-07 12:07:05 -0700562 if (!clist)
563 return ret;
David Dai1999c042017-02-27 12:51:09 -0800564
David Dai04ce4202016-09-26 16:24:13 -0700565 list_for_each_entry_safe(node, node_tmp, clist, link) {
David Dai04ce4202016-09-26 16:24:13 -0700566 bcm_clist_add(node);
David Dai0d014432016-11-10 12:57:44 -0800567 }
David Dai04ce4202016-09-26 16:24:13 -0700568
Maria Yucd1a4792017-09-14 23:55:15 +0800569 if (!cur_rsc) {
570 MSM_BUS_ERR("%s: Error for cur_rsc is NULL.\n", __func__);
571 return ret;
572 }
573
David Dai1999c042017-02-27 12:51:09 -0800574 cur_mbox = cur_rsc->rscdev->mbox;
575 cur_bcm_clist = cur_rsc->rscdev->bcm_clist;
David Dai3734dab2018-01-09 11:21:11 -0800576 cmdlist_active = cur_rsc->rscdev->cmdlist_active;
577 cmdlist_wake = cur_rsc->rscdev->cmdlist_wake;
578 cmdlist_sleep = cur_rsc->rscdev->cmdlist_sleep;
David Dai1999c042017-02-27 12:51:09 -0800579
David Dai0d014432016-11-10 12:57:44 -0800580 for (i = 0; i < VCD_MAX_CNT; i++) {
David Dai3734dab2018-01-09 11:21:11 -0800581 n_active[i] = 0;
582 n_wake[i] = 0;
583 n_sleep[i] = 0;
584
David Dai1999c042017-02-27 12:51:09 -0800585 if (list_empty(&cur_bcm_clist[i]))
David Dai0d014432016-11-10 12:57:44 -0800586 continue;
David Dai1999c042017-02-27 12:51:09 -0800587 list_for_each_entry(cur_bcm, &cur_bcm_clist[i], link) {
David Daibee66232017-03-31 19:05:39 -0700588 if ((cur_bcm->node_vec[DUAL_CTX].vec_a !=
589 cur_bcm->node_vec[ACTIVE_CTX].vec_a) ||
590 (cur_bcm->node_vec[DUAL_CTX].vec_b !=
591 cur_bcm->node_vec[ACTIVE_CTX].vec_b)) {
David Dai0d014432016-11-10 12:57:44 -0800592 cnt_sleep++;
593 cnt_wake++;
594 }
David Dai62c04a62017-04-12 19:05:49 -0700595 if (cur_bcm->updated ||
596 (cur_bcm->node_vec[DUAL_CTX].vec_a == 0 &&
597 cur_bcm->node_vec[ACTIVE_CTX].vec_a == 0 &&
598 cur_bcm->node_vec[DUAL_CTX].vec_b == 0 &&
599 cur_bcm->node_vec[ACTIVE_CTX].vec_b == 0 &&
600 init_time == true))
601 continue;
602 cnt_active++;
David Dai0d014432016-11-10 12:57:44 -0800603 }
604 cnt_vcd++;
605 }
606
David Dai6666e1e2017-08-10 17:30:34 -0700607 if (!cnt_active)
608 goto exit_msm_bus_commit_data;
609
David Dai0d014432016-11-10 12:57:44 -0800610 bcm_cnt = tcs_cmd_list_gen(n_active, n_wake, n_sleep, cmdlist_active,
David Dai1999c042017-02-27 12:51:09 -0800611 cmdlist_wake, cmdlist_sleep, cur_bcm_clist);
David Dai0d014432016-11-10 12:57:44 -0800612
David Dai1408be02017-02-02 18:44:05 -0800613 ret = rpmh_invalidate(cur_mbox);
David Daibabfac62017-07-14 14:47:42 -0700614 if (ret)
615 MSM_BUS_ERR("%s: Error invalidating mbox: %d\n",
616 __func__, ret);
617
David Daif1164752017-07-31 15:18:44 -0700618 if (cur_rsc->rscdev->req_state == RPMH_AWAKE_STATE) {
David Daieadc3542017-03-31 12:17:16 -0700619 ret = rpmh_write(cur_mbox, cur_rsc->rscdev->req_state,
620 cmdlist_active, cnt_active);
David Daif1164752017-07-31 15:18:44 -0700621 /*
622 * Ignore -EBUSY from rpmh_write if it's an AWAKE_STATE
623 * request since AWAKE requests are invalid when
624 * the display RSC is in solver mode and the bus driver
625 * does not know the current state of the display RSC.
626 */
627 if (ret && ret != -EBUSY)
628 MSM_BUS_ERR("%s: error sending active/awake sets: %d\n",
629 __func__, ret);
630 } else {
Lina Iyerc4f79472017-08-29 15:24:18 -0600631 ret = rpmh_write_batch(cur_mbox, cur_rsc->rscdev->req_state,
David Dai0d014432016-11-10 12:57:44 -0800632 cmdlist_active, n_active);
David Daif1164752017-07-31 15:18:44 -0700633 if (ret)
634 MSM_BUS_ERR("%s: error sending active/awake sets: %d\n",
David Daibabfac62017-07-14 14:47:42 -0700635 __func__, ret);
David Daif1164752017-07-31 15:18:44 -0700636 }
David Dai6666e1e2017-08-10 17:30:34 -0700637 if (cnt_wake) {
Lina Iyerc4f79472017-08-29 15:24:18 -0600638 ret = rpmh_write_batch(cur_mbox, RPMH_WAKE_ONLY_STATE,
David Dai6666e1e2017-08-10 17:30:34 -0700639 cmdlist_wake, n_wake);
640 if (ret)
641 MSM_BUS_ERR("%s: error sending wake sets: %d\n",
642 __func__, ret);
643 }
644 if (cnt_sleep) {
Lina Iyerc4f79472017-08-29 15:24:18 -0600645 ret = rpmh_write_batch(cur_mbox, RPMH_SLEEP_STATE,
David Dai6666e1e2017-08-10 17:30:34 -0700646 cmdlist_sleep, n_sleep);
647 if (ret)
648 MSM_BUS_ERR("%s: error sending sleep sets: %d\n",
649 __func__, ret);
David Dai04ce4202016-09-26 16:24:13 -0700650 }
David Dai0d014432016-11-10 12:57:44 -0800651
David Dai27ffa282017-08-04 12:25:17 -0700652 list_for_each_entry_safe(node, node_tmp, clist, link) {
653 if (unlikely(node->node_info->defer_qos))
654 msm_bus_dev_init_qos(&node->dev, NULL);
655 }
656
David Dai6666e1e2017-08-10 17:30:34 -0700657exit_msm_bus_commit_data:
658 list_for_each_entry_safe(node, node_tmp, clist, link) {
659 bcm_clist_clean(node);
660 node->dirty = false;
661 list_del_init(&node->link);
662 }
663 cur_rsc = NULL;
David Dai04ce4202016-09-26 16:24:13 -0700664 return ret;
665}
666
David Dai9d66f3f2016-11-23 15:33:06 -0800667int msm_bus_query_gen(struct list_head *query_list,
668 struct msm_bus_tcs_usecase *tcs_usecase)
669{
670 int ret = 0;
671 struct msm_bus_node_device_type *node = NULL;
672 struct msm_bus_node_device_type *node_tmp = NULL;
673 struct msm_bus_node_device_type *cur_bcm = NULL;
674 int *n_active = NULL;
675 int cnt_vcd = 0;
676 int cnt_active = 0;
677 int i = 0;
678
679 list_for_each_entry_safe(node, node_tmp, query_list, query_link)
680 bcm_query_list_add(node);
681
682 for (i = 0; i < VCD_MAX_CNT; i++) {
683 if (list_empty(&bcm_query_list_inorder[i]))
684 continue;
685 list_for_each_entry(cur_bcm, &bcm_query_list_inorder[i],
686 query_link) {
687 cnt_active++;
688 }
689 cnt_vcd++;
690 }
691
692 tcs_usecase->num_cmds = cnt_active;
693 ret = tcs_cmd_query_list_gen(tcs_usecase->cmds);
694
695 list_for_each_entry_safe(node, node_tmp, query_list, query_link) {
696 bcm_query_list_clean(node);
697 node->query_dirty = false;
698 list_del_init(&node->query_link);
699 }
700
701 kfree(n_active);
702 return ret;
703}
704
David Daib4aff8b2017-04-11 19:36:53 -0700705static void bcm_commit_single_req(struct msm_bus_node_device_type *cur_bcm,
706 uint64_t vec_a, uint64_t vec_b)
707{
708 struct msm_bus_node_device_type *cur_rsc = NULL;
709 struct rpmh_client *cur_mbox = NULL;
710 struct tcs_cmd *cmd_active = NULL;
David Dai9d66f3f2016-11-23 15:33:06 -0800711
David Daib4aff8b2017-04-11 19:36:53 -0700712 if (!cur_bcm->node_info->num_rsc_devs)
713 return;
714
715 cmd_active = kzalloc(sizeof(struct tcs_cmd), GFP_KERNEL);
716
717 if (!cmd_active)
718 return;
719
720 cur_rsc = to_msm_bus_node(cur_bcm->node_info->rsc_devs[0]);
721 cur_mbox = cur_rsc->rscdev->mbox;
722
723 tcs_cmd_gen(cur_bcm, cmd_active, vec_a, vec_b, true);
724 rpmh_write_single(cur_mbox, RPMH_ACTIVE_ONLY_STATE,
725 cmd_active->addr, cmd_active->data);
726
727 kfree(cmd_active);
728}
David Dai9d66f3f2016-11-23 15:33:06 -0800729
David Dai04ce4202016-09-26 16:24:13 -0700730void *msm_bus_realloc_devmem(struct device *dev, void *p, size_t old_size,
731 size_t new_size, gfp_t flags)
732{
733 void *ret;
734 size_t copy_size = old_size;
735
736 if (!new_size) {
737 devm_kfree(dev, p);
738 return ZERO_SIZE_PTR;
739 }
740
741 if (new_size < old_size)
742 copy_size = new_size;
743
744 ret = devm_kzalloc(dev, new_size, flags);
745 if (!ret) {
746 MSM_BUS_ERR("%s: Error Reallocating memory", __func__);
747 goto exit_realloc_devmem;
748 }
749
750 memcpy(ret, p, copy_size);
751 devm_kfree(dev, p);
752exit_realloc_devmem:
753 return ret;
754}
755
756static void msm_bus_fab_init_noc_ops(struct msm_bus_node_device_type *bus_dev)
757{
758 switch (bus_dev->fabdev->bus_type) {
759 case MSM_BUS_NOC:
760 msm_bus_noc_set_ops(bus_dev);
761 break;
762 case MSM_BUS_BIMC:
763 msm_bus_bimc_set_ops(bus_dev);
764 break;
765 default:
766 MSM_BUS_ERR("%s: Invalid Bus type", __func__);
767 }
768}
769
770static int msm_bus_disable_node_qos_clk(struct msm_bus_node_device_type *node)
771{
David Dai04ce4202016-09-26 16:24:13 -0700772 int i;
773 int ret = 0;
774
David Dai800de052017-07-15 13:19:30 -0700775 if (!node) {
David Dai04ce4202016-09-26 16:24:13 -0700776 ret = -ENXIO;
777 goto exit_disable_node_qos_clk;
778 }
David Dai04ce4202016-09-26 16:24:13 -0700779
David Dai800de052017-07-15 13:19:30 -0700780 for (i = 0; i < node->num_node_qos_clks; i++)
781 ret = disable_nodeclk(&node->node_qos_clks[i]);
David Dai04ce4202016-09-26 16:24:13 -0700782
783exit_disable_node_qos_clk:
784 return ret;
785}
786
787static int msm_bus_enable_node_qos_clk(struct msm_bus_node_device_type *node)
788{
David Dai04ce4202016-09-26 16:24:13 -0700789 int i;
David Daibabfac62017-07-14 14:47:42 -0700790 int ret = 0;
David Dai04ce4202016-09-26 16:24:13 -0700791 long rounded_rate;
792
David Daib4aff8b2017-04-11 19:36:53 -0700793 for (i = 0; i < node->num_node_qos_clks; i++) {
794 if (!node->node_qos_clks[i].enable_only_clk) {
David Dai04ce4202016-09-26 16:24:13 -0700795 rounded_rate =
796 clk_round_rate(
David Daib4aff8b2017-04-11 19:36:53 -0700797 node->node_qos_clks[i].clk, 1);
798 ret = setrate_nodeclk(&node->node_qos_clks[i],
David Dai04ce4202016-09-26 16:24:13 -0700799 rounded_rate);
800 if (ret)
801 MSM_BUS_DBG("%s: Failed set rate clk,node %d\n",
802 __func__, node->node_info->id);
803 }
David Daib4aff8b2017-04-11 19:36:53 -0700804 ret = enable_nodeclk(&node->node_qos_clks[i],
David Dai04ce4202016-09-26 16:24:13 -0700805 node->node_info->bus_device);
806 if (ret) {
807 MSM_BUS_DBG("%s: Failed to set Qos Clks ret %d\n",
808 __func__, ret);
809 msm_bus_disable_node_qos_clk(node);
810 goto exit_enable_node_qos_clk;
811 }
David Dai04ce4202016-09-26 16:24:13 -0700812 }
813exit_enable_node_qos_clk:
814 return ret;
815}
816
David Daib4aff8b2017-04-11 19:36:53 -0700817static int msm_bus_vote_qos_bcms(struct msm_bus_node_device_type *node)
818{
819 struct msm_bus_node_device_type *cur_dev = NULL;
820 struct msm_bus_node_device_type *cur_bcm = NULL;
821 int i;
822 struct device *dev = NULL;
823
824 if (!node || (!to_msm_bus_node(node->node_info->bus_device)))
825 return -ENXIO;
826
827 cur_dev = node;
828
829 for (i = 0; i < cur_dev->num_qos_bcms; i++) {
830 dev = bus_find_device(&msm_bus_type, NULL,
831 (void *) &cur_dev->qos_bcms[i].qos_bcm_id,
832 msm_bus_device_match_adhoc);
833
834 if (!dev) {
835 MSM_BUS_ERR("Can't find dev node for %d",
836 cur_dev->qos_bcms[i].qos_bcm_id);
837 return -ENODEV;
838 }
839
840 cur_bcm = to_msm_bus_node(dev);
841 if (cur_bcm->node_vec[ACTIVE_CTX].vec_a != 0 ||
842 cur_bcm->node_vec[ACTIVE_CTX].vec_b != 0 ||
843 cur_bcm->node_vec[DUAL_CTX].vec_a != 0 ||
844 cur_bcm->node_vec[DUAL_CTX].vec_b != 0)
845 return 0;
846
847 bcm_commit_single_req(cur_bcm,
848 cur_dev->qos_bcms[i].vec.vec_a,
849 cur_dev->qos_bcms[i].vec.vec_b);
850 }
851
852 return 0;
853}
854
855static int msm_bus_rm_vote_qos_bcms(struct msm_bus_node_device_type *node)
856{
857 struct msm_bus_node_device_type *cur_dev = NULL;
858 struct msm_bus_node_device_type *cur_bcm = NULL;
859 int i;
860 struct device *dev = NULL;
861
862 if (!node || (!to_msm_bus_node(node->node_info->bus_device)))
863 return -ENXIO;
864
865 cur_dev = node;
866
867 for (i = 0; i < cur_dev->num_qos_bcms; i++) {
868 dev = bus_find_device(&msm_bus_type, NULL,
869 (void *) &cur_dev->qos_bcms[i].qos_bcm_id,
870 msm_bus_device_match_adhoc);
871
872 if (!dev) {
873 MSM_BUS_ERR("Can't find dev node for %d",
874 cur_dev->qos_bcms[i].qos_bcm_id);
875 return -ENODEV;
876 }
877
878 cur_bcm = to_msm_bus_node(dev);
879 if (cur_bcm->node_vec[ACTIVE_CTX].vec_a != 0 ||
880 cur_bcm->node_vec[ACTIVE_CTX].vec_b != 0 ||
881 cur_bcm->node_vec[DUAL_CTX].vec_a != 0 ||
882 cur_bcm->node_vec[DUAL_CTX].vec_b != 0)
883 return 0;
884
885 bcm_commit_single_req(cur_bcm, 0, 0);
886 }
887
888 return 0;
889}
890
David Dai04ce4202016-09-26 16:24:13 -0700891int msm_bus_enable_limiter(struct msm_bus_node_device_type *node_dev,
892 int enable, uint64_t lim_bw)
893{
894 int ret = 0;
895 struct msm_bus_node_device_type *bus_node_dev;
896
897 if (!node_dev) {
898 MSM_BUS_ERR("No device specified");
899 ret = -ENXIO;
900 goto exit_enable_limiter;
901 }
902
903 if (!node_dev->ap_owned) {
904 MSM_BUS_ERR("Device is not AP owned %d",
905 node_dev->node_info->id);
906 ret = -ENXIO;
907 goto exit_enable_limiter;
908 }
909
910 bus_node_dev = to_msm_bus_node(node_dev->node_info->bus_device);
911 if (!bus_node_dev) {
912 MSM_BUS_ERR("Unable to get bus device infofor %d",
913 node_dev->node_info->id);
914 ret = -ENXIO;
915 goto exit_enable_limiter;
916 }
917 if (bus_node_dev->fabdev &&
918 bus_node_dev->fabdev->noc_ops.limit_mport) {
919 if (ret < 0) {
920 MSM_BUS_ERR("Can't Enable QoS clk %d",
921 node_dev->node_info->id);
922 goto exit_enable_limiter;
923 }
924 bus_node_dev->fabdev->noc_ops.limit_mport(
925 node_dev,
926 bus_node_dev->fabdev->qos_base,
927 bus_node_dev->fabdev->base_offset,
928 bus_node_dev->fabdev->qos_off,
929 bus_node_dev->fabdev->qos_freq,
930 enable, lim_bw);
931 }
932
933exit_enable_limiter:
934 return ret;
935}
936
937static int msm_bus_dev_init_qos(struct device *dev, void *data)
938{
939 int ret = 0;
940 struct msm_bus_node_device_type *node_dev = NULL;
941
942 node_dev = to_msm_bus_node(dev);
943 if (!node_dev) {
944 MSM_BUS_ERR("%s: Unable to get node device info", __func__);
945 ret = -ENXIO;
946 goto exit_init_qos;
947 }
948
949 MSM_BUS_DBG("Device = %d", node_dev->node_info->id);
950
David Dai27ffa282017-08-04 12:25:17 -0700951 if (node_dev->node_info->qos_params.defer_init_qos) {
952 node_dev->node_info->qos_params.defer_init_qos = false;
953 node_dev->node_info->defer_qos = true;
954 goto exit_init_qos;
955 }
956
David Dai04ce4202016-09-26 16:24:13 -0700957 if (node_dev->ap_owned) {
958 struct msm_bus_node_device_type *bus_node_info;
959
960 bus_node_info =
961 to_msm_bus_node(node_dev->node_info->bus_device);
962
963 if (!bus_node_info) {
964 MSM_BUS_ERR("%s: Unable to get bus device info for %d",
965 __func__,
966 node_dev->node_info->id);
967 ret = -ENXIO;
968 goto exit_init_qos;
969 }
970
971 if (bus_node_info->fabdev &&
972 bus_node_info->fabdev->noc_ops.qos_init) {
973 int ret = 0;
974
David Daib4aff8b2017-04-11 19:36:53 -0700975 if (node_dev->ap_owned) {
David Dai04ce4202016-09-26 16:24:13 -0700976 if (bus_node_info->fabdev->bypass_qos_prg)
977 goto exit_init_qos;
978
David Daib4aff8b2017-04-11 19:36:53 -0700979 ret = msm_bus_vote_qos_bcms(node_dev);
David Dai04ce4202016-09-26 16:24:13 -0700980 ret = msm_bus_enable_node_qos_clk(node_dev);
981 if (ret < 0) {
982 MSM_BUS_DBG("Can't Enable QoS clk %d\n",
983 node_dev->node_info->id);
984 node_dev->node_info->defer_qos = true;
985 goto exit_init_qos;
986 }
987
988 bus_node_info->fabdev->noc_ops.qos_init(
989 node_dev,
David Daiaf2e3792017-09-07 13:26:04 -0700990 bus_node_info,
David Dai04ce4202016-09-26 16:24:13 -0700991 bus_node_info->fabdev->qos_base,
992 bus_node_info->fabdev->base_offset,
993 bus_node_info->fabdev->qos_off,
994 bus_node_info->fabdev->qos_freq);
995 ret = msm_bus_disable_node_qos_clk(node_dev);
David Daib4aff8b2017-04-11 19:36:53 -0700996 ret = msm_bus_rm_vote_qos_bcms(node_dev);
David Dai04ce4202016-09-26 16:24:13 -0700997 node_dev->node_info->defer_qos = false;
998 }
999 } else
1000 MSM_BUS_ERR("%s: Skipping QOS init for %d",
1001 __func__, node_dev->node_info->id);
1002 }
1003exit_init_qos:
1004 return ret;
1005}
1006
1007static int msm_bus_fabric_init(struct device *dev,
1008 struct msm_bus_node_device_type *pdata)
1009{
1010 struct msm_bus_fab_device_type *fabdev;
1011 struct msm_bus_node_device_type *node_dev = NULL;
1012 int ret = 0;
1013
1014 node_dev = to_msm_bus_node(dev);
1015 if (!node_dev) {
1016 MSM_BUS_ERR("%s: Unable to get bus device info", __func__);
1017 ret = -ENXIO;
1018 goto exit_fabric_init;
1019 }
1020
1021 if (node_dev->node_info->virt_dev) {
1022 MSM_BUS_ERR("%s: Skip Fab init for virtual device %d", __func__,
1023 node_dev->node_info->id);
1024 goto exit_fabric_init;
1025 }
1026
1027 fabdev = devm_kzalloc(dev, sizeof(struct msm_bus_fab_device_type),
1028 GFP_KERNEL);
1029 if (!fabdev) {
1030 MSM_BUS_ERR("Fabric alloc failed\n");
1031 ret = -ENOMEM;
1032 goto exit_fabric_init;
1033 }
1034
1035 node_dev->fabdev = fabdev;
1036 fabdev->pqos_base = pdata->fabdev->pqos_base;
1037 fabdev->qos_range = pdata->fabdev->qos_range;
1038 fabdev->base_offset = pdata->fabdev->base_offset;
1039 fabdev->qos_off = pdata->fabdev->qos_off;
1040 fabdev->qos_freq = pdata->fabdev->qos_freq;
1041 fabdev->bus_type = pdata->fabdev->bus_type;
1042 fabdev->bypass_qos_prg = pdata->fabdev->bypass_qos_prg;
1043 msm_bus_fab_init_noc_ops(node_dev);
1044
1045 fabdev->qos_base = devm_ioremap(dev,
1046 fabdev->pqos_base, fabdev->qos_range);
1047 if (!fabdev->qos_base) {
1048 MSM_BUS_ERR("%s: Error remapping address 0x%zx :bus device %d",
1049 __func__,
1050 (size_t)fabdev->pqos_base, node_dev->node_info->id);
1051 ret = -ENOMEM;
1052 goto exit_fabric_init;
1053 }
1054
1055exit_fabric_init:
1056 return ret;
1057}
1058
1059static int msm_bus_bcm_init(struct device *dev,
1060 struct msm_bus_node_device_type *pdata)
1061{
1062 struct msm_bus_bcm_device_type *bcmdev;
1063 struct msm_bus_node_device_type *node_dev = NULL;
David Dai0d014432016-11-10 12:57:44 -08001064 struct bcm_db aux_data = {0};
David Dai04ce4202016-09-26 16:24:13 -07001065 int ret = 0;
David Dai0d014432016-11-10 12:57:44 -08001066 int i = 0;
David Dai04ce4202016-09-26 16:24:13 -07001067
1068 node_dev = to_msm_bus_node(dev);
1069 if (!node_dev) {
1070 ret = -ENXIO;
1071 goto exit_bcm_init;
1072 }
1073
1074 bcmdev = devm_kzalloc(dev, sizeof(struct msm_bus_bcm_device_type),
1075 GFP_KERNEL);
1076 if (!bcmdev) {
1077 ret = -ENOMEM;
1078 goto exit_bcm_init;
1079 }
1080
1081 node_dev->bcmdev = bcmdev;
David Dai1408be02017-02-02 18:44:05 -08001082 bcmdev->name = pdata->bcmdev->name;
1083
1084 if (!cmd_db_get_aux_data_len(bcmdev->name)) {
David Dai0d014432016-11-10 12:57:44 -08001085 MSM_BUS_ERR("%s: Error getting bcm info, bcm:%s",
David Dai1408be02017-02-02 18:44:05 -08001086 __func__, bcmdev->name);
David Dai0d014432016-11-10 12:57:44 -08001087 ret = -ENXIO;
1088 goto exit_bcm_init;
1089 }
David Dai04ce4202016-09-26 16:24:13 -07001090
David Dai1408be02017-02-02 18:44:05 -08001091 cmd_db_get_aux_data(bcmdev->name, (u8 *)&aux_data,
David Dai0d014432016-11-10 12:57:44 -08001092 sizeof(struct bcm_db));
1093
David Dai1408be02017-02-02 18:44:05 -08001094 bcmdev->addr = cmd_db_get_addr(bcmdev->name);
David Dai0d014432016-11-10 12:57:44 -08001095 bcmdev->width = (uint32_t)aux_data.width;
1096 bcmdev->clk_domain = aux_data.clk_domain;
1097 bcmdev->unit_size = aux_data.unit_size;
David Dai04ce4202016-09-26 16:24:13 -07001098 bcmdev->type = 0;
David Dai04ce4202016-09-26 16:24:13 -07001099 bcmdev->num_bus_devs = 0;
1100
1101 // Add way to count # of VCDs, initialize LL
David Dai9d66f3f2016-11-23 15:33:06 -08001102 for (i = 0; i < VCD_MAX_CNT; i++) {
David Dai9d66f3f2016-11-23 15:33:06 -08001103 INIT_LIST_HEAD(&bcm_query_list_inorder[i]);
1104 }
David Dai04ce4202016-09-26 16:24:13 -07001105
1106exit_bcm_init:
1107 return ret;
1108}
1109
David Dai1999c042017-02-27 12:51:09 -08001110static int msm_bus_rsc_init(struct platform_device *pdev,
1111 struct device *dev,
1112 struct msm_bus_node_device_type *pdata)
1113{
1114 struct msm_bus_rsc_device_type *rscdev;
1115 struct msm_bus_node_device_type *node_dev = NULL;
1116 int ret = 0;
1117 int i = 0;
David Dai04ce4202016-09-26 16:24:13 -07001118
David Dai1999c042017-02-27 12:51:09 -08001119 node_dev = to_msm_bus_node(dev);
1120 if (!node_dev) {
1121 ret = -ENXIO;
1122 goto exit_rsc_init;
1123 }
1124
1125 rscdev = devm_kzalloc(dev, sizeof(struct msm_bus_rsc_device_type),
1126 GFP_KERNEL);
1127 if (!rscdev) {
1128 ret = -ENOMEM;
1129 goto exit_rsc_init;
1130 }
1131
1132 node_dev->rscdev = rscdev;
1133 rscdev->req_state = pdata->rscdev->req_state;
1134 rscdev->mbox = rpmh_get_byname(pdev, node_dev->node_info->name);
1135
1136 if (IS_ERR_OR_NULL(rscdev->mbox)) {
1137 MSM_BUS_ERR("%s: Failed to get mbox:%s", __func__,
1138 node_dev->node_info->name);
David Dai1999c042017-02-27 12:51:09 -08001139 }
1140
1141 // Add way to count # of VCDs, initialize LL
1142 for (i = 0; i < VCD_MAX_CNT; i++)
1143 INIT_LIST_HEAD(&rscdev->bcm_clist[i]);
1144
1145exit_rsc_init:
1146 return ret;
1147}
David Dai04ce4202016-09-26 16:24:13 -07001148
David Dai3734dab2018-01-09 11:21:11 -08001149static int msm_bus_postcon_setup(struct device *bus_dev, void *data)
1150{
1151 struct msm_bus_node_device_type *bus_node = NULL;
1152 struct msm_bus_rsc_device_type *rscdev;
1153
1154 bus_node = to_msm_bus_node(bus_dev);
1155 if (!bus_node) {
1156 MSM_BUS_ERR("%s: Can't get device info", __func__);
1157 return -ENODEV;
1158 }
1159
1160 if (bus_node->node_info->is_rsc_dev) {
1161 rscdev = bus_node->rscdev;
1162 rscdev->cmdlist_active = devm_kcalloc(bus_dev,
1163 rscdev->num_bcm_devs,
1164 sizeof(struct tcs_cmd), GFP_KERNEL);
1165 if (!rscdev->cmdlist_active)
1166 return -ENOMEM;
1167
1168 rscdev->cmdlist_wake = devm_kcalloc(bus_dev,
1169 rscdev->num_bcm_devs,
1170 sizeof(struct tcs_cmd), GFP_KERNEL);
1171 if (!rscdev->cmdlist_wake)
1172 return -ENOMEM;
1173
1174 rscdev->cmdlist_sleep = devm_kcalloc(bus_dev,
1175 rscdev->num_bcm_devs,
1176 sizeof(struct tcs_cmd), GFP_KERNEL);
1177 if (!rscdev->cmdlist_sleep)
1178 return -ENOMEM;
1179 }
1180
1181 return 0;
1182}
1183
David Dai04ce4202016-09-26 16:24:13 -07001184static int msm_bus_init_clk(struct device *bus_dev,
1185 struct msm_bus_node_device_type *pdata)
1186{
1187 unsigned int ctx;
1188 struct msm_bus_node_device_type *node_dev = to_msm_bus_node(bus_dev);
1189 int i;
1190
1191 for (ctx = 0; ctx < NUM_CTX; ctx++) {
1192 if (!IS_ERR_OR_NULL(pdata->clk[ctx].clk)) {
1193 node_dev->clk[ctx].clk = pdata->clk[ctx].clk;
1194 node_dev->clk[ctx].enable_only_clk =
1195 pdata->clk[ctx].enable_only_clk;
1196 node_dev->clk[ctx].setrate_only_clk =
1197 pdata->clk[ctx].setrate_only_clk;
1198 node_dev->clk[ctx].enable = false;
1199 node_dev->clk[ctx].dirty = false;
1200 strlcpy(node_dev->clk[ctx].reg_name,
1201 pdata->clk[ctx].reg_name, MAX_REG_NAME);
1202 node_dev->clk[ctx].reg = NULL;
1203 bus_get_reg(&node_dev->clk[ctx], bus_dev);
1204 MSM_BUS_DBG("%s: Valid node clk node %d ctx %d\n",
1205 __func__, node_dev->node_info->id, ctx);
1206 }
1207 }
1208
1209 if (!IS_ERR_OR_NULL(pdata->bus_qos_clk.clk)) {
1210 node_dev->bus_qos_clk.clk = pdata->bus_qos_clk.clk;
1211 node_dev->bus_qos_clk.enable_only_clk =
1212 pdata->bus_qos_clk.enable_only_clk;
1213 node_dev->bus_qos_clk.setrate_only_clk =
1214 pdata->bus_qos_clk.setrate_only_clk;
1215 node_dev->bus_qos_clk.enable = false;
1216 strlcpy(node_dev->bus_qos_clk.reg_name,
1217 pdata->bus_qos_clk.reg_name, MAX_REG_NAME);
1218 node_dev->bus_qos_clk.reg = NULL;
1219 MSM_BUS_DBG("%s: Valid bus qos clk node %d\n", __func__,
1220 node_dev->node_info->id);
1221 }
1222
1223 if (pdata->num_node_qos_clks) {
1224 node_dev->num_node_qos_clks = pdata->num_node_qos_clks;
1225 node_dev->node_qos_clks = devm_kzalloc(bus_dev,
1226 (node_dev->num_node_qos_clks * sizeof(struct nodeclk)),
1227 GFP_KERNEL);
1228 if (!node_dev->node_qos_clks) {
1229 dev_err(bus_dev, "Failed to alloc memory for qos clk");
1230 return -ENOMEM;
1231 }
1232
1233 for (i = 0; i < pdata->num_node_qos_clks; i++) {
1234 node_dev->node_qos_clks[i].clk =
1235 pdata->node_qos_clks[i].clk;
1236 node_dev->node_qos_clks[i].enable_only_clk =
1237 pdata->node_qos_clks[i].enable_only_clk;
1238 node_dev->node_qos_clks[i].setrate_only_clk =
1239 pdata->node_qos_clks[i].setrate_only_clk;
1240 node_dev->node_qos_clks[i].enable = false;
1241 strlcpy(node_dev->node_qos_clks[i].reg_name,
1242 pdata->node_qos_clks[i].reg_name, MAX_REG_NAME);
1243 node_dev->node_qos_clks[i].reg = NULL;
1244 MSM_BUS_DBG("%s: Valid qos clk[%d] node %d %d Reg%s\n",
1245 __func__, i,
1246 node_dev->node_info->id,
1247 node_dev->num_node_qos_clks,
1248 node_dev->node_qos_clks[i].reg_name);
1249 }
1250 }
1251
1252 return 0;
1253}
1254
1255static int msm_bus_copy_node_info(struct msm_bus_node_device_type *pdata,
1256 struct device *bus_dev)
1257{
David Daia55b46e2017-05-08 10:31:31 -07001258 int ret = 0, i = 0;
David Dai04ce4202016-09-26 16:24:13 -07001259 struct msm_bus_node_info_type *node_info = NULL;
1260 struct msm_bus_node_info_type *pdata_node_info = NULL;
1261 struct msm_bus_node_device_type *bus_node = NULL;
1262
1263 bus_node = to_msm_bus_node(bus_dev);
1264
1265 if (!bus_node || !pdata) {
1266 ret = -ENXIO;
1267 MSM_BUS_ERR("%s: Invalid pointers pdata %p, bus_node %p",
1268 __func__, pdata, bus_node);
1269 goto exit_copy_node_info;
1270 }
1271
1272 node_info = bus_node->node_info;
1273 pdata_node_info = pdata->node_info;
1274
1275 node_info->name = pdata_node_info->name;
1276 node_info->id = pdata_node_info->id;
David Daia55b46e2017-05-08 10:31:31 -07001277 node_info->bcm_req_idx = devm_kzalloc(bus_dev,
1278 sizeof(int) * pdata_node_info->num_bcm_devs,
1279 GFP_KERNEL);
1280 if (!node_info->bcm_req_idx) {
1281 ret = -ENOMEM;
1282 goto exit_copy_node_info;
1283 }
1284
1285 for (i = 0; i < pdata_node_info->num_bcm_devs; i++)
1286 node_info->bcm_req_idx[i] = -1;
1287
David Dai04ce4202016-09-26 16:24:13 -07001288 node_info->bus_device_id = pdata_node_info->bus_device_id;
1289 node_info->mas_rpm_id = pdata_node_info->mas_rpm_id;
1290 node_info->slv_rpm_id = pdata_node_info->slv_rpm_id;
1291 node_info->num_connections = pdata_node_info->num_connections;
1292 node_info->num_blist = pdata_node_info->num_blist;
1293 node_info->num_bcm_devs = pdata_node_info->num_bcm_devs;
David Dai1999c042017-02-27 12:51:09 -08001294 node_info->num_rsc_devs = pdata_node_info->num_rsc_devs;
David Dai04ce4202016-09-26 16:24:13 -07001295 node_info->num_qports = pdata_node_info->num_qports;
1296 node_info->virt_dev = pdata_node_info->virt_dev;
1297 node_info->is_fab_dev = pdata_node_info->is_fab_dev;
1298 node_info->is_bcm_dev = pdata_node_info->is_bcm_dev;
David Dai1999c042017-02-27 12:51:09 -08001299 node_info->is_rsc_dev = pdata_node_info->is_rsc_dev;
David Daib4aff8b2017-04-11 19:36:53 -07001300 node_info->qos_params.prio_dflt = pdata_node_info->qos_params.prio_dflt;
1301 node_info->qos_params.limiter.bw =
1302 pdata_node_info->qos_params.limiter.bw;
1303 node_info->qos_params.limiter.sat =
1304 pdata_node_info->qos_params.limiter.sat;
1305 node_info->qos_params.limiter_en =
1306 pdata_node_info->qos_params.limiter_en;
1307 node_info->qos_params.reg.low_prio =
1308 pdata_node_info->qos_params.reg.low_prio;
1309 node_info->qos_params.reg.hi_prio =
1310 pdata_node_info->qos_params.reg.hi_prio;
1311 node_info->qos_params.reg.bw =
1312 pdata_node_info->qos_params.reg.bw;
1313 node_info->qos_params.reg.sat =
1314 pdata_node_info->qos_params.reg.sat;
1315 node_info->qos_params.reg_mode.read =
1316 pdata_node_info->qos_params.reg_mode.read;
1317 node_info->qos_params.reg_mode.write =
1318 pdata_node_info->qos_params.reg_mode.write;
1319 node_info->qos_params.urg_fwd_en =
1320 pdata_node_info->qos_params.urg_fwd_en;
David Dai27ffa282017-08-04 12:25:17 -07001321 node_info->qos_params.defer_init_qos =
1322 pdata_node_info->qos_params.defer_init_qos;
David Dai04ce4202016-09-26 16:24:13 -07001323 node_info->agg_params.buswidth = pdata_node_info->agg_params.buswidth;
1324 node_info->agg_params.agg_scheme =
1325 pdata_node_info->agg_params.agg_scheme;
1326 node_info->agg_params.vrail_comp =
1327 pdata_node_info->agg_params.vrail_comp;
1328 node_info->agg_params.num_aggports =
1329 pdata_node_info->agg_params.num_aggports;
1330 node_info->agg_params.num_util_levels =
1331 pdata_node_info->agg_params.num_util_levels;
1332 node_info->agg_params.util_levels = devm_kzalloc(bus_dev,
1333 sizeof(struct node_util_levels_type) *
1334 node_info->agg_params.num_util_levels,
1335 GFP_KERNEL);
1336 if (!node_info->agg_params.util_levels) {
1337 MSM_BUS_ERR("%s: Agg util level alloc failed\n", __func__);
1338 ret = -ENOMEM;
1339 goto exit_copy_node_info;
1340 }
1341 memcpy(node_info->agg_params.util_levels,
1342 pdata_node_info->agg_params.util_levels,
1343 sizeof(struct node_util_levels_type) *
1344 pdata_node_info->agg_params.num_util_levels);
1345
1346 node_info->dev_connections = devm_kzalloc(bus_dev,
1347 sizeof(struct device *) *
1348 pdata_node_info->num_connections,
1349 GFP_KERNEL);
1350 if (!node_info->dev_connections) {
1351 MSM_BUS_ERR("%s:Bus dev connections alloc failed\n", __func__);
1352 ret = -ENOMEM;
1353 goto exit_copy_node_info;
1354 }
1355
1356 node_info->connections = devm_kzalloc(bus_dev,
1357 sizeof(int) * pdata_node_info->num_connections,
1358 GFP_KERNEL);
1359 if (!node_info->connections) {
1360 MSM_BUS_ERR("%s:Bus connections alloc failed\n", __func__);
1361 devm_kfree(bus_dev, node_info->dev_connections);
1362 ret = -ENOMEM;
1363 goto exit_copy_node_info;
1364 }
1365
1366 memcpy(node_info->connections,
1367 pdata_node_info->connections,
1368 sizeof(int) * pdata_node_info->num_connections);
1369
1370 node_info->black_connections = devm_kzalloc(bus_dev,
1371 sizeof(struct device *) *
1372 pdata_node_info->num_blist,
1373 GFP_KERNEL);
1374 if (!node_info->black_connections) {
1375 MSM_BUS_ERR("%s: Bus black connections alloc failed\n",
1376 __func__);
1377 devm_kfree(bus_dev, node_info->dev_connections);
1378 devm_kfree(bus_dev, node_info->connections);
1379 ret = -ENOMEM;
1380 goto exit_copy_node_info;
1381 }
1382
1383 node_info->black_listed_connections = devm_kzalloc(bus_dev,
1384 pdata_node_info->num_blist * sizeof(int),
1385 GFP_KERNEL);
1386 if (!node_info->black_listed_connections) {
1387 MSM_BUS_ERR("%s:Bus black list connections alloc failed\n",
1388 __func__);
1389 devm_kfree(bus_dev, node_info->black_connections);
1390 devm_kfree(bus_dev, node_info->dev_connections);
1391 devm_kfree(bus_dev, node_info->connections);
1392 ret = -ENOMEM;
1393 goto exit_copy_node_info;
1394 }
1395
1396 memcpy(node_info->black_listed_connections,
1397 pdata_node_info->black_listed_connections,
1398 sizeof(int) * pdata_node_info->num_blist);
1399
1400 node_info->bcm_devs = devm_kzalloc(bus_dev,
1401 sizeof(struct device *) *
1402 pdata_node_info->num_bcm_devs,
1403 GFP_KERNEL);
1404 if (!node_info->bcm_devs) {
1405 MSM_BUS_ERR("%s:Bcm dev connections alloc failed\n", __func__);
1406 ret = -ENOMEM;
1407 goto exit_copy_node_info;
1408 }
1409
1410 node_info->bcm_dev_ids = devm_kzalloc(bus_dev,
1411 sizeof(int) * pdata_node_info->num_bcm_devs,
1412 GFP_KERNEL);
David Daibabfac62017-07-14 14:47:42 -07001413 if (!node_info->bcm_dev_ids) {
David Dai04ce4202016-09-26 16:24:13 -07001414 MSM_BUS_ERR("%s:Bus connections alloc failed\n", __func__);
1415 devm_kfree(bus_dev, node_info->bcm_devs);
1416 ret = -ENOMEM;
1417 goto exit_copy_node_info;
1418 }
1419
1420 memcpy(node_info->bcm_dev_ids,
1421 pdata_node_info->bcm_dev_ids,
1422 sizeof(int) * pdata_node_info->num_bcm_devs);
1423
David Dai1999c042017-02-27 12:51:09 -08001424 node_info->rsc_devs = devm_kzalloc(bus_dev,
1425 sizeof(struct device *) *
1426 pdata_node_info->num_rsc_devs,
1427 GFP_KERNEL);
1428 if (!node_info->rsc_devs) {
1429 MSM_BUS_ERR("%s:rsc dev connections alloc failed\n", __func__);
1430 ret = -ENOMEM;
1431 goto exit_copy_node_info;
1432 }
1433
1434 node_info->rsc_dev_ids = devm_kzalloc(bus_dev,
1435 sizeof(int) * pdata_node_info->num_rsc_devs,
1436 GFP_KERNEL);
David Daibabfac62017-07-14 14:47:42 -07001437 if (!node_info->rsc_dev_ids) {
David Dai1999c042017-02-27 12:51:09 -08001438 MSM_BUS_ERR("%s:Bus connections alloc failed\n", __func__);
1439 devm_kfree(bus_dev, node_info->rsc_devs);
1440 ret = -ENOMEM;
1441 goto exit_copy_node_info;
1442 }
1443
1444 memcpy(node_info->rsc_dev_ids,
1445 pdata_node_info->rsc_dev_ids,
1446 sizeof(int) * pdata_node_info->num_rsc_devs);
1447
David Dai04ce4202016-09-26 16:24:13 -07001448 node_info->qport = devm_kzalloc(bus_dev,
1449 sizeof(int) * pdata_node_info->num_qports,
1450 GFP_KERNEL);
1451 if (!node_info->qport) {
1452 MSM_BUS_ERR("%s:Bus qport allocation failed\n", __func__);
1453 devm_kfree(bus_dev, node_info->dev_connections);
1454 devm_kfree(bus_dev, node_info->connections);
1455 devm_kfree(bus_dev, node_info->black_listed_connections);
1456 ret = -ENOMEM;
1457 goto exit_copy_node_info;
1458 }
1459
1460 memcpy(node_info->qport,
1461 pdata_node_info->qport,
1462 sizeof(int) * pdata_node_info->num_qports);
1463
1464exit_copy_node_info:
1465 return ret;
1466}
1467
1468static struct device *msm_bus_device_init(
1469 struct msm_bus_node_device_type *pdata)
1470{
1471 struct device *bus_dev = NULL;
1472 struct msm_bus_node_device_type *bus_node = NULL;
1473 struct msm_bus_node_info_type *node_info = NULL;
David Daib4aff8b2017-04-11 19:36:53 -07001474 int ret = 0, i = 0;
David Dai04ce4202016-09-26 16:24:13 -07001475
1476 /**
1477 * Init here so we can use devm calls
1478 */
1479
1480 bus_node = kzalloc(sizeof(struct msm_bus_node_device_type), GFP_KERNEL);
1481 if (!bus_node) {
1482 MSM_BUS_ERR("%s:Bus node alloc failed\n", __func__);
1483 kfree(bus_dev);
1484 bus_dev = NULL;
1485 goto exit_device_init;
1486 }
1487 bus_dev = &bus_node->dev;
1488 device_initialize(bus_dev);
1489
1490 node_info = devm_kzalloc(bus_dev,
1491 sizeof(struct msm_bus_node_info_type), GFP_KERNEL);
1492 if (!node_info) {
1493 MSM_BUS_ERR("%s:Bus node info alloc failed\n", __func__);
1494 devm_kfree(bus_dev, bus_node);
1495 kfree(bus_dev);
1496 bus_dev = NULL;
1497 goto exit_device_init;
1498 }
1499
1500 bus_node->node_info = node_info;
1501 bus_node->ap_owned = pdata->ap_owned;
David Dai62c04a62017-04-12 19:05:49 -07001502 bus_node->dirty = false;
David Daib4aff8b2017-04-11 19:36:53 -07001503 bus_node->num_qos_bcms = pdata->num_qos_bcms;
1504 if (bus_node->num_qos_bcms) {
1505 bus_node->qos_bcms = devm_kzalloc(bus_dev,
1506 (sizeof(struct qos_bcm_type) *
1507 bus_node->num_qos_bcms), GFP_KERNEL);
1508 if (!bus_node->qos_bcms)
1509 goto exit_device_init;
1510 for (i = 0; i < bus_node->num_qos_bcms; i++) {
1511 bus_node->qos_bcms[i].qos_bcm_id =
1512 pdata->qos_bcms[i].qos_bcm_id;
1513 bus_node->qos_bcms[i].vec.vec_a =
1514 pdata->qos_bcms[i].vec.vec_a;
1515 bus_node->qos_bcms[i].vec.vec_b =
1516 pdata->qos_bcms[i].vec.vec_b;
1517 }
1518 }
1519
David Dai04ce4202016-09-26 16:24:13 -07001520 bus_dev->of_node = pdata->of_node;
1521
1522 if (msm_bus_copy_node_info(pdata, bus_dev) < 0) {
1523 devm_kfree(bus_dev, bus_node);
1524 devm_kfree(bus_dev, node_info);
1525 kfree(bus_dev);
1526 bus_dev = NULL;
1527 goto exit_device_init;
1528 }
1529
1530 bus_dev->bus = &msm_bus_type;
1531 dev_set_name(bus_dev, bus_node->node_info->name);
1532
1533 ret = device_add(bus_dev);
1534 if (ret < 0) {
1535 MSM_BUS_ERR("%s: Error registering device %d",
1536 __func__, pdata->node_info->id);
1537 devm_kfree(bus_dev, bus_node);
1538 devm_kfree(bus_dev, node_info->dev_connections);
1539 devm_kfree(bus_dev, node_info->connections);
1540 devm_kfree(bus_dev, node_info->black_connections);
1541 devm_kfree(bus_dev, node_info->black_listed_connections);
1542 devm_kfree(bus_dev, node_info);
1543 kfree(bus_dev);
1544 bus_dev = NULL;
1545 goto exit_device_init;
1546 }
1547 device_create_file(bus_dev, &dev_attr_bw);
1548 INIT_LIST_HEAD(&bus_node->devlist);
1549
1550exit_device_init:
1551 return bus_dev;
1552}
1553
1554static int msm_bus_setup_dev_conn(struct device *bus_dev, void *data)
1555{
1556 struct msm_bus_node_device_type *bus_node = NULL;
1557 struct msm_bus_node_device_type *bcm_node = NULL;
David Dai1999c042017-02-27 12:51:09 -08001558 struct msm_bus_node_device_type *rsc_node = NULL;
David Dai04ce4202016-09-26 16:24:13 -07001559 int ret = 0;
1560 int j;
1561 struct msm_bus_node_device_type *fab;
1562
1563 bus_node = to_msm_bus_node(bus_dev);
1564 if (!bus_node) {
1565 MSM_BUS_ERR("%s: Can't get device info", __func__);
1566 ret = -ENODEV;
1567 goto exit_setup_dev_conn;
1568 }
1569
1570 /* Setup parent bus device for this node */
David Dai0d014432016-11-10 12:57:44 -08001571 if (!bus_node->node_info->is_fab_dev &&
David Dai1999c042017-02-27 12:51:09 -08001572 !bus_node->node_info->is_bcm_dev &&
1573 !bus_node->node_info->is_rsc_dev) {
David Dai04ce4202016-09-26 16:24:13 -07001574 struct device *bus_parent_device =
1575 bus_find_device(&msm_bus_type, NULL,
1576 (void *)&bus_node->node_info->bus_device_id,
1577 msm_bus_device_match_adhoc);
1578
1579 if (!bus_parent_device) {
1580 MSM_BUS_ERR("%s: Error finding parentdev %d parent %d",
1581 __func__,
1582 bus_node->node_info->id,
1583 bus_node->node_info->bus_device_id);
1584 ret = -ENXIO;
1585 goto exit_setup_dev_conn;
1586 }
1587 bus_node->node_info->bus_device = bus_parent_device;
1588 fab = to_msm_bus_node(bus_parent_device);
1589 list_add_tail(&bus_node->dev_link, &fab->devlist);
1590 }
1591
1592 bus_node->node_info->is_traversed = false;
1593
1594 for (j = 0; j < bus_node->node_info->num_connections; j++) {
1595 bus_node->node_info->dev_connections[j] =
1596 bus_find_device(&msm_bus_type, NULL,
1597 (void *)&bus_node->node_info->connections[j],
1598 msm_bus_device_match_adhoc);
1599
1600 if (!bus_node->node_info->dev_connections[j]) {
1601 MSM_BUS_ERR("%s: Error finding conn %d for device %d",
1602 __func__, bus_node->node_info->connections[j],
1603 bus_node->node_info->id);
1604 ret = -ENODEV;
1605 goto exit_setup_dev_conn;
1606 }
1607 }
1608
1609 for (j = 0; j < bus_node->node_info->num_blist; j++) {
1610 bus_node->node_info->black_connections[j] =
1611 bus_find_device(&msm_bus_type, NULL,
1612 (void *)&bus_node->node_info->
1613 black_listed_connections[j],
1614 msm_bus_device_match_adhoc);
1615
1616 if (!bus_node->node_info->black_connections[j]) {
1617 MSM_BUS_ERR("%s: Error finding conn %d for device %d\n",
1618 __func__, bus_node->node_info->
1619 black_listed_connections[j],
1620 bus_node->node_info->id);
1621 ret = -ENODEV;
1622 goto exit_setup_dev_conn;
1623 }
1624 }
1625
1626 for (j = 0; j < bus_node->node_info->num_bcm_devs; j++) {
1627 bus_node->node_info->bcm_devs[j] =
1628 bus_find_device(&msm_bus_type, NULL,
1629 (void *)&bus_node->node_info->bcm_dev_ids[j],
1630 msm_bus_device_match_adhoc);
1631
1632 if (!bus_node->node_info->bcm_devs[j]) {
1633 MSM_BUS_ERR("%s: Error finding conn %d for device %d",
1634 __func__, bus_node->node_info->bcm_dev_ids[j],
1635 bus_node->node_info->id);
1636 ret = -ENODEV;
1637 goto exit_setup_dev_conn;
1638 }
David Dai0d014432016-11-10 12:57:44 -08001639 bcm_node = to_msm_bus_node(bus_node->node_info->bcm_devs[j]);
David Dai04ce4202016-09-26 16:24:13 -07001640 bcm_node->bcmdev->num_bus_devs++;
1641 }
1642
David Dai1999c042017-02-27 12:51:09 -08001643 for (j = 0; j < bus_node->node_info->num_rsc_devs; j++) {
1644 bus_node->node_info->rsc_devs[j] =
1645 bus_find_device(&msm_bus_type, NULL,
1646 (void *)&bus_node->node_info->rsc_dev_ids[j],
1647 msm_bus_device_match_adhoc);
1648
1649 if (!bus_node->node_info->rsc_devs[j]) {
1650 MSM_BUS_ERR("%s: Error finding conn %d for device %d",
1651 __func__, bus_node->node_info->rsc_dev_ids[j],
1652 bus_node->node_info->id);
1653 ret = -ENODEV;
1654 goto exit_setup_dev_conn;
1655 }
1656 rsc_node = to_msm_bus_node(bus_node->node_info->rsc_devs[j]);
David Dai3734dab2018-01-09 11:21:11 -08001657 rsc_node->rscdev->num_bcm_devs++;
David Dai1999c042017-02-27 12:51:09 -08001658 }
1659
David Dai04ce4202016-09-26 16:24:13 -07001660exit_setup_dev_conn:
1661 return ret;
1662}
1663
1664static int msm_bus_node_debug(struct device *bus_dev, void *data)
1665{
1666 int j;
1667 int ret = 0;
1668 struct msm_bus_node_device_type *bus_node = NULL;
1669
1670 bus_node = to_msm_bus_node(bus_dev);
1671 if (!bus_node) {
1672 MSM_BUS_ERR("%s: Can't get device info", __func__);
1673 ret = -ENODEV;
1674 goto exit_node_debug;
1675 }
1676
1677 MSM_BUS_DBG("Device = %d buswidth %u", bus_node->node_info->id,
1678 bus_node->node_info->agg_params.buswidth);
1679 for (j = 0; j < bus_node->node_info->num_connections; j++) {
1680 struct msm_bus_node_device_type *bdev =
1681 to_msm_bus_node(bus_node->node_info->dev_connections[j]);
1682 MSM_BUS_DBG("\n\t Connection[%d] %d", j, bdev->node_info->id);
1683 }
1684
1685 if (bus_node->node_info->is_fab_dev)
1686 msm_bus_floor_init(bus_dev);
1687
1688exit_node_debug:
1689 return ret;
1690}
1691
1692static int msm_bus_free_dev(struct device *dev, void *data)
1693{
1694 struct msm_bus_node_device_type *bus_node = NULL;
1695
1696 bus_node = to_msm_bus_node(dev);
1697
1698 if (bus_node)
1699 MSM_BUS_ERR("\n%s: Removing device %d", __func__,
1700 bus_node->node_info->id);
1701 device_unregister(dev);
1702 kfree(bus_node);
1703 return 0;
1704}
1705
1706int msm_bus_device_remove(struct platform_device *pdev)
1707{
1708 bus_for_each_dev(&msm_bus_type, NULL, NULL, msm_bus_free_dev);
1709 return 0;
1710}
1711
1712static int msm_bus_device_probe(struct platform_device *pdev)
1713{
1714 unsigned int i = 1, ret;
1715 struct msm_bus_device_node_registration *pdata;
1716
1717 MSM_BUS_ERR("msm_bus: Probe started");
1718 /* If possible, get pdata from device-tree */
1719 if (pdev->dev.of_node)
1720 pdata = msm_bus_of_to_pdata(pdev);
1721 else {
1722 pdata = (struct msm_bus_device_node_registration *)pdev->
1723 dev.platform_data;
1724 }
1725
1726 MSM_BUS_ERR("msm_bus: DT Parsing complete");
1727
1728 if (IS_ERR_OR_NULL(pdata)) {
1729 MSM_BUS_ERR("No platform data found");
1730 ret = -ENODATA;
1731 goto exit_device_probe;
1732 }
1733
1734 for (i = 0; i < pdata->num_devices; i++) {
1735 struct device *node_dev = NULL;
1736
1737 node_dev = msm_bus_device_init(&pdata->info[i]);
1738
1739 if (!node_dev) {
1740 MSM_BUS_ERR("%s: Error during dev init for %d",
1741 __func__, pdata->info[i].node_info->id);
1742 ret = -ENXIO;
1743 goto exit_device_probe;
1744 }
1745
1746 ret = msm_bus_init_clk(node_dev, &pdata->info[i]);
1747 if (ret) {
1748 MSM_BUS_ERR("\n Failed to init bus clk. ret %d", ret);
1749 msm_bus_device_remove(pdev);
1750 goto exit_device_probe;
1751 }
1752 /*Is this a fabric device ?*/
1753 if (pdata->info[i].node_info->is_fab_dev) {
1754 MSM_BUS_DBG("%s: %d is a fab", __func__,
1755 pdata->info[i].node_info->id);
1756 ret = msm_bus_fabric_init(node_dev, &pdata->info[i]);
1757 if (ret) {
1758 MSM_BUS_ERR("%s: Error intializing fab %d",
1759 __func__, pdata->info[i].node_info->id);
1760 goto exit_device_probe;
1761 }
1762 }
Stephen Boydd213aee2017-04-05 17:09:22 -07001763 if (pdata->info[i].node_info->is_bcm_dev) {
David Dai04ce4202016-09-26 16:24:13 -07001764 ret = msm_bus_bcm_init(node_dev, &pdata->info[i]);
1765 if (ret) {
1766 MSM_BUS_ERR("%s: Error intializing bcm %d",
1767 __func__, pdata->info[i].node_info->id);
1768 goto exit_device_probe;
1769 }
Stephen Boydd213aee2017-04-05 17:09:22 -07001770 }
1771 if (pdata->info[i].node_info->is_rsc_dev) {
David Dai1999c042017-02-27 12:51:09 -08001772 ret = msm_bus_rsc_init(pdev, node_dev, &pdata->info[i]);
1773 if (ret) {
1774 MSM_BUS_ERR("%s: Error intializing rsc %d",
1775 __func__, pdata->info[i].node_info->id);
1776 goto exit_device_probe;
1777 }
Stephen Boydd213aee2017-04-05 17:09:22 -07001778 }
David Dai04ce4202016-09-26 16:24:13 -07001779 }
1780
1781 ret = bus_for_each_dev(&msm_bus_type, NULL, NULL,
1782 msm_bus_setup_dev_conn);
1783 if (ret) {
1784 MSM_BUS_ERR("%s: Error setting up dev connections", __func__);
1785 goto exit_device_probe;
1786 }
1787
David Dai3734dab2018-01-09 11:21:11 -08001788 ret = bus_for_each_dev(&msm_bus_type, NULL, NULL,
1789 msm_bus_postcon_setup);
1790 if (ret) {
1791 MSM_BUS_ERR("%s: Error post connection setup", __func__);
1792 goto exit_device_probe;
1793 }
1794
David Dai04ce4202016-09-26 16:24:13 -07001795 /*
1796 * Setup the QoS for the nodes, don't check the error codes as we
1797 * defer QoS programming to the first transaction in cases of failure
1798 * and we want to continue the probe.
1799 */
1800 ret = bus_for_each_dev(&msm_bus_type, NULL, NULL, msm_bus_dev_init_qos);
1801
1802 /* Register the arb layer ops */
1803 msm_bus_arb_setops_adhoc(&arb_ops);
1804 bus_for_each_dev(&msm_bus_type, NULL, NULL, msm_bus_node_debug);
1805
David Dai04ce4202016-09-26 16:24:13 -07001806 devm_kfree(&pdev->dev, pdata->info);
1807 devm_kfree(&pdev->dev, pdata);
1808exit_device_probe:
1809 return ret;
1810}
1811
1812static int msm_bus_device_rules_probe(struct platform_device *pdev)
1813{
1814 struct bus_rule_type *rule_data = NULL;
1815 int num_rules = 0;
1816
1817 num_rules = msm_bus_of_get_static_rules(pdev, &rule_data);
1818
1819 if (!rule_data)
1820 goto exit_rules_probe;
1821
1822 msm_rule_register(num_rules, rule_data, NULL);
1823 static_rules.num_rules = num_rules;
1824 static_rules.rules = rule_data;
1825 pdev->dev.platform_data = &static_rules;
1826
1827exit_rules_probe:
1828 return 0;
1829}
1830
1831int msm_bus_device_rules_remove(struct platform_device *pdev)
1832{
1833 struct static_rules_type *static_rules = NULL;
1834
1835 static_rules = pdev->dev.platform_data;
1836 if (static_rules)
1837 msm_rule_unregister(static_rules->num_rules,
1838 static_rules->rules, NULL);
1839 return 0;
1840}
1841
1842
1843static const struct of_device_id rules_match[] = {
1844 {.compatible = "qcom,msm-bus-static-bw-rules"},
1845 {}
1846};
1847
1848static struct platform_driver msm_bus_rules_driver = {
1849 .probe = msm_bus_device_rules_probe,
1850 .remove = msm_bus_device_rules_remove,
1851 .driver = {
1852 .name = "msm_bus_rules_device",
1853 .owner = THIS_MODULE,
1854 .of_match_table = rules_match,
1855 },
1856};
1857
1858static const struct of_device_id fabric_match[] = {
1859 {.compatible = "qcom,msm-bus-device"},
1860 {}
1861};
1862
1863static struct platform_driver msm_bus_device_driver = {
1864 .probe = msm_bus_device_probe,
1865 .remove = msm_bus_device_remove,
1866 .driver = {
1867 .name = "msm_bus_device",
1868 .owner = THIS_MODULE,
1869 .of_match_table = fabric_match,
1870 },
1871};
1872
1873int __init msm_bus_device_init_driver(void)
1874{
1875 int rc;
1876
1877 MSM_BUS_ERR("msm_bus_fabric_rpmh_init_driver\n");
1878 rc = platform_driver_register(&msm_bus_device_driver);
1879
1880 if (rc) {
1881 MSM_BUS_ERR("Failed to register bus device driver");
1882 return rc;
1883 }
1884 return platform_driver_register(&msm_bus_rules_driver);
1885}
1886
1887int __init msm_bus_device_late_init(void)
1888{
David Dai68c72502017-07-07 19:56:01 -07001889 commit_late_init_data(true);
David Dai04ce4202016-09-26 16:24:13 -07001890 MSM_BUS_ERR("msm_bus_late_init: Remove handoff bw requests\n");
David Dai62c04a62017-04-12 19:05:49 -07001891 init_time = false;
David Dai68c72502017-07-07 19:56:01 -07001892 return commit_late_init_data(false);
David Dai04ce4202016-09-26 16:24:13 -07001893}
1894subsys_initcall(msm_bus_device_init_driver);
1895late_initcall_sync(msm_bus_device_late_init);