blob: ad9236ed0a63fe37bbc99652987377115e778cd4 [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
40/*
41 * Macros
42 */
43#define MIN_IMG_SIZE 64*1024
Radha krishna Simha Jiguru6e74d572014-05-13 11:30:20 +053044#define NETAP0_IMAGE "qca-nss0.bin"
45#define NETAP1_IMAGE "qca-nss1.bin"
wthomas442c7972013-08-05 14:28:17 -070046
Abhishek Rastogibc74e432013-04-02 10:28:22 +053047/*
48 * Global declarations
49 */
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +053050int nss_ctl_redirect __read_mostly = 0;
Sakthi Vignesh Radhakrishnanaf39aad2014-03-31 11:31:03 -070051int nss_ctl_debug __read_mostly = 0;
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053052int nss_rps_cfg __read_mostly = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +053053
54/*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053055 * PM client handle
56 */
57static void *pm_client;
58
59/*
wthomas626147f2013-09-18 13:12:40 -070060 * Handler to send NSS messages
61 */
62void *nss_freq_change_context;
Thomas Wufb6a6842013-10-23 13:14:27 -070063struct clk *nss_core0_clk;
wthomas626147f2013-09-18 13:12:40 -070064
65/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +053066 * Top level nss context structure
67 */
68struct nss_top_instance nss_top_main;
wthomas442c7972013-08-05 14:28:17 -070069struct nss_cmd_buffer nss_cmd_buf;
wthomas626147f2013-09-18 13:12:40 -070070struct nss_runtime_sampling nss_runtime_samples;
71struct workqueue_struct *nss_wq;
72
73/*
74 * Work Queue to handle messages to Kernel
75 */
76nss_work_t *nss_work;
Abhishek Rastogibc74e432013-04-02 10:28:22 +053077
78/*
79 * File local/Static variables/functions
80 */
81
Abhishek Rastogi271eee72013-07-29 21:08:36 +053082static const struct net_device_ops nss_netdev_ops;
83static const struct ethtool_ops nss_ethtool_ops;
84
85/*
86 * nss_dummy_netdev_setup()
87 * Dummy setup for net_device handler
88 */
89static void nss_dummy_netdev_setup(struct net_device *ndev)
90{
wthomas626147f2013-09-18 13:12:40 -070091
Abhishek Rastogi271eee72013-07-29 21:08:36 +053092}
93
Abhishek Rastogibc74e432013-04-02 10:28:22 +053094/*
95 * nss_handle_irq()
96 * HLOS interrupt handler for nss interrupts
97 */
98static irqreturn_t nss_handle_irq (int irq, void *ctx)
99{
100 struct int_ctx_instance *int_ctx = (struct int_ctx_instance *) ctx;
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530101 struct nss_ctx_instance *nss_ctx = int_ctx->nss_ctx;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530102
103 /*
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530104 * Mask interrupt until our bottom half re-enables it
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530105 */
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530106 nss_hal_disable_interrupt(nss_ctx->nmap, int_ctx->irq,
107 int_ctx->shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530108
109 /*
110 * Schedule tasklet to process interrupt cause
111 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530112 napi_schedule(&int_ctx->napi);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530113 return IRQ_HANDLED;
114}
115
116/*
117 * nss_probe()
118 * HLOS device probe callback
119 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530120static int __devinit nss_probe(struct platform_device *nss_dev)
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530121{
122 struct nss_top_instance *nss_top = &nss_top_main;
123 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
124 struct nss_platform_data *npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530125 struct netdev_priv_instance *ndev_priv;
126 int i, err = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530127
Thomas Wu49008962014-04-02 14:50:47 -0700128 const struct firmware *nss_fw = NULL;
129 int rc = -ENODEV;
130 void __iomem *load_mem;
131
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530132 nss_ctx->nss_top = nss_top;
133 nss_ctx->id = nss_dev->id;
134
wthomas442c7972013-08-05 14:28:17 -0700135 nss_info("%p: NSS_DEV_ID %s \n", nss_ctx, dev_name(&nss_dev->dev));
136
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530137 /*
138 * F/W load from NSS Driver
139 */
140 if (nss_dev->id == 0) {
141 rc = request_firmware(&nss_fw, NETAP0_IMAGE, &(nss_dev->dev));
142 } else if (nss_dev->id == 1) {
143 rc = request_firmware(&nss_fw, NETAP1_IMAGE, &(nss_dev->dev));
144 } else {
Samarjeet Banerjee7bce8c52014-05-02 15:32:13 +0530145 nss_warning("%p: Invalid nss dev: %d \n", nss_ctx, nss_dev->id);
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530146 }
147
148 /*
149 * Check if the file read is successful
150 */
151 if (rc) {
152 nss_warning("%p: request_firmware failed with err code: %d", nss_ctx, rc);
153 err = rc;
154 goto err_init_0;
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530155 }
156
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530157 if (nss_fw->size < MIN_IMG_SIZE) {
158 nss_warning("%p: nss firmware is truncated, size:%d", nss_ctx, nss_fw->size);
Thomas Wu49008962014-04-02 14:50:47 -0700159 }
160
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530161 load_mem = ioremap_nocache(npd->load_addr, nss_fw->size);
162 if (load_mem == NULL) {
163 nss_warning("%p: ioremap_nocache failed: %x", nss_ctx, npd->load_addr);
164 release_firmware(nss_fw);
Thomas Wu49008962014-04-02 14:50:47 -0700165 goto err_init_0;
Thomas Wu49008962014-04-02 14:50:47 -0700166 }
167
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530168 printk("nss_driver - fw of size %u bytes copied to load addr: %x\n", nss_fw->size, npd->load_addr);
169 memcpy_toio(load_mem, nss_fw->data, nss_fw->size);
170 release_firmware(nss_fw);
171 iounmap(load_mem);
172
wthomas442c7972013-08-05 14:28:17 -0700173 /*
174 * Both NSS cores controlled by same regulator, Hook only Once
175 */
176 if (!nss_dev->id) {
Thomas Wufb6a6842013-10-23 13:14:27 -0700177 nss_core0_clk = clk_get(&nss_dev->dev, "nss_core_clk");
178 if (IS_ERR(nss_core0_clk)) {
wthomas442c7972013-08-05 14:28:17 -0700179
Thomas Wufb6a6842013-10-23 13:14:27 -0700180 err = PTR_ERR(nss_core0_clk);
wthomas442c7972013-08-05 14:28:17 -0700181 nss_info("%p: Regulator %s get failed, err=%d\n", nss_ctx, dev_name(&nss_dev->dev), err);
182 return err;
183
wthomas442c7972013-08-05 14:28:17 -0700184 }
Thomas Wufb6a6842013-10-23 13:14:27 -0700185 clk_set_rate(nss_core0_clk, NSS_FREQ_550);
186 clk_prepare(nss_core0_clk);
187 clk_enable(nss_core0_clk);
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800188
189 /*
190 * Check if turbo is supported
191 */
192 if (npd->turbo_frequency) {
193 /*
194 * Turbo is supported
195 */
196 printk("nss_driver - Turbo Support %d\n", npd->turbo_frequency);
197 nss_runtime_samples.freq_scale_sup_max = NSS_MAX_CPU_SCALES;
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530198 nss_pm_set_turbo();
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800199 } else {
200 printk("nss_driver - Turbo No Support %d\n", npd->turbo_frequency);
201 nss_runtime_samples.freq_scale_sup_max = NSS_MAX_CPU_SCALES - 1;
202 }
wthomas442c7972013-08-05 14:28:17 -0700203 }
204
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530205 /*
Sakthi Vignesh Radhakrishnand923e342013-12-09 11:53:03 -0800206 * Get load address of NSS firmware
207 */
208 nss_info("%p: Setting NSS%d Firmware load address to %x\n", nss_ctx, nss_dev->id, npd->load_addr);
209 nss_top->nss[nss_dev->id].load = npd->load_addr;
210
211 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530212 * Get virtual and physical memory addresses for nss logical/hardware address maps
213 */
214
215 /*
216 * Virtual address of CSM space
217 */
218 nss_ctx->nmap = npd->nmap;
219 nss_assert(nss_ctx->nmap);
220
221 /*
222 * Physical address of CSM space
223 */
224 nss_ctx->nphys = npd->nphys;
225 nss_assert(nss_ctx->nphys);
226
227 /*
228 * Virtual address of logical registers space
229 */
230 nss_ctx->vmap = npd->vmap;
231 nss_assert(nss_ctx->vmap);
232
233 /*
234 * Physical address of logical registers space
235 */
236 nss_ctx->vphys = npd->vphys;
237 nss_assert(nss_ctx->vphys);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530238 nss_info("%d:ctx=%p, vphys=%x, vmap=%x, nphys=%x, nmap=%x",
239 nss_dev->id, nss_ctx, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
240
241 /*
242 * Register netdevice handlers
243 */
244 nss_ctx->int_ctx[0].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
245 "qca-nss-dev%d", nss_dummy_netdev_setup);
246 if (nss_ctx->int_ctx[0].ndev == NULL) {
247 nss_warning("%p: Could not allocate net_device #0", nss_ctx);
248 err = -ENOMEM;
249 goto err_init_0;
250 }
251
252 nss_ctx->int_ctx[0].ndev->netdev_ops = &nss_netdev_ops;
253 nss_ctx->int_ctx[0].ndev->ethtool_ops = &nss_ethtool_ops;
254 err = register_netdev(nss_ctx->int_ctx[0].ndev);
255 if (err) {
256 nss_warning("%p: Could not register net_device #0", nss_ctx);
257 goto err_init_1;
258 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530259
260 /*
261 * request for IRQs
262 *
263 * WARNING: CPU affinities should be set using OS supported methods
264 */
265 nss_ctx->int_ctx[0].nss_ctx = nss_ctx;
266 nss_ctx->int_ctx[0].shift_factor = 0;
267 nss_ctx->int_ctx[0].irq = npd->irq[0];
268 err = request_irq(npd->irq[0], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[0]);
269 if (err) {
270 nss_warning("%d: IRQ0 request failed", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530271 goto err_init_2;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530272 }
273
274 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530275 * Register NAPI for NSS core interrupt #0
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530276 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530277 ndev_priv = netdev_priv(nss_ctx->int_ctx[0].ndev);
278 ndev_priv->int_ctx = &nss_ctx->int_ctx[0];
279 netif_napi_add(nss_ctx->int_ctx[0].ndev, &nss_ctx->int_ctx[0].napi, nss_core_handle_napi, 64);
280 napi_enable(&nss_ctx->int_ctx[0].napi);
281 nss_ctx->int_ctx[0].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530282
283 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530284 * Check if second interrupt is supported on this nss core
285 */
286 if (npd->num_irq > 1) {
287 nss_info("%d: This NSS core supports two interrupts", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530288
289 /*
290 * Register netdevice handlers
291 */
292 nss_ctx->int_ctx[1].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
293 "qca-nss-dev%d", nss_dummy_netdev_setup);
294 if (nss_ctx->int_ctx[1].ndev == NULL) {
295 nss_warning("%p: Could not allocate net_device #1", nss_ctx);
296 err = -ENOMEM;
297 goto err_init_3;
298 }
299
300 nss_ctx->int_ctx[1].ndev->netdev_ops = &nss_netdev_ops;
301 nss_ctx->int_ctx[1].ndev->ethtool_ops = &nss_ethtool_ops;
302 err = register_netdev(nss_ctx->int_ctx[1].ndev);
303 if (err) {
304 nss_warning("%p: Could not register net_device #1", nss_ctx);
305 goto err_init_4;
306 }
307
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530308 nss_ctx->int_ctx[1].nss_ctx = nss_ctx;
309 nss_ctx->int_ctx[1].shift_factor = 15;
310 nss_ctx->int_ctx[1].irq = npd->irq[1];
311 err = request_irq(npd->irq[1], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[1]);
312 if (err) {
313 nss_warning("%d: IRQ1 request failed for nss", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530314 goto err_init_5;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530315 }
316
317 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530318 * Register NAPI for NSS core interrupt #1
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530319 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530320 ndev_priv = netdev_priv(nss_ctx->int_ctx[1].ndev);
321 ndev_priv->int_ctx = &nss_ctx->int_ctx[1];
322 netif_napi_add(nss_ctx->int_ctx[1].ndev, &nss_ctx->int_ctx[1].napi, nss_core_handle_napi, 64);
323 napi_enable(&nss_ctx->int_ctx[1].napi);
324 nss_ctx->int_ctx[1].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530325 }
326
327 spin_lock_bh(&(nss_top->lock));
328
329 /*
330 * Check functionalities are supported by this NSS core
331 */
Murat Sezgin7a705422014-01-30 16:09:22 -0800332 if (npd->shaping_enabled == NSS_FEATURE_ENABLED) {
333 nss_top->shaping_handler_id = nss_dev->id;
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530334 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 -0800335 }
336
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530337 if (npd->ipv4_enabled == NSS_FEATURE_ENABLED) {
338 nss_top->ipv4_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530339 nss_ipv4_register_handler();
340 nss_pppoe_register_handler();
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530341 nss_eth_rx_register_handler();
342 nss_n2h_register_handler();
Sol Kavy2783c072014-04-05 12:53:13 -0700343 nss_virt_if_register_handler();
Tushar Mathura3e03052014-04-07 20:17:28 +0530344 nss_lag_register_handler();
Ankit Dhanuka9b430252014-08-12 13:53:41 +0530345 nss_dynamic_interface_register_handler();
346
Sol Kavy4013e282014-04-06 15:57:00 -0700347 for (i = 0; i < NSS_MAX_VIRTUAL_INTERFACES; i++) {
348 nss_top->virt_if_handler_id[i] = nss_dev->id;
349 }
Ankit Dhanuka65935322014-10-08 19:20:47 +0530350
351 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR] = nss_dev->id;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530352 }
353
354 if (npd->ipv6_enabled == NSS_FEATURE_ENABLED) {
355 nss_top->ipv6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530356 nss_ipv6_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530357 }
358
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530359 if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
360 nss_top->crypto_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530361 nss_crypto_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530362 }
363
364 if (npd->ipsec_enabled == NSS_FEATURE_ENABLED) {
365 nss_top->ipsec_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530366 nss_ipsec_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530367 }
368
369 if (npd->wlan_enabled == NSS_FEATURE_ENABLED) {
370 nss_top->wlan_handler_id = nss_dev->id;
371 }
372
Bharath M Kumar0d87e912013-08-12 18:32:57 +0530373 if (npd->tun6rd_enabled == NSS_FEATURE_ENABLED) {
374 nss_top->tun6rd_handler_id = nss_dev->id;
375 }
376
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530377 if (npd->tunipip6_enabled == NSS_FEATURE_ENABLED) {
378 nss_top->tunipip6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530379 nss_tunipip6_register_handler();
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530380 }
381
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530382 if (npd->gre_redir_enabled == NSS_FEATURE_ENABLED) {
383 nss_top->gre_redir_handler_id = nss_dev->id;
384 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR] = nss_dev->id;
385 nss_gre_redir_register_handler();
Ankit Dhanuka2ae20a82014-08-25 18:04:00 +0530386 nss_sjack_register_handler();
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530387 }
388
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530389 if (npd->gmac_enabled[0] == NSS_FEATURE_ENABLED) {
390 nss_top->phys_if_handler_id[0] = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530391 nss_phys_if_register_handler(0);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530392 }
393
394 if (npd->gmac_enabled[1] == NSS_FEATURE_ENABLED) {
395 nss_top->phys_if_handler_id[1] = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530396 nss_phys_if_register_handler(1);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530397 }
398
399 if (npd->gmac_enabled[2] == NSS_FEATURE_ENABLED) {
400 nss_top->phys_if_handler_id[2] = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530401 nss_phys_if_register_handler(2);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530402 }
403
404 if (npd->gmac_enabled[3] == NSS_FEATURE_ENABLED) {
405 nss_top->phys_if_handler_id[3] = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530406 nss_phys_if_register_handler(3);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530407 }
408
Thomas Wu168ca262014-03-21 16:20:27 -0700409 nss_core_freq_register_handler();
410
wthomas626147f2013-09-18 13:12:40 -0700411 nss_top->frequency_handler_id = nss_dev->id;
412
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530413 spin_unlock_bh(&(nss_top->lock));
414
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530415 /*
416 * Initialize decongestion callbacks to NULL
417 */
418 for (i = 0; i< NSS_MAX_CLIENTS; i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530419 nss_ctx->queue_decongestion_callback[i] = 0;
420 nss_ctx->queue_decongestion_ctx[i] = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530421 }
422
423 spin_lock_init(&(nss_ctx->decongest_cb_lock));
424 nss_ctx->magic = NSS_CTX_MAGIC;
425
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530426 nss_info("%p: Reseting NSS core %d now", nss_ctx, nss_ctx->id);
427
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530428 /*
429 * Enable clocks and bring NSS core out of reset
430 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530431 nss_hal_core_reset(nss_dev->id, nss_ctx->nmap, nss_ctx->load, nss_top->clk_src);
432
433 /*
434 * Enable interrupts for NSS core
435 */
436 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
437 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
438
439 if (npd->num_irq > 1) {
440 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
441 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
442 }
443
Radhakrishna Jigurub7346cf2013-12-16 13:08:43 +0530444 /*
445 * Initialize max buffer size for NSS core
446 */
447 nss_ctx->max_buf_size = NSS_NBUF_PAYLOAD_SIZE;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530448 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 +0530449 goto err_init_0;
450
451err_init_5:
452 unregister_netdev(nss_ctx->int_ctx[1].ndev);
453err_init_4:
454 free_netdev(nss_ctx->int_ctx[1].ndev);
455err_init_3:
456 free_irq(npd->irq[0], &nss_ctx->int_ctx[0]);
457err_init_2:
458 unregister_netdev(nss_ctx->int_ctx[0].ndev);
459err_init_1:
460 free_netdev(nss_ctx->int_ctx[0].ndev);
461err_init_0:
462 return err;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530463}
464
465/*
466 * nss_remove()
467 * HLOS device remove callback
468 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530469static int __devexit nss_remove(struct platform_device *nss_dev)
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530470{
471 struct nss_top_instance *nss_top = &nss_top_main;
472 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
473
474 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530475 * Clean-up debugfs
476 */
477 nss_stats_clean();
478
479 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530480 * Disable interrupts and bottom halves in HLOS
481 * Disable interrupts from NSS to HLOS
482 */
483 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
484 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530485
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530486 free_irq(nss_ctx->int_ctx[0].irq, &nss_ctx->int_ctx[0]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530487 unregister_netdev(nss_ctx->int_ctx[0].ndev);
488 free_netdev(nss_ctx->int_ctx[0].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530489
490 /*
491 * Check if second interrupt is supported
492 * If so then clear resources for second interrupt as well
493 */
494 if (nss_ctx->int_ctx[1].irq) {
495 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
496 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530497 free_irq(nss_ctx->int_ctx[1].irq, &nss_ctx->int_ctx[1]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530498 unregister_netdev(nss_ctx->int_ctx[1].ndev);
499 free_netdev(nss_ctx->int_ctx[1].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530500 }
501
502 nss_info("%p: All resources freed for nss core%d", nss_ctx, nss_dev->id);
503 return 0;
504}
505
506/*
507 * nss_driver
508 * Platform driver structure for NSS
509 */
510struct platform_driver nss_driver = {
511 .probe = nss_probe,
512 .remove = __devexit_p(nss_remove),
513 .driver = {
514 .name = "qca-nss",
515 .owner = THIS_MODULE,
516 },
517};
518
519/*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530520 * nss_reset_frequency_stats_samples()
521 * Reset all frequency sampling state when auto scaling is turned off.
522 */
523static void nss_reset_frequency_stats_samples (void)
524{
525 nss_runtime_samples.buffer_index = 0;
526 nss_runtime_samples.sum = 0;
527 nss_runtime_samples.average = 0;
528 nss_runtime_samples.sample_count = 0;
529 nss_runtime_samples.message_rate_limit = 0;
530 nss_runtime_samples.freq_scale_rate_limit_up = 0;
531 nss_runtime_samples.freq_scale_rate_limit_down = 0;
532}
533
534/*
wthomas626147f2013-09-18 13:12:40 -0700535 ***************************************************************************************************
Thomas Wufb6a6842013-10-23 13:14:27 -0700536 * nss_wq_function() is used to queue up requests to change NSS frequencies.
537 * The function will take care of NSS notices and also control clock.
538 * The auto rate algorithmn will queue up requests or the procfs may also queue up these requests.
wthomas626147f2013-09-18 13:12:40 -0700539 ***************************************************************************************************
540 */
541
542/*
543 * nss_wq_function()
544 * Added to Handle BH requests to kernel
545 */
546void nss_wq_function (struct work_struct *work)
547{
548 nss_work_t *my_work = (nss_work_t *)work;
549
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530550 nss_freq_change(nss_freq_change_context, my_work->frequency, my_work->stats_enable, 0);
Thomas Wufb6a6842013-10-23 13:14:27 -0700551 clk_set_rate(nss_core0_clk, my_work->frequency);
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530552 nss_freq_change(nss_freq_change_context, my_work->frequency, my_work->stats_enable, 1);
wthomas626147f2013-09-18 13:12:40 -0700553
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530554 if(!pm_client) {
555 goto out;
556 }
557
558 if (my_work->frequency == NSS_FREQ_733) {
559 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_TURBO);
560 } else if ((my_work->frequency == NSS_FREQ_275) || (my_work->frequency == NSS_FREQ_550)) {
561 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_NOMINAL);
562 } else {
563 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_IDLE);
564 }
565out:
wthomas626147f2013-09-18 13:12:40 -0700566 kfree((void *)work);
567}
568
569/*
wthomas442c7972013-08-05 14:28:17 -0700570 * nss_current_freq_handler()
571 * Handle Userspace Frequency Change Requests
572 */
573static int nss_current_freq_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
574{
wthomas442c7972013-08-05 14:28:17 -0700575 int ret;
wthomas626147f2013-09-18 13:12:40 -0700576
577 BUG_ON(!nss_wq);
wthomas442c7972013-08-05 14:28:17 -0700578
579 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
580
wthomasd39fa822013-08-22 16:44:23 -0700581 if (!write) {
wthomas626147f2013-09-18 13:12:40 -0700582 printk("Frequency Set to %d\n", nss_cmd_buf.current_freq);
wthomasd39fa822013-08-22 16:44:23 -0700583 return ret;
wthomas442c7972013-08-05 14:28:17 -0700584 }
wthomasd39fa822013-08-22 16:44:23 -0700585
wthomas626147f2013-09-18 13:12:40 -0700586 /* Turn off Auto Scale */
587 nss_cmd_buf.auto_scale = 0;
588 nss_runtime_samples.freq_scale_ready = 0;
wthomasd39fa822013-08-22 16:44:23 -0700589
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800590 /* If support NSS freq is in the table send the new frequency request to NSS or If No Turbo and ask for turbo freq */
591 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 -0700592 printk("Frequency not found. Please check Frequency Table\n");
wthomas626147f2013-09-18 13:12:40 -0700593 return ret;
wthomasd39fa822013-08-22 16:44:23 -0700594 }
595
Thomas Wu7409bce2014-05-21 10:56:07 -0700596 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
wthomas626147f2013-09-18 13:12:40 -0700597 if (!nss_work) {
598 nss_info("NSS Freq WQ kmalloc fail");
599 return ret;
600 }
601 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
602 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530603 nss_work->stats_enable = 0;
604
605 /* Ensure we start with a fresh set of samples later */
606 nss_reset_frequency_stats_samples();
607
wthomas626147f2013-09-18 13:12:40 -0700608 queue_work(nss_wq, (struct work_struct *)nss_work);
609
wthomas442c7972013-08-05 14:28:17 -0700610 return ret;
611}
612
613/*
614 * nss_auto_scale_handler()
615 * Enables or Disable Auto Scaling
616 */
617static int nss_auto_scale_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
618{
619 int ret;
620
621 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
622
wthomas626147f2013-09-18 13:12:40 -0700623 if (!write) {
624 return ret;
625 }
626
Thomas Wufb6a6842013-10-23 13:14:27 -0700627 if (nss_cmd_buf.auto_scale != 1) {
wthomas626147f2013-09-18 13:12:40 -0700628 /*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530629 * Is auto scaling currently enabled? If so, send the command to
630 * disable stats reporting to NSS
wthomas626147f2013-09-18 13:12:40 -0700631 */
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530632 if (nss_runtime_samples.freq_scale_ready != 0) {
633 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
Thomas Wu7409bce2014-05-21 10:56:07 -0700634 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530635 if (!nss_work) {
636 nss_info("NSS Freq WQ kmalloc fail");
637 return ret;
638 }
639 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
640 nss_work->frequency = nss_cmd_buf.current_freq;
641 nss_work->stats_enable = 0;
642 queue_work(nss_wq, (struct work_struct *)nss_work);
643 nss_runtime_samples.freq_scale_ready = 0;
644
645 /*
646 * The current samples would be stale later when scaling is
647 * enabled again, hence reset them
648 */
649 nss_reset_frequency_stats_samples();
650 }
Thomas Wufb6a6842013-10-23 13:14:27 -0700651 return ret;
wthomas626147f2013-09-18 13:12:40 -0700652 }
wthomas442c7972013-08-05 14:28:17 -0700653
Thomas Wufb6a6842013-10-23 13:14:27 -0700654 /*
655 * Auto Scaling is already being done
656 */
657 if (nss_runtime_samples.freq_scale_ready == 1) {
658 return ret;
659 }
660
661 /*
662 * Setup default values - Middle of Freq Scale Band
663 */
664 nss_runtime_samples.freq_scale_index = 1;
665 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
666
Thomas Wu7409bce2014-05-21 10:56:07 -0700667 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Thomas Wufb6a6842013-10-23 13:14:27 -0700668 if (!nss_work) {
669 nss_info("NSS Freq WQ kmalloc fail");
670 return ret;
671 }
672 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
673 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530674 nss_work->stats_enable = 1;
Thomas Wufb6a6842013-10-23 13:14:27 -0700675 queue_work(nss_wq, (struct work_struct *)nss_work);
676
677 nss_runtime_samples.freq_scale_ready = 1;
678
wthomas442c7972013-08-05 14:28:17 -0700679 return ret;
680}
681
682/*
683 * nss_get_freq_table_handler()
684 * Display Support Freq and Ex how to Change.
685 */
Thomas Wu05495be2013-12-19 14:24:24 -0800686static 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 -0700687{
688 int ret;
689
690 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
691
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800692 if (nss_runtime_samples.freq_scale_sup_max != NSS_MAX_CPU_SCALES) {
693 printk("Frequency Supported - 110Mhz 275Mhz 550Mhz\n");
694 printk("Ex. To Change Frequency - echo 110000000 > current_freq \n");
695
696 return ret;
697 }
698
wthomas626147f2013-09-18 13:12:40 -0700699 printk("Frequency Supported - 110Mhz 275Mhz 550Mhz 733Mhz \n");
wthomas442c7972013-08-05 14:28:17 -0700700 printk("Ex. To Change Frequency - echo 110000000 > current_freq \n");
701
702 return ret;
703}
704
705/*
Thomas Wu05495be2013-12-19 14:24:24 -0800706 * nss_get_average_inst_handler()
707 * Display AVG Inst Per Ms.
708 */
709static int nss_get_average_inst_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
710{
711 int ret;
712
713 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
714
715 if (!ret && !write) {
716 printk("Current Inst Per Ms %x\n", nss_runtime_samples.average);
717 }
718
719 return ret;
720}
721
722/*
Abhishek Rastogi1626a902013-11-21 17:09:49 +0530723 * nss_debug_handler()
724 * Enable NSS debug output
725 */
726static int nss_debug_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
727{
728 int ret;
729
730 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
731 if (!ret) {
732 if ((write) && (nss_ctl_debug != 0)) {
733 printk("Enabling NSS SPI Debug\n");
734 nss_hal_debug_enable();
735 }
736 }
737
738 return ret;
739}
740
741/*
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530742 * nss_rps_handler()
743 * Enable NSS RPS
744 */
745static int nss_rpscfg_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
746{
747 struct nss_top_instance *nss_top = &nss_top_main;
748 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
749 int ret;
750
751 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
752 if (!ret) {
753 if ((write) && (nss_rps_cfg == 1)) {
754 printk("Enabling NSS RPS\n");
755 nss_n2h_rps_configure(nss_ctx, 1);
756 return ret;
757 }
758
759 if ((write) && (nss_rps_cfg == 0)) {
760 printk("Runtime disabling of NSS RPS not supported \n");
761 return ret;
762 }
763
764 if (write) {
765 printk("Invalid input value.Valid values are 0 and 1 \n");
766 }
767
768 }
769
770 return ret;
771}
772
773/*
Thomas Wu52075f42014-02-06 16:32:42 -0800774 * nss_coredump_handler()
775 * Send Signal To Coredump NSS Cores
776 */
777static int nss_coredump_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
778{
779 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *) nss_freq_change_context;
780 int ret;
781
782 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
783 if (!ret) {
784 if ((write) && (nss_ctl_debug != 0)) {
785 printk("Coredumping to DDR\n");
786 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);
787 }
788 }
789
790 return ret;
791}
792
793/*
wthomas442c7972013-08-05 14:28:17 -0700794 * sysctl-tuning infrastructure.
795 */
796static ctl_table nss_freq_table[] = {
797 {
798 .procname = "current_freq",
799 .data = &nss_cmd_buf.current_freq,
800 .maxlen = sizeof(int),
801 .mode = 0644,
802 .proc_handler = &nss_current_freq_handler,
803 },
804 {
805 .procname = "freq_table",
806 .data = &nss_cmd_buf.max_freq,
807 .maxlen = sizeof(int),
808 .mode = 0644,
809 .proc_handler = &nss_get_freq_table_handler,
810 },
811 {
812 .procname = "auto_scale",
813 .data = &nss_cmd_buf.auto_scale,
814 .maxlen = sizeof(int),
815 .mode = 0644,
816 .proc_handler = &nss_auto_scale_handler,
817 },
Thomas Wu05495be2013-12-19 14:24:24 -0800818 {
819 .procname = "inst_per_sec",
820 .data = &nss_cmd_buf.average_inst,
821 .maxlen = sizeof(int),
822 .mode = 0644,
823 .proc_handler = &nss_get_average_inst_handler,
824 },
wthomas442c7972013-08-05 14:28:17 -0700825 { }
826};
827
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530828static ctl_table nss_general_table[] = {
829 {
830 .procname = "redirect",
831 .data = &nss_ctl_redirect,
832 .maxlen = sizeof(int),
833 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700834 .proc_handler = proc_dointvec,
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530835 },
Abhishek Rastogi1626a902013-11-21 17:09:49 +0530836 {
837 .procname = "debug",
838 .data = &nss_ctl_debug,
839 .maxlen = sizeof(int),
840 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700841 .proc_handler = &nss_debug_handler,
Abhishek Rastogi1626a902013-11-21 17:09:49 +0530842 },
Thomas Wu52075f42014-02-06 16:32:42 -0800843 {
844 .procname = "coredump",
845 .data = &nss_cmd_buf.coredump,
846 .maxlen = sizeof(int),
847 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700848 .proc_handler = &nss_coredump_handler,
Thomas Wu52075f42014-02-06 16:32:42 -0800849 },
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530850 {
851 .procname = "rps",
852 .data = &nss_rps_cfg,
853 .maxlen = sizeof(int),
854 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700855 .proc_handler = &nss_rpscfg_handler,
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530856 },
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530857 { }
858};
859
wthomas442c7972013-08-05 14:28:17 -0700860static ctl_table nss_clock_dir[] = {
861 {
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530862 .procname = "clock",
863 .mode = 0555,
864 .child = nss_freq_table,
865 },
866 {
867 .procname = "general",
868 .mode = 0555,
869 .child = nss_general_table,
wthomas442c7972013-08-05 14:28:17 -0700870 },
871 { }
872};
873
874static ctl_table nss_root_dir[] = {
875 {
876 .procname = "nss",
877 .mode = 0555,
878 .child = nss_clock_dir,
879 },
880 { }
881};
882
883static ctl_table nss_root[] = {
884 {
885 .procname = "dev",
886 .mode = 0555,
887 .child = nss_root_dir,
888 },
889 { }
890};
891
892static struct ctl_table_header *nss_dev_header;
893
894/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530895 * nss_init()
896 * Registers nss driver
897 */
898static int __init nss_init(void)
899{
900 nss_info("Init NSS driver");
901
wthomas626147f2013-09-18 13:12:40 -0700902 nss_freq_change_context = nss_get_frequency_mgr();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530903 /*
904 * Perform clock init common to all NSS cores
905 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530906 nss_hal_common_reset(&(nss_top_main.clk_src));
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530907
908 /*
909 * Enable spin locks
910 */
911 spin_lock_init(&(nss_top_main.lock));
912 spin_lock_init(&(nss_top_main.stats_lock));
913
914 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530915 * Enable NSS statistics
916 */
917 nss_stats_init();
918
919 /*
wthomas442c7972013-08-05 14:28:17 -0700920 * Register sysctl table.
921 */
922 nss_dev_header = register_sysctl_table(nss_root);
923
924 /*
Vijay Dewangan9db18752014-09-15 16:25:01 -0700925 * Registering sysctl for ipv4/6 specific config.
926 */
927 nss_ipv4_register_sysctl();
928 nss_ipv6_register_sysctl();
929
930 /*
wthomas626147f2013-09-18 13:12:40 -0700931 * Setup Runtime Sample values
932 */
933 nss_runtime_samples.freq_scale[0].frequency = NSS_FREQ_110;
wthomas626147f2013-09-18 13:12:40 -0700934 nss_runtime_samples.freq_scale[0].minimum = NSS_FREQ_110_MIN;
935 nss_runtime_samples.freq_scale[0].maximum = NSS_FREQ_110_MAX;
wthomas626147f2013-09-18 13:12:40 -0700936 nss_runtime_samples.freq_scale[1].frequency = NSS_FREQ_550;
wthomas626147f2013-09-18 13:12:40 -0700937 nss_runtime_samples.freq_scale[1].minimum = NSS_FREQ_550_MIN;
938 nss_runtime_samples.freq_scale[1].maximum = NSS_FREQ_550_MAX;
wthomas626147f2013-09-18 13:12:40 -0700939 nss_runtime_samples.freq_scale[2].frequency = NSS_FREQ_733;
wthomas626147f2013-09-18 13:12:40 -0700940 nss_runtime_samples.freq_scale[2].minimum = NSS_FREQ_733_MIN;
941 nss_runtime_samples.freq_scale[2].maximum = NSS_FREQ_733_MAX;
wthomas626147f2013-09-18 13:12:40 -0700942 nss_runtime_samples.freq_scale_index = 1;
943 nss_runtime_samples.freq_scale_ready = 0;
Thomas Wu9681f7e2013-11-06 13:12:57 -0800944 nss_runtime_samples.freq_scale_rate_limit_up = 0;
945 nss_runtime_samples.freq_scale_rate_limit_down = 0;
wthomas626147f2013-09-18 13:12:40 -0700946 nss_runtime_samples.buffer_index = 0;
947 nss_runtime_samples.sum = 0;
948 nss_runtime_samples.sample_count = 0;
949 nss_runtime_samples.average = 0;
950 nss_runtime_samples.message_rate_limit = 0;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530951 nss_runtime_samples.initialized = 0;
wthomas626147f2013-09-18 13:12:40 -0700952
Thomas Wu05495be2013-12-19 14:24:24 -0800953 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
954
wthomas626147f2013-09-18 13:12:40 -0700955 /*
956 * Initial Workqueue
957 */
958 nss_wq = create_workqueue("nss_freq_queue");
959
960 /*
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530961 * Initialize NSS Bus PM module
962 */
963 nss_pm_init();
964
965 /*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530966 * Register with Bus driver
967 */
968 pm_client = nss_pm_client_register(NSS_PM_CLIENT_NETAP);
969 if (!pm_client) {
970 nss_warning("Error registering with PM driver");
971 }
972
973 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530974 * Register platform_driver
975 */
976 return platform_driver_register(&nss_driver);
977}
978
979/*
980 * nss_cleanup()
981 * Unregisters nss driver
982 */
983static void __exit nss_cleanup(void)
984{
985 nss_info("Exit NSS driver");
wthomas442c7972013-08-05 14:28:17 -0700986
987 if (nss_dev_header)
988 unregister_sysctl_table(nss_dev_header);
989
Vijay Dewangan9db18752014-09-15 16:25:01 -0700990 /*
991 * Unregister ipv4/6 specific sysctl
992 */
993 nss_ipv4_unregister_sysctl();
994 nss_ipv6_unregister_sysctl();
995
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530996 platform_driver_unregister(&nss_driver);
997}
998
999module_init(nss_init);
1000module_exit(nss_cleanup);
1001
1002MODULE_DESCRIPTION("QCA NSS Driver");
1003MODULE_AUTHOR("Qualcomm Atheros Inc");
1004MODULE_LICENSE("Dual BSD/GPL");