blob: afdd3b52c94a181a617a9ef1bae6ad70794f3d39 [file] [log] [blame]
Radhakrishna Jiguru1c9b2252013-08-27 23:57:48 +05301/*
2 **************************************************************************
3 * Copyright (c) 2013, Qualcomm Atheros, Inc.
4 * 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 */
Abhishek Rastogibc74e432013-04-02 10:28:22 +053016
17/*
18 * nss_init.c
19 * NSS init APIs
20 *
21 */
22
23#include "nss_core.h"
24#include <nss_hal.h>
25
26#include <linux/module.h>
27#include <linux/platform_device.h>
wthomas442c7972013-08-05 14:28:17 -070028#include <linux/proc_fs.h>
29#include <linux/device.h>
Abhishek Rastogibc74e432013-04-02 10:28:22 +053030#include <mach/msm_nss.h>
31
wthomas442c7972013-08-05 14:28:17 -070032#include <linux/sysctl.h>
33#include <linux/regulator/consumer.h>
34
Abhishek Rastogibc74e432013-04-02 10:28:22 +053035/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +053036 * Declare module parameters
37 */
38static int load0 = 0x40000000;
39module_param(load0, int, S_IRUSR | S_IWUSR);
40MODULE_PARM_DESC(load0, "NSS Core 0 load address");
41
42static int entry0 = 0x40000000;
43module_param(entry0, int, S_IRUSR | S_IWUSR);
44MODULE_PARM_DESC(load0, "NSS Core 0 entry address");
45
46static char *string0 = "nss0";
47module_param(string0, charp, 0);
48MODULE_PARM_DESC(string0, "NSS Core 0 identification string");
49
50static int load1 = 0x40100000;
51module_param(load1, int, S_IRUSR | S_IWUSR);
52MODULE_PARM_DESC(load0, "NSS Core 1 load address");
53
54static int entry1 = 0x40100000;
55module_param(entry1, int, S_IRUSR | S_IWUSR);
56MODULE_PARM_DESC(load0, "NSS Core 1 entry address");
57
58static char *string1 = "nss1";
59module_param(string1, charp, 0);
60MODULE_PARM_DESC(string1, "NSS Core 1 identification string");
61
62
63/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +053064 * Global declarations
65 */
66
wthomas442c7972013-08-05 14:28:17 -070067
68/*
69 * Define for RPM Nominal and Turbo for NSS
70 */
71#define NSS_NOM_VCC 1050000
72#define NSS_TURB_VCC 1150000
73
74/*
75 * Global Handlers for the nss regulators
76 */
77struct regulator *nss0_vreg;
78
Abhishek Rastogibc74e432013-04-02 10:28:22 +053079/*
80 * Top level nss context structure
81 */
82struct nss_top_instance nss_top_main;
wthomas442c7972013-08-05 14:28:17 -070083struct nss_cmd_buffer nss_cmd_buf;
Abhishek Rastogibc74e432013-04-02 10:28:22 +053084
85/*
86 * File local/Static variables/functions
87 */
88
Abhishek Rastogi271eee72013-07-29 21:08:36 +053089static const struct net_device_ops nss_netdev_ops;
90static const struct ethtool_ops nss_ethtool_ops;
91
92/*
93 * nss_dummy_netdev_setup()
94 * Dummy setup for net_device handler
95 */
96static void nss_dummy_netdev_setup(struct net_device *ndev)
97{
98 return;
99}
100
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530101/*
102 * nss_handle_irq()
103 * HLOS interrupt handler for nss interrupts
104 */
105static irqreturn_t nss_handle_irq (int irq, void *ctx)
106{
107 struct int_ctx_instance *int_ctx = (struct int_ctx_instance *) ctx;
108
109 /*
110 * Disable IRQ until our bottom half re-enables it
111 */
112 disable_irq_nosync(irq);
113
114 /*
115 * Schedule tasklet to process interrupt cause
116 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530117 napi_schedule(&int_ctx->napi);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530118 return IRQ_HANDLED;
119}
120
121/*
122 * nss_probe()
123 * HLOS device probe callback
124 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530125static int __devinit nss_probe(struct platform_device *nss_dev)
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530126{
127 struct nss_top_instance *nss_top = &nss_top_main;
128 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
129 struct nss_platform_data *npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530130 struct netdev_priv_instance *ndev_priv;
131 int i, err = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530132
133 nss_ctx->nss_top = nss_top;
134 nss_ctx->id = nss_dev->id;
135
wthomas442c7972013-08-05 14:28:17 -0700136 nss_info("%p: NSS_DEV_ID %s \n", nss_ctx, dev_name(&nss_dev->dev));
137
138 /*
139 * Both NSS cores controlled by same regulator, Hook only Once
140 */
141 if (!nss_dev->id) {
142 nss0_vreg = devm_regulator_get(&nss_dev->dev, "VDD_UBI0");
143
144 if (IS_ERR(nss0_vreg)) {
145
146 err = PTR_ERR(nss0_vreg);
147 nss_info("%p: Regulator %s get failed, err=%d\n", nss_ctx, dev_name(&nss_dev->dev), err);
148 return err;
149
150 } else {
151
152 nss_info("%p: Regulator %s get success\n", nss_ctx, dev_name(&nss_dev->dev));
153
154 err = regulator_enable(nss0_vreg);
155 if (err) {
156 nss_info("%p: Regulator %s enable voltage failed, err=%d\n", nss_ctx, dev_name(&nss_dev->dev), err);
157 return err;
158 }
159
160 err = regulator_set_voltage(nss0_vreg, NSS_NOM_VCC, NSS_NOM_VCC);
161 if (err) {
162 nss_info("%p: Regulator %s set voltage failed, err=%d\n", nss_ctx, dev_name(&nss_dev->dev), err);
163 return err;
164 }
165
166
167 }
168 }
169
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530170 /*
171 * Get virtual and physical memory addresses for nss logical/hardware address maps
172 */
173
174 /*
175 * Virtual address of CSM space
176 */
177 nss_ctx->nmap = npd->nmap;
178 nss_assert(nss_ctx->nmap);
179
180 /*
181 * Physical address of CSM space
182 */
183 nss_ctx->nphys = npd->nphys;
184 nss_assert(nss_ctx->nphys);
185
186 /*
187 * Virtual address of logical registers space
188 */
189 nss_ctx->vmap = npd->vmap;
190 nss_assert(nss_ctx->vmap);
191
192 /*
193 * Physical address of logical registers space
194 */
195 nss_ctx->vphys = npd->vphys;
196 nss_assert(nss_ctx->vphys);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530197 nss_info("%d:ctx=%p, vphys=%x, vmap=%x, nphys=%x, nmap=%x",
198 nss_dev->id, nss_ctx, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
199
200 /*
201 * Register netdevice handlers
202 */
203 nss_ctx->int_ctx[0].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
204 "qca-nss-dev%d", nss_dummy_netdev_setup);
205 if (nss_ctx->int_ctx[0].ndev == NULL) {
206 nss_warning("%p: Could not allocate net_device #0", nss_ctx);
207 err = -ENOMEM;
208 goto err_init_0;
209 }
210
211 nss_ctx->int_ctx[0].ndev->netdev_ops = &nss_netdev_ops;
212 nss_ctx->int_ctx[0].ndev->ethtool_ops = &nss_ethtool_ops;
213 err = register_netdev(nss_ctx->int_ctx[0].ndev);
214 if (err) {
215 nss_warning("%p: Could not register net_device #0", nss_ctx);
216 goto err_init_1;
217 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530218
219 /*
220 * request for IRQs
221 *
222 * WARNING: CPU affinities should be set using OS supported methods
223 */
224 nss_ctx->int_ctx[0].nss_ctx = nss_ctx;
225 nss_ctx->int_ctx[0].shift_factor = 0;
226 nss_ctx->int_ctx[0].irq = npd->irq[0];
227 err = request_irq(npd->irq[0], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[0]);
228 if (err) {
229 nss_warning("%d: IRQ0 request failed", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530230 goto err_init_2;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530231 }
232
233 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530234 * Register NAPI for NSS core interrupt #0
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530235 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530236 ndev_priv = netdev_priv(nss_ctx->int_ctx[0].ndev);
237 ndev_priv->int_ctx = &nss_ctx->int_ctx[0];
238 netif_napi_add(nss_ctx->int_ctx[0].ndev, &nss_ctx->int_ctx[0].napi, nss_core_handle_napi, 64);
239 napi_enable(&nss_ctx->int_ctx[0].napi);
240 nss_ctx->int_ctx[0].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530241
242 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530243 * Check if second interrupt is supported on this nss core
244 */
245 if (npd->num_irq > 1) {
246 nss_info("%d: This NSS core supports two interrupts", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530247
248 /*
249 * Register netdevice handlers
250 */
251 nss_ctx->int_ctx[1].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
252 "qca-nss-dev%d", nss_dummy_netdev_setup);
253 if (nss_ctx->int_ctx[1].ndev == NULL) {
254 nss_warning("%p: Could not allocate net_device #1", nss_ctx);
255 err = -ENOMEM;
256 goto err_init_3;
257 }
258
259 nss_ctx->int_ctx[1].ndev->netdev_ops = &nss_netdev_ops;
260 nss_ctx->int_ctx[1].ndev->ethtool_ops = &nss_ethtool_ops;
261 err = register_netdev(nss_ctx->int_ctx[1].ndev);
262 if (err) {
263 nss_warning("%p: Could not register net_device #1", nss_ctx);
264 goto err_init_4;
265 }
266
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530267 nss_ctx->int_ctx[1].nss_ctx = nss_ctx;
268 nss_ctx->int_ctx[1].shift_factor = 15;
269 nss_ctx->int_ctx[1].irq = npd->irq[1];
270 err = request_irq(npd->irq[1], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[1]);
271 if (err) {
272 nss_warning("%d: IRQ1 request failed for nss", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530273 goto err_init_5;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530274 }
275
276 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530277 * Register NAPI for NSS core interrupt #1
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530278 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530279 ndev_priv = netdev_priv(nss_ctx->int_ctx[1].ndev);
280 ndev_priv->int_ctx = &nss_ctx->int_ctx[1];
281 netif_napi_add(nss_ctx->int_ctx[1].ndev, &nss_ctx->int_ctx[1].napi, nss_core_handle_napi, 64);
282 napi_enable(&nss_ctx->int_ctx[1].napi);
283 nss_ctx->int_ctx[1].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530284 }
285
286 spin_lock_bh(&(nss_top->lock));
287
288 /*
289 * Check functionalities are supported by this NSS core
290 */
291 if (npd->ipv4_enabled == NSS_FEATURE_ENABLED) {
292 nss_top->ipv4_handler_id = nss_dev->id;
293 }
294
295 if (npd->ipv6_enabled == NSS_FEATURE_ENABLED) {
296 nss_top->ipv6_handler_id = nss_dev->id;
297 }
298
299 if (npd->l2switch_enabled == NSS_FEATURE_ENABLED) {
300 nss_top->l2switch_handler_id = nss_dev->id;
301 }
302
303 if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
304 nss_top->crypto_handler_id = nss_dev->id;
305 }
306
307 if (npd->ipsec_enabled == NSS_FEATURE_ENABLED) {
308 nss_top->ipsec_handler_id = nss_dev->id;
309 }
310
311 if (npd->wlan_enabled == NSS_FEATURE_ENABLED) {
312 nss_top->wlan_handler_id = nss_dev->id;
313 }
314
315 if (npd->gmac_enabled[0] == NSS_FEATURE_ENABLED) {
316 nss_top->phys_if_handler_id[0] = nss_dev->id;
317 }
318
319 if (npd->gmac_enabled[1] == NSS_FEATURE_ENABLED) {
320 nss_top->phys_if_handler_id[1] = nss_dev->id;
321 }
322
323 if (npd->gmac_enabled[2] == NSS_FEATURE_ENABLED) {
324 nss_top->phys_if_handler_id[2] = nss_dev->id;
325 }
326
327 if (npd->gmac_enabled[3] == NSS_FEATURE_ENABLED) {
328 nss_top->phys_if_handler_id[3] = nss_dev->id;
329 }
330
331 spin_unlock_bh(&(nss_top->lock));
332
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530333 /*
334 * Initialize decongestion callbacks to NULL
335 */
336 for (i = 0; i< NSS_MAX_CLIENTS; i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530337 nss_ctx->queue_decongestion_callback[i] = 0;
338 nss_ctx->queue_decongestion_ctx[i] = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530339 }
340
341 spin_lock_init(&(nss_ctx->decongest_cb_lock));
342 nss_ctx->magic = NSS_CTX_MAGIC;
343
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530344 nss_info("%p: Reseting NSS core %d now", nss_ctx, nss_ctx->id);
345
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530346 /*
347 * Enable clocks and bring NSS core out of reset
348 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530349 nss_hal_core_reset(nss_dev->id, nss_ctx->nmap, nss_ctx->load, nss_top->clk_src);
350
351 /*
352 * Enable interrupts for NSS core
353 */
354 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
355 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
356
357 if (npd->num_irq > 1) {
358 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
359 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
360 }
361
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530362 nss_info("%p: All resources initialized and nss core%d has been brought out of reset", nss_ctx, nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530363 goto err_init_0;
364
365err_init_5:
366 unregister_netdev(nss_ctx->int_ctx[1].ndev);
367err_init_4:
368 free_netdev(nss_ctx->int_ctx[1].ndev);
369err_init_3:
370 free_irq(npd->irq[0], &nss_ctx->int_ctx[0]);
371err_init_2:
372 unregister_netdev(nss_ctx->int_ctx[0].ndev);
373err_init_1:
374 free_netdev(nss_ctx->int_ctx[0].ndev);
375err_init_0:
376 return err;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530377}
378
379/*
380 * nss_remove()
381 * HLOS device remove callback
382 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530383static int __devexit nss_remove(struct platform_device *nss_dev)
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530384{
385 struct nss_top_instance *nss_top = &nss_top_main;
386 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
387
388 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530389 * Clean-up debugfs
390 */
391 nss_stats_clean();
392
393 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530394 * Disable interrupts and bottom halves in HLOS
395 * Disable interrupts from NSS to HLOS
396 */
397 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
398 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530399
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530400 free_irq(nss_ctx->int_ctx[0].irq, &nss_ctx->int_ctx[0]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530401 unregister_netdev(nss_ctx->int_ctx[0].ndev);
402 free_netdev(nss_ctx->int_ctx[0].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530403
404 /*
405 * Check if second interrupt is supported
406 * If so then clear resources for second interrupt as well
407 */
408 if (nss_ctx->int_ctx[1].irq) {
409 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
410 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530411 free_irq(nss_ctx->int_ctx[1].irq, &nss_ctx->int_ctx[1]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530412 unregister_netdev(nss_ctx->int_ctx[1].ndev);
413 free_netdev(nss_ctx->int_ctx[1].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530414 }
415
416 nss_info("%p: All resources freed for nss core%d", nss_ctx, nss_dev->id);
417 return 0;
418}
419
420/*
421 * nss_driver
422 * Platform driver structure for NSS
423 */
424struct platform_driver nss_driver = {
425 .probe = nss_probe,
426 .remove = __devexit_p(nss_remove),
427 .driver = {
428 .name = "qca-nss",
429 .owner = THIS_MODULE,
430 },
431};
432
433/*
wthomas442c7972013-08-05 14:28:17 -0700434 * nss_current_freq_handler()
435 * Handle Userspace Frequency Change Requests
436 */
437static int nss_current_freq_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
438{
439 void *ubicom_na_nss_context = NULL;
440 int ret;
441 int vret;
442
443 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
444
445 if (write) {
446
447 ubicom_na_nss_context = nss_register_ipv4_mgr(NULL);
448
449 nss_info("Frequency Set to %d\n", nss_cmd_buf.current_freq);
450
451 /* If support NSS freq is in the table send the new frequency request to NSS */
452
453 if (nss_cmd_buf.current_freq == 110000000) {
454
455 nss_freq_change(ubicom_na_nss_context, 533000000, 0);
456 nss_hal_pvt_divide_pll(0, 11, 1);
457 nss_hal_pvt_enable_pll18(1100);
458 nss_freq_change(ubicom_na_nss_context, nss_cmd_buf.current_freq, 0);
459 nss_hal_pvt_divide_pll(0, 18, 5);
460
461 vret = regulator_set_voltage(nss0_vreg, NSS_NOM_VCC, NSS_NOM_VCC);
462 if (vret) {
463 nss_info("Regulator set voltage failed, err=%d\n", vret);
464 return ret;
465 }
466
467 } else if (nss_cmd_buf.current_freq == 225000000) {
468
469 nss_freq_change(ubicom_na_nss_context, 533000000, 0);
470 nss_hal_pvt_divide_pll(0, 11, 1);
471 nss_hal_pvt_enable_pll18(1100);
472 nss_freq_change(ubicom_na_nss_context, nss_cmd_buf.current_freq, 0);
473 nss_hal_pvt_divide_pll(0, 18, 2);
474
475 vret = regulator_set_voltage(nss0_vreg, NSS_NOM_VCC, NSS_NOM_VCC);
476 if (vret) {
477 nss_info("Regulator set voltage failed, err=%d\n", vret);
478 return ret;
479 }
480
481 } else if (nss_cmd_buf.current_freq == 550000000) {
482
483 nss_freq_change(ubicom_na_nss_context, 533000000, 0);
484 nss_hal_pvt_divide_pll(0, 11, 1);
485 nss_hal_pvt_enable_pll18(1100);
486 nss_freq_change(ubicom_na_nss_context, nss_cmd_buf.current_freq, 0);
487 nss_hal_pvt_divide_pll(0, 18, 1);
488
489 vret = regulator_set_voltage(nss0_vreg, NSS_NOM_VCC, NSS_NOM_VCC);
490 if (vret) {
491 nss_info("Regulator set voltage failed, err=%d\n", vret);
492 return ret;
493 }
494
495 } else if (nss_cmd_buf.current_freq == 733000000) {
496 vret = regulator_set_voltage(nss0_vreg, NSS_TURB_VCC, NSS_TURB_VCC);
497 if (vret) {
498 nss_info("Regulator set voltage failed, err=%d\n", vret);
499 return ret;
500 }
501
502 nss_freq_change(ubicom_na_nss_context, 533000000, 0);
503 nss_hal_pvt_divide_pll(0, 11, 1);
504 nss_hal_pvt_enable_pll18(1466);
505 nss_freq_change(ubicom_na_nss_context, nss_cmd_buf.current_freq, 0);
506 nss_hal_pvt_divide_pll(0, 18, 1);
507
508 } else {
509 nss_info("Frequency not found. Please check Frequency Table\n");
510 }
511 }
512 return ret;
513}
514
515/*
516 * nss_auto_scale_handler()
517 * Enables or Disable Auto Scaling
518 */
519static int nss_auto_scale_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
520{
521 int ret;
522
523 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
524
525 printk("Not Supported\n");
526
527 return ret;
528}
529
530/*
531 * nss_get_freq_table_handler()
532 * Display Support Freq and Ex how to Change.
533 */
534static int nss_get_freq_table_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
535{
536 int ret;
537
538 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
539
540 printk("Frequency Supported - 110Mhz 225Mhz 550Mhz 733Mhz \n");
541 printk("Ex. To Change Frequency - echo 110000000 > current_freq \n");
542
543 return ret;
544}
545
546/*
547 * sysctl-tuning infrastructure.
548 */
549static ctl_table nss_freq_table[] = {
550 {
551 .procname = "current_freq",
552 .data = &nss_cmd_buf.current_freq,
553 .maxlen = sizeof(int),
554 .mode = 0644,
555 .proc_handler = &nss_current_freq_handler,
556 },
557 {
558 .procname = "freq_table",
559 .data = &nss_cmd_buf.max_freq,
560 .maxlen = sizeof(int),
561 .mode = 0644,
562 .proc_handler = &nss_get_freq_table_handler,
563 },
564 {
565 .procname = "auto_scale",
566 .data = &nss_cmd_buf.auto_scale,
567 .maxlen = sizeof(int),
568 .mode = 0644,
569 .proc_handler = &nss_auto_scale_handler,
570 },
571 { }
572};
573
574static ctl_table nss_clock_dir[] = {
575 {
576 .procname = "clock",
577 .mode = 0555,
578 .child = nss_freq_table,
579 },
580 { }
581};
582
583static ctl_table nss_root_dir[] = {
584 {
585 .procname = "nss",
586 .mode = 0555,
587 .child = nss_clock_dir,
588 },
589 { }
590};
591
592static ctl_table nss_root[] = {
593 {
594 .procname = "dev",
595 .mode = 0555,
596 .child = nss_root_dir,
597 },
598 { }
599};
600
601static struct ctl_table_header *nss_dev_header;
602
603/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530604 * nss_init()
605 * Registers nss driver
606 */
607static int __init nss_init(void)
608{
609 nss_info("Init NSS driver");
610
611 /*
612 * Perform clock init common to all NSS cores
613 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530614 nss_hal_common_reset(&(nss_top_main.clk_src));
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530615
616 /*
617 * Enable spin locks
618 */
619 spin_lock_init(&(nss_top_main.lock));
620 spin_lock_init(&(nss_top_main.stats_lock));
621
622 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530623 * Enable NSS statistics
624 */
625 nss_stats_init();
626
627 /*
628 * Store load addresses
629 */
630 nss_top_main.nss[0].load = (uint32_t)load0;
631 nss_top_main.nss[1].load = (uint32_t)load1;
632
633 /*
wthomas442c7972013-08-05 14:28:17 -0700634 * Register sysctl table.
635 */
636 nss_dev_header = register_sysctl_table(nss_root);
637
638 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530639 * Register platform_driver
640 */
641 return platform_driver_register(&nss_driver);
642}
643
644/*
645 * nss_cleanup()
646 * Unregisters nss driver
647 */
648static void __exit nss_cleanup(void)
649{
650 nss_info("Exit NSS driver");
wthomas442c7972013-08-05 14:28:17 -0700651
652 if (nss_dev_header)
653 unregister_sysctl_table(nss_dev_header);
654
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530655 platform_driver_unregister(&nss_driver);
656}
657
658module_init(nss_init);
659module_exit(nss_cleanup);
660
661MODULE_DESCRIPTION("QCA NSS Driver");
662MODULE_AUTHOR("Qualcomm Atheros Inc");
663MODULE_LICENSE("Dual BSD/GPL");