blob: 75527cddb9d38b83785316d23d58f0db1993c029 [file] [log] [blame]
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +05301/*
2 **************************************************************************
Tanmay V Jagdale20490fb2017-02-09 17:32:31 +05303 * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +05304 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 **************************************************************************
15 */
Murat Sezgin84ca6512014-04-14 13:57:24 -070016
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053017/*
18 * nss_pm.c
19 * NSS Power Management APIs
20 *
21 */
22#include <linux/debugfs.h>
23#include <linux/module.h>
24#include <linux/netdevice.h>
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080025#include <nss_api_if.h>
Samarjeet Banerjeeb126e0f2016-08-05 20:58:27 +053026#include <nss_core.h>
mandrew496aba72016-11-19 14:12:38 +053027
Tanmay V Jagdale20490fb2017-02-09 17:32:31 +053028#if (NSS_DT_SUPPORT != 1)
29#include <nss_clocks.h>
30#endif
31
mandrew496aba72016-11-19 14:12:38 +053032#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053033#include "nss_pm.h"
34
35/*
36 * Global NSS PM structure
37 */
38struct nss_pm_global_ctx ctx;
39
40/*
41 * Bus vector table for GMAC driver
42 */
43static struct msm_bus_paths nss_gmac_bw_level_tbl[NSS_PM_PERF_MAX_LEVELS] = {
44 [NSS_PM_PERF_LEVEL_SUSPEND] = GMAC_BW_MBPS(0, 0),
45 /* 0 MHz to DDR, 0 MHz to TCM */
46 [NSS_PM_PERF_LEVEL_IDLE] = GMAC_BW_MBPS(133, 5),
47 /* 133 MHz to DDR, 5 MHz to TCM */
48 [NSS_PM_PERF_LEVEL_NOMINAL] = GMAC_BW_MBPS(200, 400),
49 /* 200 MHz to DDR, 10 MHz to TCM */
50 [NSS_PM_PERF_LEVEL_TURBO] = GMAC_BW_MBPS(266, 533),
51 /* 266 MHz to DDR, 20 MHz to TCM */
52};
53
54/*
55 * Bus vector table for Crypto driver
56 */
57static struct msm_bus_paths nss_crypto_bw_level_tbl[NSS_PM_PERF_MAX_LEVELS] = {
58 [NSS_PM_PERF_LEVEL_SUSPEND] = CRYPTO_BW_MBPS(0, 0),
59 /* 0 MHz to DDR, 0 MHz to TCM */
60 [NSS_PM_PERF_LEVEL_IDLE] = CRYPTO_BW_MBPS(133, 5),
61 /* 133 MHz to DDR, 5 MHz to TCM */
62 [NSS_PM_PERF_LEVEL_NOMINAL] = CRYPTO_BW_MBPS(200, 400),
63 /* 200 MHz to DDR, 10 MHz to TCM */
64 [NSS_PM_PERF_LEVEL_TURBO] = CRYPTO_BW_MBPS(266, 533),
65 /* 266 MHz to DDR, 20 MHz to TCM */
66};
67
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053068#ifdef NSS_PM_NETAP_GMAC_SCALING
69
70/*
71 * Bus vector table for NSS HLOS driver
72 * This requests bw for both NSS Fab0 and Fab1 on behalf of GMAC and NSS Drivers
73 */
74static struct msm_bus_paths nss_netap_bw_level_tbl[NSS_PM_PERF_MAX_LEVELS] = {
75 [NSS_PM_PERF_LEVEL_SUSPEND] = GMAC_BW_MBPS(0, 0),
76 /* 0 MHz to DDR, 0 MHz to TCM */
Rajith Cherian402872f2016-03-12 16:34:08 +053077 [NSS_PM_PERF_LEVEL_IDLE] = GMAC_BW_MBPS(122, 122),
78 /* 133 MHz to DDR and TCM */
79 [NSS_PM_PERF_LEVEL_NOMINAL] = GMAC_BW_MBPS(200, 200),
80 /* 400 MHz to DDR and TCM */
81 [NSS_PM_PERF_LEVEL_TURBO] = GMAC_BW_MBPS(400, 400),
82 /* 533 MHz to DDR and TCM */
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053083};
84
85#else
86
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053087/*
88 * Bus vector table for NSS HLOS driver
89 */
90static struct msm_bus_paths nss_netap_bw_level_tbl[NSS_PM_PERF_MAX_LEVELS] = {
91 [NSS_PM_PERF_LEVEL_SUSPEND] = NETAP_BW_MBPS(0, 0),
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053092 /* 0 MHz to DDR, 0 MHz to TCM */
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053093 [NSS_PM_PERF_LEVEL_IDLE] = NETAP_BW_MBPS(133, 133),
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053094 /* 133 MHz to DDR and TCM */
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053095 [NSS_PM_PERF_LEVEL_NOMINAL] = NETAP_BW_MBPS(400, 400),
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053096 /* 400 MHz to DDR and TCM */
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053097 [NSS_PM_PERF_LEVEL_TURBO] = NETAP_BW_MBPS(533, 533),
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053098 /* 533 MHz to DDR and TCM */
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053099};
100
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530101#endif
102
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530103/*
104 * Bus Driver Platform data for GMAC, Crypto and Netap clients
105 */
106static struct msm_bus_scale_pdata nss_bus_scale[] = {
107 [NSS_PM_CLIENT_GMAC] = {
108 .usecase = nss_gmac_bw_level_tbl,
109 .num_usecases = ARRAY_SIZE(nss_gmac_bw_level_tbl),
110 .active_only = 1,
111 .name = "qca-nss-gmac",
112 },
113
114 [NSS_PM_CLIENT_CRYPTO] = {
115 .usecase = nss_crypto_bw_level_tbl,
116 .num_usecases = ARRAY_SIZE(nss_crypto_bw_level_tbl),
117 .active_only = 1,
118 .name = "qca-nss-crypto",
119 },
120
121 [NSS_PM_CLIENT_NETAP] = {
122 .usecase = nss_netap_bw_level_tbl,
123 .num_usecases = ARRAY_SIZE(nss_netap_bw_level_tbl),
124 .active_only = 1,
125 .name = "qca-nss-drv",
126 },
127};
128
129/*
130 * nss_pm_dbg_perf_level_get
131 * debugfs hook to get the current performance level
132 */
133static int nss_pm_dbg_perf_level_get(void *data, u64 *val)
134{
135 nss_pm_client_data_t *pm_client;
136
137 pm_client = (nss_pm_client_data_t *)data;
138 *val = pm_client->current_perf_lvl;
139
140 return NSS_PM_API_SUCCESS;
141}
142
143/*
144 * nss_pm_dbg_autoscale_get
145 * debugfs hook to get the current autoscale setting
146 */
147static int nss_pm_dbg_autoscale_get(void *data, u64 *val)
148{
149 nss_pm_client_data_t *pm_client;
150
151 pm_client = (nss_pm_client_data_t *)data;
152 *val = pm_client->auto_scale;
153
154 return NSS_PM_API_SUCCESS;
155}
156
157/*
158 * nss_pm_dbg_perf_level_set
159 * debugfs hook to set perf level for a client
160 */
161static int nss_pm_dbg_perf_level_set(void *data, u64 val)
162{
163 uint32_t perf_level;
164
165 perf_level = (uint32_t) val;
166
167 if (perf_level >= NSS_PM_PERF_MAX_LEVELS ||
168 perf_level < NSS_PM_PERF_LEVEL_IDLE) {
169 nss_pm_warning("unsupported performance level %d \n", perf_level);
170 return NSS_PM_API_FAILED;
171 }
172
173 nss_pm_set_perf_level(data, perf_level);
174 return NSS_PM_API_SUCCESS;
175}
176
177/*
178 * nss_pm_dbg_autoscale_set
179 * debugfs hook to enable auto scaling for a client
180 */
181static int nss_pm_dbg_autoscale_set(void *data, u64 val)
182{
183 nss_pm_client_data_t *pm_client;
184
185 if (val > 1) {
186 nss_pm_warning(" Invalid set value, valid values are 0/1 \n");
187 return NSS_PM_API_FAILED;
188 }
189
190 pm_client->auto_scale = (uint32_t)val;
191 return NSS_PM_API_SUCCESS;
192}
193
194DEFINE_SIMPLE_ATTRIBUTE(perf_level_fops, nss_pm_dbg_perf_level_get, nss_pm_dbg_perf_level_set, "%llu\n");
195
196DEFINE_SIMPLE_ATTRIBUTE(autoscale_fops, nss_pm_dbg_autoscale_get, nss_pm_dbg_autoscale_set, "%llu\n");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800197#endif /** (NSS_PM_SUPPORT == 1) */
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530198
199/*
200 * nss_pm_client_register
201 * Initialize GMAC specific PM parameters
202 *
203 * Creates debugfs hooks for user-space control of NSS Client PM
204 * Initializes Bus BW to Idle Perf level
205 * Returns PM handle to the caller.
206 *
207 */
208void *nss_pm_client_register(nss_pm_client_t client_id)
209{
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800210#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530211 int ret;
212 struct dentry *pm_dentry;
213 nss_pm_client_data_t *pm_client;
214
215 if (unlikely(client_id >= NSS_PM_MAX_CLIENTS)) {
216 nss_pm_warning("nss_pm_client_register invalid client id %d \n", client_id);
217 goto error;
218 }
219
220 pm_client = &ctx.nss_pm_client[client_id];
221
222 pm_client->bus_perf_client = msm_bus_scale_register_client(&nss_bus_scale[client_id]);
223 if (!pm_client->bus_perf_client) {
224 nss_pm_warning("unable to register bus client \n");
225 goto error;
226 }
227
228 ret = msm_bus_scale_client_update_request(pm_client->bus_perf_client, NSS_PM_PERF_LEVEL_IDLE);
229 if (ret) {
230 nss_pm_warning("initial bandwidth req failed (%d)\n", ret);
231 msm_bus_scale_unregister_client((uint32_t) pm_client->bus_perf_client);
232 goto error;
233 }
234
235 pm_client->current_perf_lvl = NSS_PM_PERF_LEVEL_IDLE;
236
237 switch (client_id) {
238 case NSS_PM_CLIENT_GMAC:
239 pm_dentry = debugfs_create_dir("gmac" , ctx.pm_dentry);
240 break;
241
242 case NSS_PM_CLIENT_CRYPTO:
243 pm_dentry = debugfs_create_dir("crypto" , ctx.pm_dentry);
244 break;
245
246 case NSS_PM_CLIENT_NETAP:
247 pm_dentry = debugfs_create_dir("netap" , ctx.pm_dentry);
248 break;
249
250 default:
251 nss_pm_warning("debugfs create failed invalid client id %d \n", client_id);
252 msm_bus_scale_unregister_client((uint32_t) pm_client->bus_perf_client);
253 goto error;
254
255 }
256
257 if (unlikely(pm_dentry == NULL)) {
258 nss_pm_info("debugfs not created for %d client pm \n", client_id);
259 goto out;
260 }
261
262 pm_client->dentry = pm_dentry;
Pamidipati, Vijay3e053882013-12-03 17:34:31 +0530263 pm_client->client_id = client_id;
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530264
265 if (!debugfs_create_file("perf_level", S_IRUGO | S_IWUSR, pm_dentry, pm_client, &perf_level_fops)) {
266 nss_pm_info("debugfs perf_level file not created for %d client pm \n", client_id);
267 }
268
269 if (!debugfs_create_file("auto-scale", S_IRUGO | S_IWUSR, pm_dentry, pm_client, &autoscale_fops)) {
270 nss_pm_info("debugfs auto-scale file not created for %d client pm \n", client_id);
271 }
272
273out:
274 return (void *)pm_client;
275error:
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800276#endif
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530277 return NULL;
278}
279EXPORT_SYMBOL(nss_pm_client_register);
280
281/*
282 * nss_pm_client_unregister
283 * Unregister the client for any PM operations
284 */
285int nss_pm_client_unregister(nss_pm_client_t client_id)
286{
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800287#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530288 nss_pm_client_data_t *pm_client;
289
290 if (unlikely(client_id >= NSS_PM_MAX_CLIENTS)) {
291 nss_pm_warning("nss_pm_client_unregister invalid client id %d \n", client_id);
292 goto error;
293 }
294
295 pm_client = &ctx.nss_pm_client[client_id];
296
297 if (unlikely(pm_client == NULL)) {
298 nss_pm_warning("nss_pm_client_unregister client not registered %d \n", client_id);
299 goto error;
300 }
301
302 if (pm_client->bus_perf_client) {
303 msm_bus_scale_unregister_client((uint32_t) pm_client->bus_perf_client);
304 } else {
305 nss_pm_info("nss_pm_client_unregister: client not registered \n");
306 }
307
308 if (likely(pm_client->dentry != NULL)) {
309 debugfs_remove_recursive(pm_client->dentry);
310 }
311
312 return NSS_PM_API_SUCCESS;
313
314error:
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800315#endif
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530316 return NSS_PM_API_FAILED;
317}
318
319/*
320 * nss_pm_set_perf_level()
321 * Sets the performance level of client specific Fabrics and Clocks to requested level
322 */
323nss_pm_interface_status_t nss_pm_set_perf_level(void *handle, nss_pm_perf_level_t lvl)
324{
Arunkumar Tca6baae2016-08-22 14:11:08 +0530325#if ((NSS_DT_SUPPORT == 1) && (NSS_FREQ_SCALE_SUPPORT == 1))
Samarjeet Banerjeeb126e0f2016-08-05 20:58:27 +0530326 nss_freq_scales_t index;
327
328 switch (lvl) {
329 case NSS_PM_PERF_LEVEL_TURBO:
330 index = NSS_FREQ_HIGH_SCALE;
331 break;
332
333 case NSS_PM_PERF_LEVEL_NOMINAL:
334 index = NSS_FREQ_MID_SCALE;
335 break;
336
337 default:
338 index = NSS_PM_PERF_LEVEL_IDLE;
339 }
340
Tanmay V Jagdale20490fb2017-02-09 17:32:31 +0530341#if !defined(NSS_HAL_IPQ807x_SUPPORT)
Samarjeet Banerjeeb126e0f2016-08-05 20:58:27 +0530342 nss_freq_sched_change(index, false);
Tanmay V Jagdale20490fb2017-02-09 17:32:31 +0530343#endif
Samarjeet Banerjeeb126e0f2016-08-05 20:58:27 +0530344
345#elif (NSS_PM_SUPPORT == 1)
346
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530347 int ret = 0;
348 nss_pm_client_data_t *pm_client;
349
350 pm_client = (nss_pm_client_data_t *) handle;
351 if (pm_client->current_perf_lvl == lvl) {
352 nss_pm_trace("Already at perf level %d , ignoring request \n", lvl);
353 return NSS_PM_API_SUCCESS;
354 }
355
356 if (!pm_client->bus_perf_client) {
357 nss_pm_warning("Bus driver client not registered.request failed \n");
358 return NSS_PM_API_FAILED;
359 }
360
Pamidipati, Vijay3e053882013-12-03 17:34:31 +0530361 /*
362 * Do client specific operations here
363 */
364 if (pm_client->client_id == NSS_PM_CLIENT_NETAP) {
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530365 if ((lvl == NSS_PM_PERF_LEVEL_TURBO) && (ctx.turbo_support == true)) {
Pamidipati, Vijay3e053882013-12-03 17:34:31 +0530366 /*
367 * For turbo perf level, switch TCM source to
368 * SRC1 to set TCM clock = 400 MHz
369 * SRC0 and SRC1 are set to 266 and 400 MHz resp.
370 * in nss_hal/ipq806x/nss_hal_pvt.c
371 */
372 writel(0x3, NSSTCM_CLK_SRC_CTL);
373 } else {
374 /*
375 * For Nominal and Idle perf level, switch to SRC0 to
376 * set TCM clock = 266 MHz
377 */
378 writel(0x2, NSSTCM_CLK_SRC_CTL);
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530379
380 if (lvl == NSS_PM_PERF_LEVEL_TURBO) {
381 lvl = NSS_PM_PERF_LEVEL_NOMINAL;
382 }
383 }
384 }
385
386 if (pm_client->client_id == NSS_PM_CLIENT_CRYPTO) {
387 if ((lvl == NSS_PM_PERF_LEVEL_TURBO) && (ctx.turbo_support == true)) {
388 /*
389 * For Turbo mode, set Crypto core and
390 * Fabric port clocks to 213 MHz
391 */
392 writel(0x23, CE5_ACLK_SRC0_NS);
393 writel(0x23, CE5_HCLK_SRC0_NS);
394 writel(0x23, CE5_CORE_CLK_SRC0_NS);
395
396 writel(0x2, CE5_ACLK_SRC_CTL);
397 writel(0x2, CE5_HCLK_SRC_CTL);
398 writel(0x2, CE5_CORE_CLK_SRC_CTL);
399 } else {
400 lvl = NSS_PM_PERF_LEVEL_NOMINAL;
Pamidipati, Vijay3e053882013-12-03 17:34:31 +0530401 }
402 }
403
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530404 /* Update bandwidth if request has changed. This may sleep. */
405 ret = msm_bus_scale_client_update_request(pm_client->bus_perf_client, lvl);
406 if (ret) {
407 nss_pm_warning("bandwidth request failed (%d)\n", ret);
408 return NSS_PM_API_FAILED;
409 }
410
411 nss_pm_info("perf level request, current: %d new: %d \n", pm_client->current_perf_lvl, lvl);
412 pm_client->current_perf_lvl = lvl;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800413#endif
Samarjeet Banerjeeb126e0f2016-08-05 20:58:27 +0530414
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530415 return NSS_PM_API_SUCCESS;
416}
417EXPORT_SYMBOL(nss_pm_set_perf_level);
418
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800419#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530420/*
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530421 * nss_pm_set_turbo()
422 * Sets the turbo support flag globally for all clients
423 */
424void nss_pm_set_turbo() {
425
426 nss_pm_info("NSS Bus PM - Platform supports Turbo Mode \n");
427 ctx.turbo_support = true;
428}
429
430/*
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530431 * nss_pm_init()
432 * Initialize NSS PM top level structures
433 */
434void nss_pm_init(void) {
435
436 nss_pm_info("NSS Bus PM (platform - IPQ806x, build - %s:%s)\n", __DATE__, __TIME__);
437
438 ctx.pm_dentry = debugfs_create_dir("qca-nss-pm", NULL);
439
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530440 /* Default turbo support is set to off */
441 ctx.turbo_support = false;
442
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530443 if (unlikely(ctx.pm_dentry == NULL)) {
444 nss_pm_warning("Failed to create qca-nss-drv directory in debugfs");
445 }
446}
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800447#endif