blob: 6cd17d32014baa15bd822d4d668c2a19c4c9168e [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;
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530108 struct nss_ctx_instance *nss_ctx = int_ctx->nss_ctx;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530109
110 /*
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530111 * Mask interrupt until our bottom half re-enables it
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530112 */
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530113 nss_hal_disable_interrupt(nss_ctx->nmap, int_ctx->irq,
114 int_ctx->shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530115
116 /*
117 * Schedule tasklet to process interrupt cause
118 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530119 napi_schedule(&int_ctx->napi);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530120 return IRQ_HANDLED;
121}
122
123/*
124 * nss_probe()
125 * HLOS device probe callback
126 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530127static int __devinit nss_probe(struct platform_device *nss_dev)
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530128{
129 struct nss_top_instance *nss_top = &nss_top_main;
130 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
131 struct nss_platform_data *npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530132 struct netdev_priv_instance *ndev_priv;
133 int i, err = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530134
135 nss_ctx->nss_top = nss_top;
136 nss_ctx->id = nss_dev->id;
137
wthomas442c7972013-08-05 14:28:17 -0700138 nss_info("%p: NSS_DEV_ID %s \n", nss_ctx, dev_name(&nss_dev->dev));
139
140 /*
141 * Both NSS cores controlled by same regulator, Hook only Once
142 */
143 if (!nss_dev->id) {
144 nss0_vreg = devm_regulator_get(&nss_dev->dev, "VDD_UBI0");
145
146 if (IS_ERR(nss0_vreg)) {
147
148 err = PTR_ERR(nss0_vreg);
149 nss_info("%p: Regulator %s get failed, err=%d\n", nss_ctx, dev_name(&nss_dev->dev), err);
150 return err;
151
152 } else {
153
154 nss_info("%p: Regulator %s get success\n", nss_ctx, dev_name(&nss_dev->dev));
155
156 err = regulator_enable(nss0_vreg);
157 if (err) {
158 nss_info("%p: Regulator %s enable voltage failed, err=%d\n", nss_ctx, dev_name(&nss_dev->dev), err);
159 return err;
160 }
161
162 err = regulator_set_voltage(nss0_vreg, NSS_NOM_VCC, NSS_NOM_VCC);
163 if (err) {
164 nss_info("%p: Regulator %s set voltage failed, err=%d\n", nss_ctx, dev_name(&nss_dev->dev), err);
165 return err;
166 }
167
168
169 }
170 }
171
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530172 /*
173 * Get virtual and physical memory addresses for nss logical/hardware address maps
174 */
175
176 /*
177 * Virtual address of CSM space
178 */
179 nss_ctx->nmap = npd->nmap;
180 nss_assert(nss_ctx->nmap);
181
182 /*
183 * Physical address of CSM space
184 */
185 nss_ctx->nphys = npd->nphys;
186 nss_assert(nss_ctx->nphys);
187
188 /*
189 * Virtual address of logical registers space
190 */
191 nss_ctx->vmap = npd->vmap;
192 nss_assert(nss_ctx->vmap);
193
194 /*
195 * Physical address of logical registers space
196 */
197 nss_ctx->vphys = npd->vphys;
198 nss_assert(nss_ctx->vphys);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530199 nss_info("%d:ctx=%p, vphys=%x, vmap=%x, nphys=%x, nmap=%x",
200 nss_dev->id, nss_ctx, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
201
202 /*
203 * Register netdevice handlers
204 */
205 nss_ctx->int_ctx[0].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
206 "qca-nss-dev%d", nss_dummy_netdev_setup);
207 if (nss_ctx->int_ctx[0].ndev == NULL) {
208 nss_warning("%p: Could not allocate net_device #0", nss_ctx);
209 err = -ENOMEM;
210 goto err_init_0;
211 }
212
213 nss_ctx->int_ctx[0].ndev->netdev_ops = &nss_netdev_ops;
214 nss_ctx->int_ctx[0].ndev->ethtool_ops = &nss_ethtool_ops;
215 err = register_netdev(nss_ctx->int_ctx[0].ndev);
216 if (err) {
217 nss_warning("%p: Could not register net_device #0", nss_ctx);
218 goto err_init_1;
219 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530220
221 /*
222 * request for IRQs
223 *
224 * WARNING: CPU affinities should be set using OS supported methods
225 */
226 nss_ctx->int_ctx[0].nss_ctx = nss_ctx;
227 nss_ctx->int_ctx[0].shift_factor = 0;
228 nss_ctx->int_ctx[0].irq = npd->irq[0];
229 err = request_irq(npd->irq[0], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[0]);
230 if (err) {
231 nss_warning("%d: IRQ0 request failed", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530232 goto err_init_2;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530233 }
234
235 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530236 * Register NAPI for NSS core interrupt #0
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530237 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530238 ndev_priv = netdev_priv(nss_ctx->int_ctx[0].ndev);
239 ndev_priv->int_ctx = &nss_ctx->int_ctx[0];
240 netif_napi_add(nss_ctx->int_ctx[0].ndev, &nss_ctx->int_ctx[0].napi, nss_core_handle_napi, 64);
241 napi_enable(&nss_ctx->int_ctx[0].napi);
242 nss_ctx->int_ctx[0].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530243
244 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530245 * Check if second interrupt is supported on this nss core
246 */
247 if (npd->num_irq > 1) {
248 nss_info("%d: This NSS core supports two interrupts", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530249
250 /*
251 * Register netdevice handlers
252 */
253 nss_ctx->int_ctx[1].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
254 "qca-nss-dev%d", nss_dummy_netdev_setup);
255 if (nss_ctx->int_ctx[1].ndev == NULL) {
256 nss_warning("%p: Could not allocate net_device #1", nss_ctx);
257 err = -ENOMEM;
258 goto err_init_3;
259 }
260
261 nss_ctx->int_ctx[1].ndev->netdev_ops = &nss_netdev_ops;
262 nss_ctx->int_ctx[1].ndev->ethtool_ops = &nss_ethtool_ops;
263 err = register_netdev(nss_ctx->int_ctx[1].ndev);
264 if (err) {
265 nss_warning("%p: Could not register net_device #1", nss_ctx);
266 goto err_init_4;
267 }
268
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530269 nss_ctx->int_ctx[1].nss_ctx = nss_ctx;
270 nss_ctx->int_ctx[1].shift_factor = 15;
271 nss_ctx->int_ctx[1].irq = npd->irq[1];
272 err = request_irq(npd->irq[1], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[1]);
273 if (err) {
274 nss_warning("%d: IRQ1 request failed for nss", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530275 goto err_init_5;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530276 }
277
278 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530279 * Register NAPI for NSS core interrupt #1
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530280 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530281 ndev_priv = netdev_priv(nss_ctx->int_ctx[1].ndev);
282 ndev_priv->int_ctx = &nss_ctx->int_ctx[1];
283 netif_napi_add(nss_ctx->int_ctx[1].ndev, &nss_ctx->int_ctx[1].napi, nss_core_handle_napi, 64);
284 napi_enable(&nss_ctx->int_ctx[1].napi);
285 nss_ctx->int_ctx[1].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530286 }
287
288 spin_lock_bh(&(nss_top->lock));
289
290 /*
291 * Check functionalities are supported by this NSS core
292 */
293 if (npd->ipv4_enabled == NSS_FEATURE_ENABLED) {
294 nss_top->ipv4_handler_id = nss_dev->id;
295 }
296
297 if (npd->ipv6_enabled == NSS_FEATURE_ENABLED) {
298 nss_top->ipv6_handler_id = nss_dev->id;
299 }
300
301 if (npd->l2switch_enabled == NSS_FEATURE_ENABLED) {
302 nss_top->l2switch_handler_id = nss_dev->id;
303 }
304
305 if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
306 nss_top->crypto_handler_id = nss_dev->id;
307 }
308
309 if (npd->ipsec_enabled == NSS_FEATURE_ENABLED) {
310 nss_top->ipsec_handler_id = nss_dev->id;
311 }
312
313 if (npd->wlan_enabled == NSS_FEATURE_ENABLED) {
314 nss_top->wlan_handler_id = nss_dev->id;
315 }
316
Bharath M Kumar0d87e912013-08-12 18:32:57 +0530317 if (npd->tun6rd_enabled == NSS_FEATURE_ENABLED) {
318 nss_top->tun6rd_handler_id = nss_dev->id;
319 }
320
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530321 if (npd->tunipip6_enabled == NSS_FEATURE_ENABLED) {
322 nss_top->tunipip6_handler_id = nss_dev->id;
323 }
324
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530325 if (npd->gmac_enabled[0] == NSS_FEATURE_ENABLED) {
326 nss_top->phys_if_handler_id[0] = nss_dev->id;
327 }
328
329 if (npd->gmac_enabled[1] == NSS_FEATURE_ENABLED) {
330 nss_top->phys_if_handler_id[1] = nss_dev->id;
331 }
332
333 if (npd->gmac_enabled[2] == NSS_FEATURE_ENABLED) {
334 nss_top->phys_if_handler_id[2] = nss_dev->id;
335 }
336
337 if (npd->gmac_enabled[3] == NSS_FEATURE_ENABLED) {
338 nss_top->phys_if_handler_id[3] = nss_dev->id;
339 }
340
341 spin_unlock_bh(&(nss_top->lock));
342
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530343 /*
344 * Initialize decongestion callbacks to NULL
345 */
346 for (i = 0; i< NSS_MAX_CLIENTS; i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530347 nss_ctx->queue_decongestion_callback[i] = 0;
348 nss_ctx->queue_decongestion_ctx[i] = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530349 }
350
351 spin_lock_init(&(nss_ctx->decongest_cb_lock));
352 nss_ctx->magic = NSS_CTX_MAGIC;
353
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530354 nss_info("%p: Reseting NSS core %d now", nss_ctx, nss_ctx->id);
355
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530356 /*
357 * Enable clocks and bring NSS core out of reset
358 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530359 nss_hal_core_reset(nss_dev->id, nss_ctx->nmap, nss_ctx->load, nss_top->clk_src);
360
361 /*
362 * Enable interrupts for NSS core
363 */
364 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
365 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
366
367 if (npd->num_irq > 1) {
368 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
369 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
370 }
371
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530372 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 +0530373 goto err_init_0;
374
375err_init_5:
376 unregister_netdev(nss_ctx->int_ctx[1].ndev);
377err_init_4:
378 free_netdev(nss_ctx->int_ctx[1].ndev);
379err_init_3:
380 free_irq(npd->irq[0], &nss_ctx->int_ctx[0]);
381err_init_2:
382 unregister_netdev(nss_ctx->int_ctx[0].ndev);
383err_init_1:
384 free_netdev(nss_ctx->int_ctx[0].ndev);
385err_init_0:
386 return err;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530387}
388
389/*
390 * nss_remove()
391 * HLOS device remove callback
392 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530393static int __devexit nss_remove(struct platform_device *nss_dev)
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530394{
395 struct nss_top_instance *nss_top = &nss_top_main;
396 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
397
398 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530399 * Clean-up debugfs
400 */
401 nss_stats_clean();
402
403 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530404 * Disable interrupts and bottom halves in HLOS
405 * Disable interrupts from NSS to HLOS
406 */
407 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
408 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530409
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530410 free_irq(nss_ctx->int_ctx[0].irq, &nss_ctx->int_ctx[0]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530411 unregister_netdev(nss_ctx->int_ctx[0].ndev);
412 free_netdev(nss_ctx->int_ctx[0].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530413
414 /*
415 * Check if second interrupt is supported
416 * If so then clear resources for second interrupt as well
417 */
418 if (nss_ctx->int_ctx[1].irq) {
419 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
420 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530421 free_irq(nss_ctx->int_ctx[1].irq, &nss_ctx->int_ctx[1]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530422 unregister_netdev(nss_ctx->int_ctx[1].ndev);
423 free_netdev(nss_ctx->int_ctx[1].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530424 }
425
426 nss_info("%p: All resources freed for nss core%d", nss_ctx, nss_dev->id);
427 return 0;
428}
429
430/*
431 * nss_driver
432 * Platform driver structure for NSS
433 */
434struct platform_driver nss_driver = {
435 .probe = nss_probe,
436 .remove = __devexit_p(nss_remove),
437 .driver = {
438 .name = "qca-nss",
439 .owner = THIS_MODULE,
440 },
441};
442
443/*
wthomas442c7972013-08-05 14:28:17 -0700444 * nss_current_freq_handler()
445 * Handle Userspace Frequency Change Requests
446 */
447static int nss_current_freq_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
448{
449 void *ubicom_na_nss_context = NULL;
450 int ret;
451 int vret;
452
453 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
454
wthomasd39fa822013-08-22 16:44:23 -0700455 if (!write) {
456 return ret;
wthomas442c7972013-08-05 14:28:17 -0700457 }
wthomasd39fa822013-08-22 16:44:23 -0700458
459 ubicom_na_nss_context = nss_register_ipv4_mgr(NULL);
460 nss_info("Frequency Set to %d\n", nss_cmd_buf.current_freq);
461
462 /* If support NSS freq is in the table send the new frequency request to NSS */
463
464 if (nss_cmd_buf.current_freq == 110000000) {
465
466 nss_freq_change(ubicom_na_nss_context, 533000000, 0);
467 nss_hal_pvt_pll_change(11);
468
469 nss_hal_pvt_enable_pll18(1100);
470 ret = nss_hal_pvt_divide_pll18(0, 5);
471 if (!ret) {
472 return 0;
473 }
474
475 nss_freq_change(ubicom_na_nss_context, nss_cmd_buf.current_freq, 0);
476 nss_hal_pvt_pll_change(18);
477
478 vret = regulator_set_voltage(nss0_vreg, NSS_NOM_VCC, NSS_NOM_VCC);
479 if (vret) {
480 nss_info("Regulator set voltage failed, err=%d\n", vret);
481 return ret;
482 }
483
484 } else if (nss_cmd_buf.current_freq == 275000000) {
485
486 nss_freq_change(ubicom_na_nss_context, 533000000, 0);
487 nss_hal_pvt_pll_change(11);
488
489 nss_hal_pvt_enable_pll18(1100);
490 ret = nss_hal_pvt_divide_pll18(0, 2);
491 if (!ret) {
492 return ret;
493 }
494
495 nss_freq_change(ubicom_na_nss_context, nss_cmd_buf.current_freq, 0);
496 nss_hal_pvt_pll_change(11);
497
498 vret = regulator_set_voltage(nss0_vreg, NSS_NOM_VCC, NSS_NOM_VCC);
499 if (vret) {
500 nss_info("Regulator set voltage failed, err=%d\n", vret);
501 return ret;
502 }
503
504 } else if (nss_cmd_buf.current_freq == 550000000) {
505
506 nss_freq_change(ubicom_na_nss_context, 533000000, 0);
507 nss_hal_pvt_pll_change(11);
508
509 nss_hal_pvt_enable_pll18(1100);
510 ret = nss_hal_pvt_divide_pll18(0, 1);
511 if (!ret) {
512 return ret;
513 }
514
515 nss_freq_change(ubicom_na_nss_context, nss_cmd_buf.current_freq, 0);
516 nss_hal_pvt_pll_change(18);
517
518 vret = regulator_set_voltage(nss0_vreg, NSS_NOM_VCC, NSS_NOM_VCC);
519 if (vret) {
520 nss_info("Regulator set voltage failed, err=%d\n", vret);
521 return ret;
522 }
523
524 } else if (nss_cmd_buf.current_freq == 733000000) {
525 vret = regulator_set_voltage(nss0_vreg, NSS_TURB_VCC, NSS_TURB_VCC);
526 if (vret) {
527 nss_info("Regulator set voltage failed, err=%d\n", vret);
528 return ret;
529 }
530
531 nss_freq_change(ubicom_na_nss_context, 533000000, 0);
532 nss_hal_pvt_pll_change(11);
533
534 nss_hal_pvt_enable_pll18(1466);
535 ret = nss_hal_pvt_divide_pll18(0, 1);
536 if (!ret) {
537 return ret;
538 }
539
540 nss_freq_change(ubicom_na_nss_context, nss_cmd_buf.current_freq, 0);
541 nss_hal_pvt_pll_change(18);
542
543 } else {
544 nss_info("Frequency not found. Please check Frequency Table\n");
545 }
546
wthomas442c7972013-08-05 14:28:17 -0700547 return ret;
548}
549
550/*
551 * nss_auto_scale_handler()
552 * Enables or Disable Auto Scaling
553 */
554static int nss_auto_scale_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
555{
556 int ret;
557
558 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
559
560 printk("Not Supported\n");
561
562 return ret;
563}
564
565/*
566 * nss_get_freq_table_handler()
567 * Display Support Freq and Ex how to Change.
568 */
569static int nss_get_freq_table_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
570{
571 int ret;
572
573 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
574
575 printk("Frequency Supported - 110Mhz 225Mhz 550Mhz 733Mhz \n");
576 printk("Ex. To Change Frequency - echo 110000000 > current_freq \n");
577
578 return ret;
579}
580
581/*
582 * sysctl-tuning infrastructure.
583 */
584static ctl_table nss_freq_table[] = {
585 {
586 .procname = "current_freq",
587 .data = &nss_cmd_buf.current_freq,
588 .maxlen = sizeof(int),
589 .mode = 0644,
590 .proc_handler = &nss_current_freq_handler,
591 },
592 {
593 .procname = "freq_table",
594 .data = &nss_cmd_buf.max_freq,
595 .maxlen = sizeof(int),
596 .mode = 0644,
597 .proc_handler = &nss_get_freq_table_handler,
598 },
599 {
600 .procname = "auto_scale",
601 .data = &nss_cmd_buf.auto_scale,
602 .maxlen = sizeof(int),
603 .mode = 0644,
604 .proc_handler = &nss_auto_scale_handler,
605 },
606 { }
607};
608
609static ctl_table nss_clock_dir[] = {
610 {
611 .procname = "clock",
612 .mode = 0555,
613 .child = nss_freq_table,
614 },
615 { }
616};
617
618static ctl_table nss_root_dir[] = {
619 {
620 .procname = "nss",
621 .mode = 0555,
622 .child = nss_clock_dir,
623 },
624 { }
625};
626
627static ctl_table nss_root[] = {
628 {
629 .procname = "dev",
630 .mode = 0555,
631 .child = nss_root_dir,
632 },
633 { }
634};
635
636static struct ctl_table_header *nss_dev_header;
637
638/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530639 * nss_init()
640 * Registers nss driver
641 */
642static int __init nss_init(void)
643{
644 nss_info("Init NSS driver");
645
646 /*
647 * Perform clock init common to all NSS cores
648 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530649 nss_hal_common_reset(&(nss_top_main.clk_src));
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530650
651 /*
652 * Enable spin locks
653 */
654 spin_lock_init(&(nss_top_main.lock));
655 spin_lock_init(&(nss_top_main.stats_lock));
656
657 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530658 * Enable NSS statistics
659 */
660 nss_stats_init();
661
662 /*
663 * Store load addresses
664 */
665 nss_top_main.nss[0].load = (uint32_t)load0;
666 nss_top_main.nss[1].load = (uint32_t)load1;
667
668 /*
wthomas442c7972013-08-05 14:28:17 -0700669 * Register sysctl table.
670 */
671 nss_dev_header = register_sysctl_table(nss_root);
672
673 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530674 * Register platform_driver
675 */
676 return platform_driver_register(&nss_driver);
677}
678
679/*
680 * nss_cleanup()
681 * Unregisters nss driver
682 */
683static void __exit nss_cleanup(void)
684{
685 nss_info("Exit NSS driver");
wthomas442c7972013-08-05 14:28:17 -0700686
687 if (nss_dev_header)
688 unregister_sysctl_table(nss_dev_header);
689
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530690 platform_driver_unregister(&nss_driver);
691}
692
693module_init(nss_init);
694module_exit(nss_cleanup);
695
696MODULE_DESCRIPTION("QCA NSS Driver");
697MODULE_AUTHOR("Qualcomm Atheros Inc");
698MODULE_LICENSE("Dual BSD/GPL");