blob: e280502eb0c6b3a05d26353f7c418a44e53e7e91 [file] [log] [blame]
Radhakrishna Jiguru1c9b2252013-08-27 23:57:48 +05301/*
2 **************************************************************************
Zac Livingston866b0e22013-10-23 18:14:17 -06003 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
Radhakrishna Jiguru1c9b2252013-08-27 23:57:48 +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 */
Abhishek Rastogibc74e432013-04-02 10:28:22 +053016
17/*
18 * nss_init.c
19 * NSS init APIs
20 *
21 */
Abhishek Rastogibc74e432013-04-02 10:28:22 +053022#include "nss_core.h"
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053023#include "nss_pm.h"
Abhishek Rastogi9da47472014-03-18 19:46:15 +053024#include "nss_tx_rx_common.h"
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053025
Abhishek Rastogibc74e432013-04-02 10:28:22 +053026#include <nss_hal.h>
Thomas Wufb6a6842013-10-23 13:14:27 -070027#include <nss_clocks.h>
Abhishek Rastogibc74e432013-04-02 10:28:22 +053028
29#include <linux/module.h>
30#include <linux/platform_device.h>
wthomas442c7972013-08-05 14:28:17 -070031#include <linux/proc_fs.h>
32#include <linux/device.h>
Abhishek Rastogibc74e432013-04-02 10:28:22 +053033#include <mach/msm_nss.h>
34
wthomas442c7972013-08-05 14:28:17 -070035#include <linux/sysctl.h>
36#include <linux/regulator/consumer.h>
Thomas Wufb6a6842013-10-23 13:14:27 -070037#include <linux/clk.h>
Thomas Wu49008962014-04-02 14:50:47 -070038#include <linux/firmware.h>
39
Saurabh Misra09dddeb2014-09-30 16:38:07 -070040#include "nss_capwap.h"
41
Thomas Wu49008962014-04-02 14:50:47 -070042/*
43 * Macros
44 */
45#define MIN_IMG_SIZE 64*1024
Radha krishna Simha Jiguru6e74d572014-05-13 11:30:20 +053046#define NETAP0_IMAGE "qca-nss0.bin"
47#define NETAP1_IMAGE "qca-nss1.bin"
wthomas442c7972013-08-05 14:28:17 -070048
Abhishek Rastogibc74e432013-04-02 10:28:22 +053049/*
50 * Global declarations
51 */
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +053052int nss_ctl_redirect __read_mostly = 0;
Sakthi Vignesh Radhakrishnanaf39aad2014-03-31 11:31:03 -070053int nss_ctl_debug __read_mostly = 0;
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053054int nss_rps_cfg __read_mostly = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +053055
56/*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053057 * PM client handle
58 */
59static void *pm_client;
60
61/*
wthomas626147f2013-09-18 13:12:40 -070062 * Handler to send NSS messages
63 */
64void *nss_freq_change_context;
Thomas Wufb6a6842013-10-23 13:14:27 -070065struct clk *nss_core0_clk;
wthomas626147f2013-09-18 13:12:40 -070066
67/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +053068 * Top level nss context structure
69 */
70struct nss_top_instance nss_top_main;
wthomas442c7972013-08-05 14:28:17 -070071struct nss_cmd_buffer nss_cmd_buf;
wthomas626147f2013-09-18 13:12:40 -070072struct nss_runtime_sampling nss_runtime_samples;
73struct workqueue_struct *nss_wq;
74
75/*
76 * Work Queue to handle messages to Kernel
77 */
78nss_work_t *nss_work;
Abhishek Rastogibc74e432013-04-02 10:28:22 +053079
80/*
81 * File local/Static variables/functions
82 */
83
Abhishek Rastogi271eee72013-07-29 21:08:36 +053084static const struct net_device_ops nss_netdev_ops;
85static const struct ethtool_ops nss_ethtool_ops;
86
87/*
88 * nss_dummy_netdev_setup()
89 * Dummy setup for net_device handler
90 */
91static void nss_dummy_netdev_setup(struct net_device *ndev)
92{
wthomas626147f2013-09-18 13:12:40 -070093
Abhishek Rastogi271eee72013-07-29 21:08:36 +053094}
95
Abhishek Rastogibc74e432013-04-02 10:28:22 +053096/*
97 * nss_handle_irq()
98 * HLOS interrupt handler for nss interrupts
99 */
100static irqreturn_t nss_handle_irq (int irq, void *ctx)
101{
102 struct int_ctx_instance *int_ctx = (struct int_ctx_instance *) ctx;
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530103 struct nss_ctx_instance *nss_ctx = int_ctx->nss_ctx;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530104
105 /*
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530106 * Mask interrupt until our bottom half re-enables it
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530107 */
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530108 nss_hal_disable_interrupt(nss_ctx->nmap, int_ctx->irq,
109 int_ctx->shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530110
111 /*
112 * Schedule tasklet to process interrupt cause
113 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530114 napi_schedule(&int_ctx->napi);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530115 return IRQ_HANDLED;
116}
117
118/*
119 * nss_probe()
120 * HLOS device probe callback
121 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530122static int __devinit nss_probe(struct platform_device *nss_dev)
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530123{
124 struct nss_top_instance *nss_top = &nss_top_main;
125 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
126 struct nss_platform_data *npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530127 struct netdev_priv_instance *ndev_priv;
128 int i, err = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530129
Thomas Wu49008962014-04-02 14:50:47 -0700130 const struct firmware *nss_fw = NULL;
131 int rc = -ENODEV;
132 void __iomem *load_mem;
133
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530134 nss_ctx->nss_top = nss_top;
135 nss_ctx->id = nss_dev->id;
136
wthomas442c7972013-08-05 14:28:17 -0700137 nss_info("%p: NSS_DEV_ID %s \n", nss_ctx, dev_name(&nss_dev->dev));
138
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530139 /*
140 * F/W load from NSS Driver
141 */
142 if (nss_dev->id == 0) {
143 rc = request_firmware(&nss_fw, NETAP0_IMAGE, &(nss_dev->dev));
144 } else if (nss_dev->id == 1) {
145 rc = request_firmware(&nss_fw, NETAP1_IMAGE, &(nss_dev->dev));
146 } else {
Samarjeet Banerjee7bce8c52014-05-02 15:32:13 +0530147 nss_warning("%p: Invalid nss dev: %d \n", nss_ctx, nss_dev->id);
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530148 }
149
150 /*
151 * Check if the file read is successful
152 */
153 if (rc) {
154 nss_warning("%p: request_firmware failed with err code: %d", nss_ctx, rc);
155 err = rc;
156 goto err_init_0;
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530157 }
158
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530159 if (nss_fw->size < MIN_IMG_SIZE) {
160 nss_warning("%p: nss firmware is truncated, size:%d", nss_ctx, nss_fw->size);
Thomas Wu49008962014-04-02 14:50:47 -0700161 }
162
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530163 load_mem = ioremap_nocache(npd->load_addr, nss_fw->size);
164 if (load_mem == NULL) {
165 nss_warning("%p: ioremap_nocache failed: %x", nss_ctx, npd->load_addr);
166 release_firmware(nss_fw);
Thomas Wu49008962014-04-02 14:50:47 -0700167 goto err_init_0;
Thomas Wu49008962014-04-02 14:50:47 -0700168 }
169
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530170 printk("nss_driver - fw of size %u bytes copied to load addr: %x\n", nss_fw->size, npd->load_addr);
171 memcpy_toio(load_mem, nss_fw->data, nss_fw->size);
172 release_firmware(nss_fw);
173 iounmap(load_mem);
174
wthomas442c7972013-08-05 14:28:17 -0700175 /*
176 * Both NSS cores controlled by same regulator, Hook only Once
177 */
178 if (!nss_dev->id) {
Thomas Wufb6a6842013-10-23 13:14:27 -0700179 nss_core0_clk = clk_get(&nss_dev->dev, "nss_core_clk");
180 if (IS_ERR(nss_core0_clk)) {
wthomas442c7972013-08-05 14:28:17 -0700181
Thomas Wufb6a6842013-10-23 13:14:27 -0700182 err = PTR_ERR(nss_core0_clk);
wthomas442c7972013-08-05 14:28:17 -0700183 nss_info("%p: Regulator %s get failed, err=%d\n", nss_ctx, dev_name(&nss_dev->dev), err);
184 return err;
185
wthomas442c7972013-08-05 14:28:17 -0700186 }
Thomas Wufb6a6842013-10-23 13:14:27 -0700187 clk_set_rate(nss_core0_clk, NSS_FREQ_550);
188 clk_prepare(nss_core0_clk);
189 clk_enable(nss_core0_clk);
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800190
191 /*
192 * Check if turbo is supported
193 */
194 if (npd->turbo_frequency) {
195 /*
196 * Turbo is supported
197 */
198 printk("nss_driver - Turbo Support %d\n", npd->turbo_frequency);
199 nss_runtime_samples.freq_scale_sup_max = NSS_MAX_CPU_SCALES;
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530200 nss_pm_set_turbo();
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800201 } else {
202 printk("nss_driver - Turbo No Support %d\n", npd->turbo_frequency);
203 nss_runtime_samples.freq_scale_sup_max = NSS_MAX_CPU_SCALES - 1;
204 }
wthomas442c7972013-08-05 14:28:17 -0700205 }
206
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530207 /*
Sakthi Vignesh Radhakrishnand923e342013-12-09 11:53:03 -0800208 * Get load address of NSS firmware
209 */
210 nss_info("%p: Setting NSS%d Firmware load address to %x\n", nss_ctx, nss_dev->id, npd->load_addr);
211 nss_top->nss[nss_dev->id].load = npd->load_addr;
212
213 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530214 * Get virtual and physical memory addresses for nss logical/hardware address maps
215 */
216
217 /*
218 * Virtual address of CSM space
219 */
220 nss_ctx->nmap = npd->nmap;
221 nss_assert(nss_ctx->nmap);
222
223 /*
224 * Physical address of CSM space
225 */
226 nss_ctx->nphys = npd->nphys;
227 nss_assert(nss_ctx->nphys);
228
229 /*
230 * Virtual address of logical registers space
231 */
232 nss_ctx->vmap = npd->vmap;
233 nss_assert(nss_ctx->vmap);
234
235 /*
236 * Physical address of logical registers space
237 */
238 nss_ctx->vphys = npd->vphys;
239 nss_assert(nss_ctx->vphys);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530240 nss_info("%d:ctx=%p, vphys=%x, vmap=%x, nphys=%x, nmap=%x",
241 nss_dev->id, nss_ctx, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
242
243 /*
244 * Register netdevice handlers
245 */
246 nss_ctx->int_ctx[0].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
247 "qca-nss-dev%d", nss_dummy_netdev_setup);
248 if (nss_ctx->int_ctx[0].ndev == NULL) {
249 nss_warning("%p: Could not allocate net_device #0", nss_ctx);
250 err = -ENOMEM;
251 goto err_init_0;
252 }
253
254 nss_ctx->int_ctx[0].ndev->netdev_ops = &nss_netdev_ops;
255 nss_ctx->int_ctx[0].ndev->ethtool_ops = &nss_ethtool_ops;
256 err = register_netdev(nss_ctx->int_ctx[0].ndev);
257 if (err) {
258 nss_warning("%p: Could not register net_device #0", nss_ctx);
259 goto err_init_1;
260 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530261
262 /*
263 * request for IRQs
264 *
265 * WARNING: CPU affinities should be set using OS supported methods
266 */
267 nss_ctx->int_ctx[0].nss_ctx = nss_ctx;
268 nss_ctx->int_ctx[0].shift_factor = 0;
269 nss_ctx->int_ctx[0].irq = npd->irq[0];
270 err = request_irq(npd->irq[0], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[0]);
271 if (err) {
272 nss_warning("%d: IRQ0 request failed", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530273 goto err_init_2;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530274 }
275
276 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530277 * Register NAPI for NSS core interrupt #0
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530278 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530279 ndev_priv = netdev_priv(nss_ctx->int_ctx[0].ndev);
280 ndev_priv->int_ctx = &nss_ctx->int_ctx[0];
281 netif_napi_add(nss_ctx->int_ctx[0].ndev, &nss_ctx->int_ctx[0].napi, nss_core_handle_napi, 64);
282 napi_enable(&nss_ctx->int_ctx[0].napi);
283 nss_ctx->int_ctx[0].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530284
285 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530286 * Check if second interrupt is supported on this nss core
287 */
288 if (npd->num_irq > 1) {
289 nss_info("%d: This NSS core supports two interrupts", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530290
291 /*
292 * Register netdevice handlers
293 */
294 nss_ctx->int_ctx[1].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
295 "qca-nss-dev%d", nss_dummy_netdev_setup);
296 if (nss_ctx->int_ctx[1].ndev == NULL) {
297 nss_warning("%p: Could not allocate net_device #1", nss_ctx);
298 err = -ENOMEM;
299 goto err_init_3;
300 }
301
302 nss_ctx->int_ctx[1].ndev->netdev_ops = &nss_netdev_ops;
303 nss_ctx->int_ctx[1].ndev->ethtool_ops = &nss_ethtool_ops;
304 err = register_netdev(nss_ctx->int_ctx[1].ndev);
305 if (err) {
306 nss_warning("%p: Could not register net_device #1", nss_ctx);
307 goto err_init_4;
308 }
309
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530310 nss_ctx->int_ctx[1].nss_ctx = nss_ctx;
311 nss_ctx->int_ctx[1].shift_factor = 15;
312 nss_ctx->int_ctx[1].irq = npd->irq[1];
313 err = request_irq(npd->irq[1], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[1]);
314 if (err) {
315 nss_warning("%d: IRQ1 request failed for nss", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530316 goto err_init_5;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530317 }
318
319 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530320 * Register NAPI for NSS core interrupt #1
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530321 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530322 ndev_priv = netdev_priv(nss_ctx->int_ctx[1].ndev);
323 ndev_priv->int_ctx = &nss_ctx->int_ctx[1];
324 netif_napi_add(nss_ctx->int_ctx[1].ndev, &nss_ctx->int_ctx[1].napi, nss_core_handle_napi, 64);
325 napi_enable(&nss_ctx->int_ctx[1].napi);
326 nss_ctx->int_ctx[1].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530327 }
328
329 spin_lock_bh(&(nss_top->lock));
330
331 /*
332 * Check functionalities are supported by this NSS core
333 */
Murat Sezgin7a705422014-01-30 16:09:22 -0800334 if (npd->shaping_enabled == NSS_FEATURE_ENABLED) {
335 nss_top->shaping_handler_id = nss_dev->id;
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530336 printk(KERN_INFO "%p: NSS Shaping is enabled, handler id: %u\n", __func__, nss_top->shaping_handler_id);
Murat Sezgin7a705422014-01-30 16:09:22 -0800337 }
338
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530339 if (npd->ipv4_enabled == NSS_FEATURE_ENABLED) {
340 nss_top->ipv4_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530341 nss_ipv4_register_handler();
342 nss_pppoe_register_handler();
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530343 nss_eth_rx_register_handler();
344 nss_n2h_register_handler();
Sol Kavy2783c072014-04-05 12:53:13 -0700345 nss_virt_if_register_handler();
Tushar Mathura3e03052014-04-07 20:17:28 +0530346 nss_lag_register_handler();
Ankit Dhanuka9b430252014-08-12 13:53:41 +0530347 nss_dynamic_interface_register_handler();
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700348 nss_top->capwap_handler_id = nss_dev->id;
349 nss_capwap_init();
Ankit Dhanuka9b430252014-08-12 13:53:41 +0530350
Sol Kavy4013e282014-04-06 15:57:00 -0700351 for (i = 0; i < NSS_MAX_VIRTUAL_INTERFACES; i++) {
352 nss_top->virt_if_handler_id[i] = nss_dev->id;
353 }
Ankit Dhanuka65935322014-10-08 19:20:47 +0530354
355 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR] = nss_dev->id;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530356 }
357
Selin Dag6d9b0c12014-11-04 18:27:21 -0800358 if (npd->ipv4_reasm_enabled == NSS_FEATURE_ENABLED) {
359 nss_top->ipv4_reasm_handler_id = nss_dev->id;
360 nss_ipv4_reasm_register_handler();
361 }
362
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530363 if (npd->ipv6_enabled == NSS_FEATURE_ENABLED) {
364 nss_top->ipv6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530365 nss_ipv6_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530366 }
367
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530368 if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
369 nss_top->crypto_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530370 nss_crypto_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530371 }
372
373 if (npd->ipsec_enabled == NSS_FEATURE_ENABLED) {
374 nss_top->ipsec_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530375 nss_ipsec_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530376 }
377
378 if (npd->wlan_enabled == NSS_FEATURE_ENABLED) {
379 nss_top->wlan_handler_id = nss_dev->id;
380 }
381
Bharath M Kumar0d87e912013-08-12 18:32:57 +0530382 if (npd->tun6rd_enabled == NSS_FEATURE_ENABLED) {
383 nss_top->tun6rd_handler_id = nss_dev->id;
384 }
385
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530386 if (npd->tunipip6_enabled == NSS_FEATURE_ENABLED) {
387 nss_top->tunipip6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530388 nss_tunipip6_register_handler();
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530389 }
390
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530391 if (npd->gre_redir_enabled == NSS_FEATURE_ENABLED) {
392 nss_top->gre_redir_handler_id = nss_dev->id;
393 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR] = nss_dev->id;
394 nss_gre_redir_register_handler();
Ankit Dhanuka2ae20a82014-08-25 18:04:00 +0530395 nss_sjack_register_handler();
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530396 }
397
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530398 if (npd->gmac_enabled[0] == NSS_FEATURE_ENABLED) {
399 nss_top->phys_if_handler_id[0] = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530400 nss_phys_if_register_handler(0);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530401 }
402
403 if (npd->gmac_enabled[1] == NSS_FEATURE_ENABLED) {
404 nss_top->phys_if_handler_id[1] = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530405 nss_phys_if_register_handler(1);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530406 }
407
408 if (npd->gmac_enabled[2] == NSS_FEATURE_ENABLED) {
409 nss_top->phys_if_handler_id[2] = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530410 nss_phys_if_register_handler(2);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530411 }
412
413 if (npd->gmac_enabled[3] == NSS_FEATURE_ENABLED) {
414 nss_top->phys_if_handler_id[3] = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530415 nss_phys_if_register_handler(3);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530416 }
417
Thomas Wu168ca262014-03-21 16:20:27 -0700418 nss_core_freq_register_handler();
419
wthomas626147f2013-09-18 13:12:40 -0700420 nss_top->frequency_handler_id = nss_dev->id;
421
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530422 spin_unlock_bh(&(nss_top->lock));
423
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530424 /*
425 * Initialize decongestion callbacks to NULL
426 */
427 for (i = 0; i< NSS_MAX_CLIENTS; i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530428 nss_ctx->queue_decongestion_callback[i] = 0;
429 nss_ctx->queue_decongestion_ctx[i] = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530430 }
431
432 spin_lock_init(&(nss_ctx->decongest_cb_lock));
433 nss_ctx->magic = NSS_CTX_MAGIC;
434
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530435 nss_info("%p: Reseting NSS core %d now", nss_ctx, nss_ctx->id);
436
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530437 /*
438 * Enable clocks and bring NSS core out of reset
439 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530440 nss_hal_core_reset(nss_dev->id, nss_ctx->nmap, nss_ctx->load, nss_top->clk_src);
441
442 /*
443 * Enable interrupts for NSS core
444 */
445 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
446 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
447
448 if (npd->num_irq > 1) {
449 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
450 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
451 }
452
Radhakrishna Jigurub7346cf2013-12-16 13:08:43 +0530453 /*
454 * Initialize max buffer size for NSS core
455 */
456 nss_ctx->max_buf_size = NSS_NBUF_PAYLOAD_SIZE;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530457 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 +0530458 goto err_init_0;
459
460err_init_5:
461 unregister_netdev(nss_ctx->int_ctx[1].ndev);
462err_init_4:
463 free_netdev(nss_ctx->int_ctx[1].ndev);
464err_init_3:
465 free_irq(npd->irq[0], &nss_ctx->int_ctx[0]);
466err_init_2:
467 unregister_netdev(nss_ctx->int_ctx[0].ndev);
468err_init_1:
469 free_netdev(nss_ctx->int_ctx[0].ndev);
470err_init_0:
471 return err;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530472}
473
474/*
475 * nss_remove()
476 * HLOS device remove callback
477 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530478static int __devexit nss_remove(struct platform_device *nss_dev)
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530479{
480 struct nss_top_instance *nss_top = &nss_top_main;
481 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
482
483 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530484 * Clean-up debugfs
485 */
486 nss_stats_clean();
487
488 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530489 * Disable interrupts and bottom halves in HLOS
490 * Disable interrupts from NSS to HLOS
491 */
492 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
493 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530494
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530495 free_irq(nss_ctx->int_ctx[0].irq, &nss_ctx->int_ctx[0]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530496 unregister_netdev(nss_ctx->int_ctx[0].ndev);
497 free_netdev(nss_ctx->int_ctx[0].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530498
499 /*
500 * Check if second interrupt is supported
501 * If so then clear resources for second interrupt as well
502 */
503 if (nss_ctx->int_ctx[1].irq) {
504 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
505 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530506 free_irq(nss_ctx->int_ctx[1].irq, &nss_ctx->int_ctx[1]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530507 unregister_netdev(nss_ctx->int_ctx[1].ndev);
508 free_netdev(nss_ctx->int_ctx[1].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530509 }
510
511 nss_info("%p: All resources freed for nss core%d", nss_ctx, nss_dev->id);
512 return 0;
513}
514
515/*
516 * nss_driver
517 * Platform driver structure for NSS
518 */
519struct platform_driver nss_driver = {
520 .probe = nss_probe,
521 .remove = __devexit_p(nss_remove),
522 .driver = {
523 .name = "qca-nss",
524 .owner = THIS_MODULE,
525 },
526};
527
528/*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530529 * nss_reset_frequency_stats_samples()
530 * Reset all frequency sampling state when auto scaling is turned off.
531 */
532static void nss_reset_frequency_stats_samples (void)
533{
534 nss_runtime_samples.buffer_index = 0;
535 nss_runtime_samples.sum = 0;
536 nss_runtime_samples.average = 0;
537 nss_runtime_samples.sample_count = 0;
538 nss_runtime_samples.message_rate_limit = 0;
539 nss_runtime_samples.freq_scale_rate_limit_up = 0;
540 nss_runtime_samples.freq_scale_rate_limit_down = 0;
541}
542
543/*
wthomas626147f2013-09-18 13:12:40 -0700544 ***************************************************************************************************
Thomas Wufb6a6842013-10-23 13:14:27 -0700545 * nss_wq_function() is used to queue up requests to change NSS frequencies.
546 * The function will take care of NSS notices and also control clock.
547 * The auto rate algorithmn will queue up requests or the procfs may also queue up these requests.
wthomas626147f2013-09-18 13:12:40 -0700548 ***************************************************************************************************
549 */
550
551/*
552 * nss_wq_function()
553 * Added to Handle BH requests to kernel
554 */
555void nss_wq_function (struct work_struct *work)
556{
557 nss_work_t *my_work = (nss_work_t *)work;
558
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530559 nss_freq_change(nss_freq_change_context, my_work->frequency, my_work->stats_enable, 0);
Thomas Wufb6a6842013-10-23 13:14:27 -0700560 clk_set_rate(nss_core0_clk, my_work->frequency);
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530561 nss_freq_change(nss_freq_change_context, my_work->frequency, my_work->stats_enable, 1);
wthomas626147f2013-09-18 13:12:40 -0700562
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530563 if(!pm_client) {
564 goto out;
565 }
566
567 if (my_work->frequency == NSS_FREQ_733) {
568 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_TURBO);
569 } else if ((my_work->frequency == NSS_FREQ_275) || (my_work->frequency == NSS_FREQ_550)) {
570 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_NOMINAL);
571 } else {
572 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_IDLE);
573 }
574out:
wthomas626147f2013-09-18 13:12:40 -0700575 kfree((void *)work);
576}
577
578/*
wthomas442c7972013-08-05 14:28:17 -0700579 * nss_current_freq_handler()
580 * Handle Userspace Frequency Change Requests
581 */
582static int nss_current_freq_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
583{
wthomas442c7972013-08-05 14:28:17 -0700584 int ret;
wthomas626147f2013-09-18 13:12:40 -0700585
586 BUG_ON(!nss_wq);
wthomas442c7972013-08-05 14:28:17 -0700587
588 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
589
wthomasd39fa822013-08-22 16:44:23 -0700590 if (!write) {
wthomas626147f2013-09-18 13:12:40 -0700591 printk("Frequency Set to %d\n", nss_cmd_buf.current_freq);
wthomasd39fa822013-08-22 16:44:23 -0700592 return ret;
wthomas442c7972013-08-05 14:28:17 -0700593 }
wthomasd39fa822013-08-22 16:44:23 -0700594
wthomas626147f2013-09-18 13:12:40 -0700595 /* Turn off Auto Scale */
596 nss_cmd_buf.auto_scale = 0;
597 nss_runtime_samples.freq_scale_ready = 0;
wthomasd39fa822013-08-22 16:44:23 -0700598
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800599 /* If support NSS freq is in the table send the new frequency request to NSS or If No Turbo and ask for turbo freq */
600 if (((nss_cmd_buf.current_freq != NSS_FREQ_110) && (nss_cmd_buf.current_freq != NSS_FREQ_275) && (nss_cmd_buf.current_freq != NSS_FREQ_550) && (nss_cmd_buf.current_freq != NSS_FREQ_733)) || ((nss_runtime_samples.freq_scale_sup_max != NSS_MAX_CPU_SCALES) && (nss_cmd_buf.current_freq == NSS_FREQ_733))) {
Thomas Wufb6a6842013-10-23 13:14:27 -0700601 printk("Frequency not found. Please check Frequency Table\n");
wthomas626147f2013-09-18 13:12:40 -0700602 return ret;
wthomasd39fa822013-08-22 16:44:23 -0700603 }
604
Thomas Wu7409bce2014-05-21 10:56:07 -0700605 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
wthomas626147f2013-09-18 13:12:40 -0700606 if (!nss_work) {
607 nss_info("NSS Freq WQ kmalloc fail");
608 return ret;
609 }
610 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
611 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530612 nss_work->stats_enable = 0;
613
614 /* Ensure we start with a fresh set of samples later */
615 nss_reset_frequency_stats_samples();
616
wthomas626147f2013-09-18 13:12:40 -0700617 queue_work(nss_wq, (struct work_struct *)nss_work);
618
wthomas442c7972013-08-05 14:28:17 -0700619 return ret;
620}
621
622/*
623 * nss_auto_scale_handler()
624 * Enables or Disable Auto Scaling
625 */
626static int nss_auto_scale_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
627{
628 int ret;
629
630 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
631
wthomas626147f2013-09-18 13:12:40 -0700632 if (!write) {
633 return ret;
634 }
635
Thomas Wufb6a6842013-10-23 13:14:27 -0700636 if (nss_cmd_buf.auto_scale != 1) {
wthomas626147f2013-09-18 13:12:40 -0700637 /*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530638 * Is auto scaling currently enabled? If so, send the command to
639 * disable stats reporting to NSS
wthomas626147f2013-09-18 13:12:40 -0700640 */
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530641 if (nss_runtime_samples.freq_scale_ready != 0) {
642 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
Thomas Wu7409bce2014-05-21 10:56:07 -0700643 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530644 if (!nss_work) {
645 nss_info("NSS Freq WQ kmalloc fail");
646 return ret;
647 }
648 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
649 nss_work->frequency = nss_cmd_buf.current_freq;
650 nss_work->stats_enable = 0;
651 queue_work(nss_wq, (struct work_struct *)nss_work);
652 nss_runtime_samples.freq_scale_ready = 0;
653
654 /*
655 * The current samples would be stale later when scaling is
656 * enabled again, hence reset them
657 */
658 nss_reset_frequency_stats_samples();
659 }
Thomas Wufb6a6842013-10-23 13:14:27 -0700660 return ret;
wthomas626147f2013-09-18 13:12:40 -0700661 }
wthomas442c7972013-08-05 14:28:17 -0700662
Thomas Wufb6a6842013-10-23 13:14:27 -0700663 /*
664 * Auto Scaling is already being done
665 */
666 if (nss_runtime_samples.freq_scale_ready == 1) {
667 return ret;
668 }
669
670 /*
671 * Setup default values - Middle of Freq Scale Band
672 */
673 nss_runtime_samples.freq_scale_index = 1;
674 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
675
Thomas Wu7409bce2014-05-21 10:56:07 -0700676 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Thomas Wufb6a6842013-10-23 13:14:27 -0700677 if (!nss_work) {
678 nss_info("NSS Freq WQ kmalloc fail");
679 return ret;
680 }
681 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
682 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530683 nss_work->stats_enable = 1;
Thomas Wufb6a6842013-10-23 13:14:27 -0700684 queue_work(nss_wq, (struct work_struct *)nss_work);
685
686 nss_runtime_samples.freq_scale_ready = 1;
687
wthomas442c7972013-08-05 14:28:17 -0700688 return ret;
689}
690
691/*
692 * nss_get_freq_table_handler()
693 * Display Support Freq and Ex how to Change.
694 */
Thomas Wu05495be2013-12-19 14:24:24 -0800695static int nss_get_freq_table_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
wthomas442c7972013-08-05 14:28:17 -0700696{
697 int ret;
698
699 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
700
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800701 if (nss_runtime_samples.freq_scale_sup_max != NSS_MAX_CPU_SCALES) {
702 printk("Frequency Supported - 110Mhz 275Mhz 550Mhz\n");
703 printk("Ex. To Change Frequency - echo 110000000 > current_freq \n");
704
705 return ret;
706 }
707
wthomas626147f2013-09-18 13:12:40 -0700708 printk("Frequency Supported - 110Mhz 275Mhz 550Mhz 733Mhz \n");
wthomas442c7972013-08-05 14:28:17 -0700709 printk("Ex. To Change Frequency - echo 110000000 > current_freq \n");
710
711 return ret;
712}
713
714/*
Thomas Wu05495be2013-12-19 14:24:24 -0800715 * nss_get_average_inst_handler()
716 * Display AVG Inst Per Ms.
717 */
718static int nss_get_average_inst_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
719{
720 int ret;
721
722 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
723
724 if (!ret && !write) {
725 printk("Current Inst Per Ms %x\n", nss_runtime_samples.average);
726 }
727
728 return ret;
729}
730
731/*
Abhishek Rastogi1626a902013-11-21 17:09:49 +0530732 * nss_debug_handler()
733 * Enable NSS debug output
734 */
735static int nss_debug_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
736{
737 int ret;
738
739 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
740 if (!ret) {
741 if ((write) && (nss_ctl_debug != 0)) {
742 printk("Enabling NSS SPI Debug\n");
743 nss_hal_debug_enable();
744 }
745 }
746
747 return ret;
748}
749
750/*
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530751 * nss_rps_handler()
752 * Enable NSS RPS
753 */
754static int nss_rpscfg_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
755{
756 struct nss_top_instance *nss_top = &nss_top_main;
757 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
758 int ret;
759
760 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
761 if (!ret) {
762 if ((write) && (nss_rps_cfg == 1)) {
763 printk("Enabling NSS RPS\n");
764 nss_n2h_rps_configure(nss_ctx, 1);
765 return ret;
766 }
767
768 if ((write) && (nss_rps_cfg == 0)) {
769 printk("Runtime disabling of NSS RPS not supported \n");
770 return ret;
771 }
772
773 if (write) {
774 printk("Invalid input value.Valid values are 0 and 1 \n");
775 }
776
777 }
778
779 return ret;
780}
781
782/*
Thomas Wu52075f42014-02-06 16:32:42 -0800783 * nss_coredump_handler()
784 * Send Signal To Coredump NSS Cores
785 */
786static int nss_coredump_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
787{
788 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *) nss_freq_change_context;
789 int ret;
790
791 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
792 if (!ret) {
793 if ((write) && (nss_ctl_debug != 0)) {
794 printk("Coredumping to DDR\n");
795 nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit, NSS_REGS_H2N_INTR_STATUS_COREDUMP_START);
796 }
797 }
798
799 return ret;
800}
801
802/*
wthomas442c7972013-08-05 14:28:17 -0700803 * sysctl-tuning infrastructure.
804 */
805static ctl_table nss_freq_table[] = {
806 {
807 .procname = "current_freq",
808 .data = &nss_cmd_buf.current_freq,
809 .maxlen = sizeof(int),
810 .mode = 0644,
811 .proc_handler = &nss_current_freq_handler,
812 },
813 {
814 .procname = "freq_table",
815 .data = &nss_cmd_buf.max_freq,
816 .maxlen = sizeof(int),
817 .mode = 0644,
818 .proc_handler = &nss_get_freq_table_handler,
819 },
820 {
821 .procname = "auto_scale",
822 .data = &nss_cmd_buf.auto_scale,
823 .maxlen = sizeof(int),
824 .mode = 0644,
825 .proc_handler = &nss_auto_scale_handler,
826 },
Thomas Wu05495be2013-12-19 14:24:24 -0800827 {
828 .procname = "inst_per_sec",
829 .data = &nss_cmd_buf.average_inst,
830 .maxlen = sizeof(int),
831 .mode = 0644,
832 .proc_handler = &nss_get_average_inst_handler,
833 },
wthomas442c7972013-08-05 14:28:17 -0700834 { }
835};
836
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530837static ctl_table nss_general_table[] = {
838 {
839 .procname = "redirect",
840 .data = &nss_ctl_redirect,
841 .maxlen = sizeof(int),
842 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700843 .proc_handler = proc_dointvec,
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530844 },
Abhishek Rastogi1626a902013-11-21 17:09:49 +0530845 {
846 .procname = "debug",
847 .data = &nss_ctl_debug,
848 .maxlen = sizeof(int),
849 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700850 .proc_handler = &nss_debug_handler,
Abhishek Rastogi1626a902013-11-21 17:09:49 +0530851 },
Thomas Wu52075f42014-02-06 16:32:42 -0800852 {
853 .procname = "coredump",
854 .data = &nss_cmd_buf.coredump,
855 .maxlen = sizeof(int),
856 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700857 .proc_handler = &nss_coredump_handler,
Thomas Wu52075f42014-02-06 16:32:42 -0800858 },
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530859 {
860 .procname = "rps",
861 .data = &nss_rps_cfg,
862 .maxlen = sizeof(int),
863 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700864 .proc_handler = &nss_rpscfg_handler,
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530865 },
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530866 { }
867};
868
wthomas442c7972013-08-05 14:28:17 -0700869static ctl_table nss_clock_dir[] = {
870 {
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530871 .procname = "clock",
872 .mode = 0555,
873 .child = nss_freq_table,
874 },
875 {
876 .procname = "general",
877 .mode = 0555,
878 .child = nss_general_table,
wthomas442c7972013-08-05 14:28:17 -0700879 },
880 { }
881};
882
883static ctl_table nss_root_dir[] = {
884 {
885 .procname = "nss",
886 .mode = 0555,
887 .child = nss_clock_dir,
888 },
889 { }
890};
891
892static ctl_table nss_root[] = {
893 {
894 .procname = "dev",
895 .mode = 0555,
896 .child = nss_root_dir,
897 },
898 { }
899};
900
901static struct ctl_table_header *nss_dev_header;
902
903/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530904 * nss_init()
905 * Registers nss driver
906 */
907static int __init nss_init(void)
908{
909 nss_info("Init NSS driver");
910
wthomas626147f2013-09-18 13:12:40 -0700911 nss_freq_change_context = nss_get_frequency_mgr();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530912 /*
913 * Perform clock init common to all NSS cores
914 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530915 nss_hal_common_reset(&(nss_top_main.clk_src));
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530916
917 /*
918 * Enable spin locks
919 */
920 spin_lock_init(&(nss_top_main.lock));
921 spin_lock_init(&(nss_top_main.stats_lock));
922
923 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530924 * Enable NSS statistics
925 */
926 nss_stats_init();
927
928 /*
wthomas442c7972013-08-05 14:28:17 -0700929 * Register sysctl table.
930 */
931 nss_dev_header = register_sysctl_table(nss_root);
932
933 /*
Vijay Dewangan9db18752014-09-15 16:25:01 -0700934 * Registering sysctl for ipv4/6 specific config.
935 */
936 nss_ipv4_register_sysctl();
937 nss_ipv6_register_sysctl();
938
939 /*
wthomas626147f2013-09-18 13:12:40 -0700940 * Setup Runtime Sample values
941 */
942 nss_runtime_samples.freq_scale[0].frequency = NSS_FREQ_110;
wthomas626147f2013-09-18 13:12:40 -0700943 nss_runtime_samples.freq_scale[0].minimum = NSS_FREQ_110_MIN;
944 nss_runtime_samples.freq_scale[0].maximum = NSS_FREQ_110_MAX;
wthomas626147f2013-09-18 13:12:40 -0700945 nss_runtime_samples.freq_scale[1].frequency = NSS_FREQ_550;
wthomas626147f2013-09-18 13:12:40 -0700946 nss_runtime_samples.freq_scale[1].minimum = NSS_FREQ_550_MIN;
947 nss_runtime_samples.freq_scale[1].maximum = NSS_FREQ_550_MAX;
wthomas626147f2013-09-18 13:12:40 -0700948 nss_runtime_samples.freq_scale[2].frequency = NSS_FREQ_733;
wthomas626147f2013-09-18 13:12:40 -0700949 nss_runtime_samples.freq_scale[2].minimum = NSS_FREQ_733_MIN;
950 nss_runtime_samples.freq_scale[2].maximum = NSS_FREQ_733_MAX;
wthomas626147f2013-09-18 13:12:40 -0700951 nss_runtime_samples.freq_scale_index = 1;
952 nss_runtime_samples.freq_scale_ready = 0;
Thomas Wu9681f7e2013-11-06 13:12:57 -0800953 nss_runtime_samples.freq_scale_rate_limit_up = 0;
954 nss_runtime_samples.freq_scale_rate_limit_down = 0;
wthomas626147f2013-09-18 13:12:40 -0700955 nss_runtime_samples.buffer_index = 0;
956 nss_runtime_samples.sum = 0;
957 nss_runtime_samples.sample_count = 0;
958 nss_runtime_samples.average = 0;
959 nss_runtime_samples.message_rate_limit = 0;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530960 nss_runtime_samples.initialized = 0;
wthomas626147f2013-09-18 13:12:40 -0700961
Thomas Wu05495be2013-12-19 14:24:24 -0800962 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
963
wthomas626147f2013-09-18 13:12:40 -0700964 /*
965 * Initial Workqueue
966 */
967 nss_wq = create_workqueue("nss_freq_queue");
968
969 /*
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530970 * Initialize NSS Bus PM module
971 */
972 nss_pm_init();
973
974 /*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530975 * Register with Bus driver
976 */
977 pm_client = nss_pm_client_register(NSS_PM_CLIENT_NETAP);
978 if (!pm_client) {
979 nss_warning("Error registering with PM driver");
980 }
981
982 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530983 * Register platform_driver
984 */
985 return platform_driver_register(&nss_driver);
986}
987
988/*
989 * nss_cleanup()
990 * Unregisters nss driver
991 */
992static void __exit nss_cleanup(void)
993{
994 nss_info("Exit NSS driver");
wthomas442c7972013-08-05 14:28:17 -0700995
996 if (nss_dev_header)
997 unregister_sysctl_table(nss_dev_header);
998
Vijay Dewangan9db18752014-09-15 16:25:01 -0700999 /*
1000 * Unregister ipv4/6 specific sysctl
1001 */
1002 nss_ipv4_unregister_sysctl();
1003 nss_ipv6_unregister_sysctl();
1004
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301005 platform_driver_unregister(&nss_driver);
1006}
1007
1008module_init(nss_init);
1009module_exit(nss_cleanup);
1010
1011MODULE_DESCRIPTION("QCA NSS Driver");
1012MODULE_AUTHOR("Qualcomm Atheros Inc");
1013MODULE_LICENSE("Dual BSD/GPL");