blob: ab4f130eb6f0e7f553b29ee03c9960b32eb3f4c1 [file] [log] [blame]
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +05301/*
2 **************************************************************************
Arunkumar T8ebe1532015-06-10 16:01:53 +05303 * Copyright (c) 2014,2015, 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>
Arunkumar T8ebe1532015-06-10 16:01:53 +053025#include <nss_hal.h>
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080026#include <nss_api_if.h>
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053027
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080028#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053029#include "nss_pm.h"
30
31/*
32 * Global NSS PM structure
33 */
34struct nss_pm_global_ctx ctx;
35
36/*
37 * Bus vector table for GMAC driver
38 */
39static struct msm_bus_paths nss_gmac_bw_level_tbl[NSS_PM_PERF_MAX_LEVELS] = {
40 [NSS_PM_PERF_LEVEL_SUSPEND] = GMAC_BW_MBPS(0, 0),
41 /* 0 MHz to DDR, 0 MHz to TCM */
42 [NSS_PM_PERF_LEVEL_IDLE] = GMAC_BW_MBPS(133, 5),
43 /* 133 MHz to DDR, 5 MHz to TCM */
44 [NSS_PM_PERF_LEVEL_NOMINAL] = GMAC_BW_MBPS(200, 400),
45 /* 200 MHz to DDR, 10 MHz to TCM */
46 [NSS_PM_PERF_LEVEL_TURBO] = GMAC_BW_MBPS(266, 533),
47 /* 266 MHz to DDR, 20 MHz to TCM */
48};
49
50/*
51 * Bus vector table for Crypto driver
52 */
53static struct msm_bus_paths nss_crypto_bw_level_tbl[NSS_PM_PERF_MAX_LEVELS] = {
54 [NSS_PM_PERF_LEVEL_SUSPEND] = CRYPTO_BW_MBPS(0, 0),
55 /* 0 MHz to DDR, 0 MHz to TCM */
56 [NSS_PM_PERF_LEVEL_IDLE] = CRYPTO_BW_MBPS(133, 5),
57 /* 133 MHz to DDR, 5 MHz to TCM */
58 [NSS_PM_PERF_LEVEL_NOMINAL] = CRYPTO_BW_MBPS(200, 400),
59 /* 200 MHz to DDR, 10 MHz to TCM */
60 [NSS_PM_PERF_LEVEL_TURBO] = CRYPTO_BW_MBPS(266, 533),
61 /* 266 MHz to DDR, 20 MHz to TCM */
62};
63
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053064#ifdef NSS_PM_NETAP_GMAC_SCALING
65
66/*
67 * Bus vector table for NSS HLOS driver
68 * This requests bw for both NSS Fab0 and Fab1 on behalf of GMAC and NSS Drivers
69 */
70static struct msm_bus_paths nss_netap_bw_level_tbl[NSS_PM_PERF_MAX_LEVELS] = {
71 [NSS_PM_PERF_LEVEL_SUSPEND] = GMAC_BW_MBPS(0, 0),
72 /* 0 MHz to DDR, 0 MHz to TCM */
73 [NSS_PM_PERF_LEVEL_IDLE] = GMAC_BW_MBPS(133, 5),
74 /* 133 MHz to DDR, 5 MHz to TCM */
75 [NSS_PM_PERF_LEVEL_NOMINAL] = GMAC_BW_MBPS(200, 400),
76 /* 200 MHz to DDR, 10 MHz to TCM */
77 [NSS_PM_PERF_LEVEL_TURBO] = GMAC_BW_MBPS(266, 533),
78 /* 266 MHz to DDR, 20 MHz to TCM */
79};
80
81#else
82
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053083/*
84 * Bus vector table for NSS HLOS driver
85 */
86static struct msm_bus_paths nss_netap_bw_level_tbl[NSS_PM_PERF_MAX_LEVELS] = {
87 [NSS_PM_PERF_LEVEL_SUSPEND] = NETAP_BW_MBPS(0, 0),
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053088 /* 0 MHz to DDR, 0 MHz to TCM */
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053089 [NSS_PM_PERF_LEVEL_IDLE] = NETAP_BW_MBPS(133, 133),
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053090 /* 133 MHz to DDR and TCM */
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053091 [NSS_PM_PERF_LEVEL_NOMINAL] = NETAP_BW_MBPS(400, 400),
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053092 /* 400 MHz to DDR and TCM */
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053093 [NSS_PM_PERF_LEVEL_TURBO] = NETAP_BW_MBPS(533, 533),
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053094 /* 533 MHz to DDR and TCM */
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053095};
96
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053097#endif
98
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053099/*
100 * Bus Driver Platform data for GMAC, Crypto and Netap clients
101 */
102static struct msm_bus_scale_pdata nss_bus_scale[] = {
103 [NSS_PM_CLIENT_GMAC] = {
104 .usecase = nss_gmac_bw_level_tbl,
105 .num_usecases = ARRAY_SIZE(nss_gmac_bw_level_tbl),
106 .active_only = 1,
107 .name = "qca-nss-gmac",
108 },
109
110 [NSS_PM_CLIENT_CRYPTO] = {
111 .usecase = nss_crypto_bw_level_tbl,
112 .num_usecases = ARRAY_SIZE(nss_crypto_bw_level_tbl),
113 .active_only = 1,
114 .name = "qca-nss-crypto",
115 },
116
117 [NSS_PM_CLIENT_NETAP] = {
118 .usecase = nss_netap_bw_level_tbl,
119 .num_usecases = ARRAY_SIZE(nss_netap_bw_level_tbl),
120 .active_only = 1,
121 .name = "qca-nss-drv",
122 },
123};
124
125/*
126 * nss_pm_dbg_perf_level_get
127 * debugfs hook to get the current performance level
128 */
129static int nss_pm_dbg_perf_level_get(void *data, u64 *val)
130{
131 nss_pm_client_data_t *pm_client;
132
133 pm_client = (nss_pm_client_data_t *)data;
134 *val = pm_client->current_perf_lvl;
135
136 return NSS_PM_API_SUCCESS;
137}
138
139/*
140 * nss_pm_dbg_autoscale_get
141 * debugfs hook to get the current autoscale setting
142 */
143static int nss_pm_dbg_autoscale_get(void *data, u64 *val)
144{
145 nss_pm_client_data_t *pm_client;
146
147 pm_client = (nss_pm_client_data_t *)data;
148 *val = pm_client->auto_scale;
149
150 return NSS_PM_API_SUCCESS;
151}
152
153/*
154 * nss_pm_dbg_perf_level_set
155 * debugfs hook to set perf level for a client
156 */
157static int nss_pm_dbg_perf_level_set(void *data, u64 val)
158{
159 uint32_t perf_level;
160
161 perf_level = (uint32_t) val;
162
163 if (perf_level >= NSS_PM_PERF_MAX_LEVELS ||
164 perf_level < NSS_PM_PERF_LEVEL_IDLE) {
165 nss_pm_warning("unsupported performance level %d \n", perf_level);
166 return NSS_PM_API_FAILED;
167 }
168
169 nss_pm_set_perf_level(data, perf_level);
170 return NSS_PM_API_SUCCESS;
171}
172
173/*
174 * nss_pm_dbg_autoscale_set
175 * debugfs hook to enable auto scaling for a client
176 */
177static int nss_pm_dbg_autoscale_set(void *data, u64 val)
178{
179 nss_pm_client_data_t *pm_client;
180
181 if (val > 1) {
182 nss_pm_warning(" Invalid set value, valid values are 0/1 \n");
183 return NSS_PM_API_FAILED;
184 }
185
186 pm_client->auto_scale = (uint32_t)val;
187 return NSS_PM_API_SUCCESS;
188}
189
190DEFINE_SIMPLE_ATTRIBUTE(perf_level_fops, nss_pm_dbg_perf_level_get, nss_pm_dbg_perf_level_set, "%llu\n");
191
192DEFINE_SIMPLE_ATTRIBUTE(autoscale_fops, nss_pm_dbg_autoscale_get, nss_pm_dbg_autoscale_set, "%llu\n");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800193#endif /** (NSS_PM_SUPPORT == 1) */
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530194
195/*
196 * nss_pm_client_register
197 * Initialize GMAC specific PM parameters
198 *
199 * Creates debugfs hooks for user-space control of NSS Client PM
200 * Initializes Bus BW to Idle Perf level
201 * Returns PM handle to the caller.
202 *
203 */
204void *nss_pm_client_register(nss_pm_client_t client_id)
205{
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800206#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530207 int ret;
208 struct dentry *pm_dentry;
209 nss_pm_client_data_t *pm_client;
210
211 if (unlikely(client_id >= NSS_PM_MAX_CLIENTS)) {
212 nss_pm_warning("nss_pm_client_register invalid client id %d \n", client_id);
213 goto error;
214 }
215
216 pm_client = &ctx.nss_pm_client[client_id];
217
218 pm_client->bus_perf_client = msm_bus_scale_register_client(&nss_bus_scale[client_id]);
219 if (!pm_client->bus_perf_client) {
220 nss_pm_warning("unable to register bus client \n");
221 goto error;
222 }
223
224 ret = msm_bus_scale_client_update_request(pm_client->bus_perf_client, NSS_PM_PERF_LEVEL_IDLE);
225 if (ret) {
226 nss_pm_warning("initial bandwidth req failed (%d)\n", ret);
227 msm_bus_scale_unregister_client((uint32_t) pm_client->bus_perf_client);
228 goto error;
229 }
230
231 pm_client->current_perf_lvl = NSS_PM_PERF_LEVEL_IDLE;
232
233 switch (client_id) {
234 case NSS_PM_CLIENT_GMAC:
235 pm_dentry = debugfs_create_dir("gmac" , ctx.pm_dentry);
236 break;
237
238 case NSS_PM_CLIENT_CRYPTO:
239 pm_dentry = debugfs_create_dir("crypto" , ctx.pm_dentry);
240 break;
241
242 case NSS_PM_CLIENT_NETAP:
243 pm_dentry = debugfs_create_dir("netap" , ctx.pm_dentry);
244 break;
245
246 default:
247 nss_pm_warning("debugfs create failed invalid client id %d \n", client_id);
248 msm_bus_scale_unregister_client((uint32_t) pm_client->bus_perf_client);
249 goto error;
250
251 }
252
253 if (unlikely(pm_dentry == NULL)) {
254 nss_pm_info("debugfs not created for %d client pm \n", client_id);
255 goto out;
256 }
257
258 pm_client->dentry = pm_dentry;
Pamidipati, Vijay3e053882013-12-03 17:34:31 +0530259 pm_client->client_id = client_id;
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530260
261 if (!debugfs_create_file("perf_level", S_IRUGO | S_IWUSR, pm_dentry, pm_client, &perf_level_fops)) {
262 nss_pm_info("debugfs perf_level file not created for %d client pm \n", client_id);
263 }
264
265 if (!debugfs_create_file("auto-scale", S_IRUGO | S_IWUSR, pm_dentry, pm_client, &autoscale_fops)) {
266 nss_pm_info("debugfs auto-scale file not created for %d client pm \n", client_id);
267 }
268
269out:
270 return (void *)pm_client;
271error:
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800272#endif
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530273 return NULL;
274}
275EXPORT_SYMBOL(nss_pm_client_register);
276
277/*
278 * nss_pm_client_unregister
279 * Unregister the client for any PM operations
280 */
281int nss_pm_client_unregister(nss_pm_client_t client_id)
282{
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800283#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530284 nss_pm_client_data_t *pm_client;
285
286 if (unlikely(client_id >= NSS_PM_MAX_CLIENTS)) {
287 nss_pm_warning("nss_pm_client_unregister invalid client id %d \n", client_id);
288 goto error;
289 }
290
291 pm_client = &ctx.nss_pm_client[client_id];
292
293 if (unlikely(pm_client == NULL)) {
294 nss_pm_warning("nss_pm_client_unregister client not registered %d \n", client_id);
295 goto error;
296 }
297
298 if (pm_client->bus_perf_client) {
299 msm_bus_scale_unregister_client((uint32_t) pm_client->bus_perf_client);
300 } else {
301 nss_pm_info("nss_pm_client_unregister: client not registered \n");
302 }
303
304 if (likely(pm_client->dentry != NULL)) {
305 debugfs_remove_recursive(pm_client->dentry);
306 }
307
308 return NSS_PM_API_SUCCESS;
309
310error:
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800311#endif
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530312 return NSS_PM_API_FAILED;
313}
314
315/*
316 * nss_pm_set_perf_level()
317 * Sets the performance level of client specific Fabrics and Clocks to requested level
318 */
319nss_pm_interface_status_t nss_pm_set_perf_level(void *handle, nss_pm_perf_level_t lvl)
320{
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800321#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530322 int ret = 0;
323 nss_pm_client_data_t *pm_client;
324
325 pm_client = (nss_pm_client_data_t *) handle;
326 if (pm_client->current_perf_lvl == lvl) {
327 nss_pm_trace("Already at perf level %d , ignoring request \n", lvl);
328 return NSS_PM_API_SUCCESS;
329 }
330
331 if (!pm_client->bus_perf_client) {
332 nss_pm_warning("Bus driver client not registered.request failed \n");
333 return NSS_PM_API_FAILED;
334 }
335
Pamidipati, Vijay3e053882013-12-03 17:34:31 +0530336 /*
337 * Do client specific operations here
338 */
339 if (pm_client->client_id == NSS_PM_CLIENT_NETAP) {
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530340 if ((lvl == NSS_PM_PERF_LEVEL_TURBO) && (ctx.turbo_support == true)) {
Pamidipati, Vijay3e053882013-12-03 17:34:31 +0530341 /*
342 * For turbo perf level, switch TCM source to
343 * SRC1 to set TCM clock = 400 MHz
344 * SRC0 and SRC1 are set to 266 and 400 MHz resp.
345 * in nss_hal/ipq806x/nss_hal_pvt.c
346 */
347 writel(0x3, NSSTCM_CLK_SRC_CTL);
348 } else {
349 /*
350 * For Nominal and Idle perf level, switch to SRC0 to
351 * set TCM clock = 266 MHz
352 */
353 writel(0x2, NSSTCM_CLK_SRC_CTL);
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530354
355 if (lvl == NSS_PM_PERF_LEVEL_TURBO) {
356 lvl = NSS_PM_PERF_LEVEL_NOMINAL;
357 }
358 }
359 }
360
361 if (pm_client->client_id == NSS_PM_CLIENT_CRYPTO) {
362 if ((lvl == NSS_PM_PERF_LEVEL_TURBO) && (ctx.turbo_support == true)) {
363 /*
364 * For Turbo mode, set Crypto core and
365 * Fabric port clocks to 213 MHz
366 */
367 writel(0x23, CE5_ACLK_SRC0_NS);
368 writel(0x23, CE5_HCLK_SRC0_NS);
369 writel(0x23, CE5_CORE_CLK_SRC0_NS);
370
371 writel(0x2, CE5_ACLK_SRC_CTL);
372 writel(0x2, CE5_HCLK_SRC_CTL);
373 writel(0x2, CE5_CORE_CLK_SRC_CTL);
374 } else {
375 lvl = NSS_PM_PERF_LEVEL_NOMINAL;
Pamidipati, Vijay3e053882013-12-03 17:34:31 +0530376 }
377 }
378
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530379 /* Update bandwidth if request has changed. This may sleep. */
380 ret = msm_bus_scale_client_update_request(pm_client->bus_perf_client, lvl);
381 if (ret) {
382 nss_pm_warning("bandwidth request failed (%d)\n", ret);
383 return NSS_PM_API_FAILED;
384 }
385
386 nss_pm_info("perf level request, current: %d new: %d \n", pm_client->current_perf_lvl, lvl);
387 pm_client->current_perf_lvl = lvl;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800388#endif
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530389 return NSS_PM_API_SUCCESS;
390}
391EXPORT_SYMBOL(nss_pm_set_perf_level);
392
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800393#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530394/*
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530395 * nss_pm_set_turbo()
396 * Sets the turbo support flag globally for all clients
397 */
398void nss_pm_set_turbo() {
399
400 nss_pm_info("NSS Bus PM - Platform supports Turbo Mode \n");
401 ctx.turbo_support = true;
402}
403
404/*
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530405 * nss_pm_init()
406 * Initialize NSS PM top level structures
407 */
408void nss_pm_init(void) {
409
410 nss_pm_info("NSS Bus PM (platform - IPQ806x, build - %s:%s)\n", __DATE__, __TIME__);
411
412 ctx.pm_dentry = debugfs_create_dir("qca-nss-pm", NULL);
413
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530414 /* Default turbo support is set to off */
415 ctx.turbo_support = false;
416
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530417 if (unlikely(ctx.pm_dentry == NULL)) {
418 nss_pm_warning("Failed to create qca-nss-drv directory in debugfs");
419 }
420}
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800421#endif