blob: 31737691f8d31ed7037cb3287d6b3da55a05ea42 [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"
Stephen Wang38e89bc2014-11-06 11:34:45 -080025#include "nss_data_plane.h"
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053026
Abhishek Rastogibc74e432013-04-02 10:28:22 +053027#include <nss_hal.h>
Thomas Wufb6a6842013-10-23 13:14:27 -070028#include <nss_clocks.h>
Abhishek Rastogibc74e432013-04-02 10:28:22 +053029
30#include <linux/module.h>
31#include <linux/platform_device.h>
wthomas442c7972013-08-05 14:28:17 -070032#include <linux/proc_fs.h>
33#include <linux/device.h>
Abhishek Rastogibc74e432013-04-02 10:28:22 +053034#include <mach/msm_nss.h>
35
wthomas442c7972013-08-05 14:28:17 -070036#include <linux/sysctl.h>
37#include <linux/regulator/consumer.h>
Thomas Wufb6a6842013-10-23 13:14:27 -070038#include <linux/clk.h>
Thomas Wu49008962014-04-02 14:50:47 -070039#include <linux/firmware.h>
40
Saurabh Misra09dddeb2014-09-30 16:38:07 -070041#include "nss_capwap.h"
42
Thomas Wu49008962014-04-02 14:50:47 -070043/*
44 * Macros
45 */
46#define MIN_IMG_SIZE 64*1024
Radha krishna Simha Jiguru6e74d572014-05-13 11:30:20 +053047#define NETAP0_IMAGE "qca-nss0.bin"
48#define NETAP1_IMAGE "qca-nss1.bin"
wthomas442c7972013-08-05 14:28:17 -070049
Abhishek Rastogibc74e432013-04-02 10:28:22 +053050/*
51 * Global declarations
52 */
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +053053int nss_ctl_redirect __read_mostly = 0;
Sakthi Vignesh Radhakrishnanaf39aad2014-03-31 11:31:03 -070054int nss_ctl_debug __read_mostly = 0;
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053055int nss_rps_cfg __read_mostly = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +053056
57/*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053058 * PM client handle
59 */
60static void *pm_client;
61
62/*
wthomas626147f2013-09-18 13:12:40 -070063 * Handler to send NSS messages
64 */
65void *nss_freq_change_context;
Thomas Wufb6a6842013-10-23 13:14:27 -070066struct clk *nss_core0_clk;
wthomas626147f2013-09-18 13:12:40 -070067
68/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +053069 * Top level nss context structure
70 */
71struct nss_top_instance nss_top_main;
wthomas442c7972013-08-05 14:28:17 -070072struct nss_cmd_buffer nss_cmd_buf;
wthomas626147f2013-09-18 13:12:40 -070073struct nss_runtime_sampling nss_runtime_samples;
74struct workqueue_struct *nss_wq;
75
76/*
77 * Work Queue to handle messages to Kernel
78 */
79nss_work_t *nss_work;
Abhishek Rastogibc74e432013-04-02 10:28:22 +053080
81/*
82 * File local/Static variables/functions
83 */
84
Abhishek Rastogi271eee72013-07-29 21:08:36 +053085static const struct net_device_ops nss_netdev_ops;
86static const struct ethtool_ops nss_ethtool_ops;
87
88/*
89 * nss_dummy_netdev_setup()
90 * Dummy setup for net_device handler
91 */
92static void nss_dummy_netdev_setup(struct net_device *ndev)
93{
wthomas626147f2013-09-18 13:12:40 -070094
Abhishek Rastogi271eee72013-07-29 21:08:36 +053095}
96
Abhishek Rastogibc74e432013-04-02 10:28:22 +053097/*
98 * nss_handle_irq()
99 * HLOS interrupt handler for nss interrupts
100 */
101static irqreturn_t nss_handle_irq (int irq, void *ctx)
102{
103 struct int_ctx_instance *int_ctx = (struct int_ctx_instance *) ctx;
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530104 struct nss_ctx_instance *nss_ctx = int_ctx->nss_ctx;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530105
106 /*
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530107 * Mask interrupt until our bottom half re-enables it
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530108 */
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530109 nss_hal_disable_interrupt(nss_ctx->nmap, int_ctx->irq,
110 int_ctx->shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530111
112 /*
113 * Schedule tasklet to process interrupt cause
114 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530115 napi_schedule(&int_ctx->napi);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530116 return IRQ_HANDLED;
117}
118
119/*
120 * nss_probe()
121 * HLOS device probe callback
122 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530123static int __devinit nss_probe(struct platform_device *nss_dev)
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530124{
125 struct nss_top_instance *nss_top = &nss_top_main;
126 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
127 struct nss_platform_data *npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530128 struct netdev_priv_instance *ndev_priv;
129 int i, err = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530130
Thomas Wu49008962014-04-02 14:50:47 -0700131 const struct firmware *nss_fw = NULL;
132 int rc = -ENODEV;
133 void __iomem *load_mem;
134
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530135 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
Stephen Wang38e89bc2014-11-06 11:34:45 -0800140 /*
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530141 * F/W load from NSS Driver
142 */
143 if (nss_dev->id == 0) {
144 rc = request_firmware(&nss_fw, NETAP0_IMAGE, &(nss_dev->dev));
145 } else if (nss_dev->id == 1) {
146 rc = request_firmware(&nss_fw, NETAP1_IMAGE, &(nss_dev->dev));
147 } else {
Samarjeet Banerjee7bce8c52014-05-02 15:32:13 +0530148 nss_warning("%p: Invalid nss dev: %d \n", nss_ctx, nss_dev->id);
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530149 }
150
151 /*
152 * Check if the file read is successful
153 */
154 if (rc) {
155 nss_warning("%p: request_firmware failed with err code: %d", nss_ctx, rc);
156 err = rc;
157 goto err_init_0;
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530158 }
159
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530160 if (nss_fw->size < MIN_IMG_SIZE) {
161 nss_warning("%p: nss firmware is truncated, size:%d", nss_ctx, nss_fw->size);
Thomas Wu49008962014-04-02 14:50:47 -0700162 }
163
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530164 load_mem = ioremap_nocache(npd->load_addr, nss_fw->size);
165 if (load_mem == NULL) {
166 nss_warning("%p: ioremap_nocache failed: %x", nss_ctx, npd->load_addr);
167 release_firmware(nss_fw);
Thomas Wu49008962014-04-02 14:50:47 -0700168 goto err_init_0;
Thomas Wu49008962014-04-02 14:50:47 -0700169 }
170
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530171 printk("nss_driver - fw of size %u bytes copied to load addr: %x\n", nss_fw->size, npd->load_addr);
172 memcpy_toio(load_mem, nss_fw->data, nss_fw->size);
173 release_firmware(nss_fw);
174 iounmap(load_mem);
175
wthomas442c7972013-08-05 14:28:17 -0700176 /*
177 * Both NSS cores controlled by same regulator, Hook only Once
178 */
179 if (!nss_dev->id) {
Thomas Wufb6a6842013-10-23 13:14:27 -0700180 nss_core0_clk = clk_get(&nss_dev->dev, "nss_core_clk");
181 if (IS_ERR(nss_core0_clk)) {
wthomas442c7972013-08-05 14:28:17 -0700182
Thomas Wufb6a6842013-10-23 13:14:27 -0700183 err = PTR_ERR(nss_core0_clk);
wthomas442c7972013-08-05 14:28:17 -0700184 nss_info("%p: Regulator %s get failed, err=%d\n", nss_ctx, dev_name(&nss_dev->dev), err);
185 return err;
186
wthomas442c7972013-08-05 14:28:17 -0700187 }
Thomas Wufb6a6842013-10-23 13:14:27 -0700188 clk_set_rate(nss_core0_clk, NSS_FREQ_550);
189 clk_prepare(nss_core0_clk);
190 clk_enable(nss_core0_clk);
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800191
192 /*
193 * Check if turbo is supported
194 */
195 if (npd->turbo_frequency) {
196 /*
197 * Turbo is supported
198 */
199 printk("nss_driver - Turbo Support %d\n", npd->turbo_frequency);
200 nss_runtime_samples.freq_scale_sup_max = NSS_MAX_CPU_SCALES;
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530201 nss_pm_set_turbo();
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800202 } else {
203 printk("nss_driver - Turbo No Support %d\n", npd->turbo_frequency);
204 nss_runtime_samples.freq_scale_sup_max = NSS_MAX_CPU_SCALES - 1;
205 }
wthomas442c7972013-08-05 14:28:17 -0700206 }
207
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530208 /*
Sakthi Vignesh Radhakrishnand923e342013-12-09 11:53:03 -0800209 * Get load address of NSS firmware
210 */
211 nss_info("%p: Setting NSS%d Firmware load address to %x\n", nss_ctx, nss_dev->id, npd->load_addr);
212 nss_top->nss[nss_dev->id].load = npd->load_addr;
213
214 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530215 * Get virtual and physical memory addresses for nss logical/hardware address maps
216 */
217
218 /*
219 * Virtual address of CSM space
220 */
221 nss_ctx->nmap = npd->nmap;
222 nss_assert(nss_ctx->nmap);
223
224 /*
225 * Physical address of CSM space
226 */
227 nss_ctx->nphys = npd->nphys;
228 nss_assert(nss_ctx->nphys);
229
230 /*
231 * Virtual address of logical registers space
232 */
233 nss_ctx->vmap = npd->vmap;
234 nss_assert(nss_ctx->vmap);
235
236 /*
237 * Physical address of logical registers space
238 */
239 nss_ctx->vphys = npd->vphys;
240 nss_assert(nss_ctx->vphys);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530241 nss_info("%d:ctx=%p, vphys=%x, vmap=%x, nphys=%x, nmap=%x",
242 nss_dev->id, nss_ctx, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
243
244 /*
245 * Register netdevice handlers
246 */
247 nss_ctx->int_ctx[0].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
248 "qca-nss-dev%d", nss_dummy_netdev_setup);
249 if (nss_ctx->int_ctx[0].ndev == NULL) {
250 nss_warning("%p: Could not allocate net_device #0", nss_ctx);
251 err = -ENOMEM;
252 goto err_init_0;
253 }
254
255 nss_ctx->int_ctx[0].ndev->netdev_ops = &nss_netdev_ops;
256 nss_ctx->int_ctx[0].ndev->ethtool_ops = &nss_ethtool_ops;
257 err = register_netdev(nss_ctx->int_ctx[0].ndev);
258 if (err) {
259 nss_warning("%p: Could not register net_device #0", nss_ctx);
260 goto err_init_1;
261 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530262
263 /*
264 * request for IRQs
265 *
266 * WARNING: CPU affinities should be set using OS supported methods
267 */
268 nss_ctx->int_ctx[0].nss_ctx = nss_ctx;
269 nss_ctx->int_ctx[0].shift_factor = 0;
270 nss_ctx->int_ctx[0].irq = npd->irq[0];
271 err = request_irq(npd->irq[0], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[0]);
272 if (err) {
273 nss_warning("%d: IRQ0 request failed", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530274 goto err_init_2;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530275 }
276
277 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530278 * Register NAPI for NSS core interrupt #0
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530279 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530280 ndev_priv = netdev_priv(nss_ctx->int_ctx[0].ndev);
281 ndev_priv->int_ctx = &nss_ctx->int_ctx[0];
282 netif_napi_add(nss_ctx->int_ctx[0].ndev, &nss_ctx->int_ctx[0].napi, nss_core_handle_napi, 64);
283 napi_enable(&nss_ctx->int_ctx[0].napi);
284 nss_ctx->int_ctx[0].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530285
286 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530287 * Check if second interrupt is supported on this nss core
288 */
289 if (npd->num_irq > 1) {
290 nss_info("%d: This NSS core supports two interrupts", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530291
292 /*
293 * Register netdevice handlers
294 */
295 nss_ctx->int_ctx[1].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
296 "qca-nss-dev%d", nss_dummy_netdev_setup);
297 if (nss_ctx->int_ctx[1].ndev == NULL) {
298 nss_warning("%p: Could not allocate net_device #1", nss_ctx);
299 err = -ENOMEM;
300 goto err_init_3;
301 }
302
303 nss_ctx->int_ctx[1].ndev->netdev_ops = &nss_netdev_ops;
304 nss_ctx->int_ctx[1].ndev->ethtool_ops = &nss_ethtool_ops;
305 err = register_netdev(nss_ctx->int_ctx[1].ndev);
306 if (err) {
307 nss_warning("%p: Could not register net_device #1", nss_ctx);
308 goto err_init_4;
309 }
310
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530311 nss_ctx->int_ctx[1].nss_ctx = nss_ctx;
312 nss_ctx->int_ctx[1].shift_factor = 15;
313 nss_ctx->int_ctx[1].irq = npd->irq[1];
314 err = request_irq(npd->irq[1], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[1]);
315 if (err) {
316 nss_warning("%d: IRQ1 request failed for nss", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530317 goto err_init_5;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530318 }
319
320 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530321 * Register NAPI for NSS core interrupt #1
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530322 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530323 ndev_priv = netdev_priv(nss_ctx->int_ctx[1].ndev);
324 ndev_priv->int_ctx = &nss_ctx->int_ctx[1];
325 netif_napi_add(nss_ctx->int_ctx[1].ndev, &nss_ctx->int_ctx[1].napi, nss_core_handle_napi, 64);
326 napi_enable(&nss_ctx->int_ctx[1].napi);
327 nss_ctx->int_ctx[1].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530328 }
329
330 spin_lock_bh(&(nss_top->lock));
331
332 /*
333 * Check functionalities are supported by this NSS core
334 */
Murat Sezgin7a705422014-01-30 16:09:22 -0800335 if (npd->shaping_enabled == NSS_FEATURE_ENABLED) {
336 nss_top->shaping_handler_id = nss_dev->id;
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530337 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 -0800338 }
339
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530340 if (npd->ipv4_enabled == NSS_FEATURE_ENABLED) {
341 nss_top->ipv4_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530342 nss_ipv4_register_handler();
343 nss_pppoe_register_handler();
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530344 nss_eth_rx_register_handler();
345 nss_n2h_register_handler();
Sol Kavy2783c072014-04-05 12:53:13 -0700346 nss_virt_if_register_handler();
Tushar Mathura3e03052014-04-07 20:17:28 +0530347 nss_lag_register_handler();
Ankit Dhanuka9b430252014-08-12 13:53:41 +0530348 nss_dynamic_interface_register_handler();
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700349 nss_top->capwap_handler_id = nss_dev->id;
350 nss_capwap_init();
Ankit Dhanuka9b430252014-08-12 13:53:41 +0530351
Sol Kavy4013e282014-04-06 15:57:00 -0700352 for (i = 0; i < NSS_MAX_VIRTUAL_INTERFACES; i++) {
353 nss_top->virt_if_handler_id[i] = nss_dev->id;
354 }
Ankit Dhanuka65935322014-10-08 19:20:47 +0530355
356 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR] = nss_dev->id;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530357 }
358
Selin Dag6d9b0c12014-11-04 18:27:21 -0800359 if (npd->ipv4_reasm_enabled == NSS_FEATURE_ENABLED) {
360 nss_top->ipv4_reasm_handler_id = nss_dev->id;
361 nss_ipv4_reasm_register_handler();
362 }
363
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530364 if (npd->ipv6_enabled == NSS_FEATURE_ENABLED) {
365 nss_top->ipv6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530366 nss_ipv6_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530367 }
368
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530369 if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
370 nss_top->crypto_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530371 nss_crypto_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530372 }
373
374 if (npd->ipsec_enabled == NSS_FEATURE_ENABLED) {
375 nss_top->ipsec_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530376 nss_ipsec_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530377 }
378
379 if (npd->wlan_enabled == NSS_FEATURE_ENABLED) {
380 nss_top->wlan_handler_id = nss_dev->id;
381 }
382
Bharath M Kumar0d87e912013-08-12 18:32:57 +0530383 if (npd->tun6rd_enabled == NSS_FEATURE_ENABLED) {
384 nss_top->tun6rd_handler_id = nss_dev->id;
385 }
386
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530387 if (npd->tunipip6_enabled == NSS_FEATURE_ENABLED) {
388 nss_top->tunipip6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530389 nss_tunipip6_register_handler();
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530390 }
391
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530392 if (npd->gre_redir_enabled == NSS_FEATURE_ENABLED) {
393 nss_top->gre_redir_handler_id = nss_dev->id;
394 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR] = nss_dev->id;
395 nss_gre_redir_register_handler();
Ankit Dhanuka2ae20a82014-08-25 18:04:00 +0530396 nss_sjack_register_handler();
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530397 }
398
Stephen Wang38e89bc2014-11-06 11:34:45 -0800399 /*
400 * Mark data plane enabled so when nss core init done we call register to nss-gmac
401 */
402 for (i = 0 ; i < NSS_MAX_PHYSICAL_INTERFACES ; i ++) {
403 if (npd->gmac_enabled[i] == NSS_FEATURE_ENABLED) {
404 nss_data_plane_set_enabled(i);
405 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530406 }
407
Sundarajan Srinivasandedd8e42014-10-06 11:59:34 -0700408 nss_freq_register_handler();
Thomas Wu168ca262014-03-21 16:20:27 -0700409
Thomas Wuc3e382c2014-10-29 15:35:13 -0700410 nss_lso_rx_register_handler();
411
wthomas626147f2013-09-18 13:12:40 -0700412 nss_top->frequency_handler_id = nss_dev->id;
413
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530414 spin_unlock_bh(&(nss_top->lock));
415
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530416 /*
417 * Initialize decongestion callbacks to NULL
418 */
419 for (i = 0; i< NSS_MAX_CLIENTS; i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530420 nss_ctx->queue_decongestion_callback[i] = 0;
421 nss_ctx->queue_decongestion_ctx[i] = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530422 }
423
424 spin_lock_init(&(nss_ctx->decongest_cb_lock));
425 nss_ctx->magic = NSS_CTX_MAGIC;
426
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530427 nss_info("%p: Reseting NSS core %d now", nss_ctx, nss_ctx->id);
428
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530429 /*
430 * Enable clocks and bring NSS core out of reset
431 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530432 nss_hal_core_reset(nss_dev->id, nss_ctx->nmap, nss_ctx->load, nss_top->clk_src);
433
434 /*
435 * Enable interrupts for NSS core
436 */
437 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
438 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
439
440 if (npd->num_irq > 1) {
441 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
442 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
443 }
444
Radhakrishna Jigurub7346cf2013-12-16 13:08:43 +0530445 /*
446 * Initialize max buffer size for NSS core
447 */
448 nss_ctx->max_buf_size = NSS_NBUF_PAYLOAD_SIZE;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530449 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 +0530450 goto err_init_0;
451
452err_init_5:
453 unregister_netdev(nss_ctx->int_ctx[1].ndev);
454err_init_4:
455 free_netdev(nss_ctx->int_ctx[1].ndev);
456err_init_3:
457 free_irq(npd->irq[0], &nss_ctx->int_ctx[0]);
458err_init_2:
459 unregister_netdev(nss_ctx->int_ctx[0].ndev);
460err_init_1:
461 free_netdev(nss_ctx->int_ctx[0].ndev);
462err_init_0:
463 return err;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530464}
465
466/*
467 * nss_remove()
468 * HLOS device remove callback
469 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530470static int __devexit nss_remove(struct platform_device *nss_dev)
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530471{
472 struct nss_top_instance *nss_top = &nss_top_main;
473 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
Stephen Wang38e89bc2014-11-06 11:34:45 -0800474 int i;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530475
476 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530477 * Clean-up debugfs
478 */
479 nss_stats_clean();
480
481 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530482 * Disable interrupts and bottom halves in HLOS
483 * Disable interrupts from NSS to HLOS
484 */
485 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
486 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530487
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530488 free_irq(nss_ctx->int_ctx[0].irq, &nss_ctx->int_ctx[0]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530489 unregister_netdev(nss_ctx->int_ctx[0].ndev);
490 free_netdev(nss_ctx->int_ctx[0].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530491
492 /*
493 * Check if second interrupt is supported
494 * If so then clear resources for second interrupt as well
495 */
496 if (nss_ctx->int_ctx[1].irq) {
497 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
498 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530499 free_irq(nss_ctx->int_ctx[1].irq, &nss_ctx->int_ctx[1]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530500 unregister_netdev(nss_ctx->int_ctx[1].ndev);
501 free_netdev(nss_ctx->int_ctx[1].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530502 }
503
Stephen Wang38e89bc2014-11-06 11:34:45 -0800504 /*
505 * nss-drv is exiting, remove from nss-gmac
506 */
507 for (i = 0 ; i < NSS_MAX_PHYSICAL_INTERFACES ; i ++) {
508 if (nss_top->if_ctx[i]) {
509 nss_data_plane_unregister_from_nss_gmac(i);
510 }
511 }
512
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530513 nss_info("%p: All resources freed for nss core%d", nss_ctx, nss_dev->id);
514 return 0;
515}
516
517/*
518 * nss_driver
519 * Platform driver structure for NSS
520 */
521struct platform_driver nss_driver = {
522 .probe = nss_probe,
523 .remove = __devexit_p(nss_remove),
524 .driver = {
525 .name = "qca-nss",
526 .owner = THIS_MODULE,
527 },
528};
529
530/*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530531 * nss_reset_frequency_stats_samples()
532 * Reset all frequency sampling state when auto scaling is turned off.
533 */
534static void nss_reset_frequency_stats_samples (void)
535{
536 nss_runtime_samples.buffer_index = 0;
537 nss_runtime_samples.sum = 0;
538 nss_runtime_samples.average = 0;
539 nss_runtime_samples.sample_count = 0;
540 nss_runtime_samples.message_rate_limit = 0;
541 nss_runtime_samples.freq_scale_rate_limit_up = 0;
542 nss_runtime_samples.freq_scale_rate_limit_down = 0;
543}
544
545/*
wthomas626147f2013-09-18 13:12:40 -0700546 ***************************************************************************************************
Thomas Wufb6a6842013-10-23 13:14:27 -0700547 * nss_wq_function() is used to queue up requests to change NSS frequencies.
548 * The function will take care of NSS notices and also control clock.
549 * The auto rate algorithmn will queue up requests or the procfs may also queue up these requests.
wthomas626147f2013-09-18 13:12:40 -0700550 ***************************************************************************************************
551 */
552
553/*
554 * nss_wq_function()
555 * Added to Handle BH requests to kernel
556 */
557void nss_wq_function (struct work_struct *work)
558{
559 nss_work_t *my_work = (nss_work_t *)work;
560
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, 0);
Thomas Wufb6a6842013-10-23 13:14:27 -0700562 clk_set_rate(nss_core0_clk, my_work->frequency);
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530563 nss_freq_change(nss_freq_change_context, my_work->frequency, my_work->stats_enable, 1);
wthomas626147f2013-09-18 13:12:40 -0700564
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530565 if(!pm_client) {
566 goto out;
567 }
568
569 if (my_work->frequency == NSS_FREQ_733) {
570 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_TURBO);
571 } else if ((my_work->frequency == NSS_FREQ_275) || (my_work->frequency == NSS_FREQ_550)) {
572 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_NOMINAL);
573 } else {
574 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_IDLE);
575 }
576out:
wthomas626147f2013-09-18 13:12:40 -0700577 kfree((void *)work);
578}
579
580/*
wthomas442c7972013-08-05 14:28:17 -0700581 * nss_current_freq_handler()
582 * Handle Userspace Frequency Change Requests
583 */
584static int nss_current_freq_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
585{
wthomas442c7972013-08-05 14:28:17 -0700586 int ret;
wthomas626147f2013-09-18 13:12:40 -0700587
588 BUG_ON(!nss_wq);
wthomas442c7972013-08-05 14:28:17 -0700589
590 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
591
wthomasd39fa822013-08-22 16:44:23 -0700592 if (!write) {
wthomas626147f2013-09-18 13:12:40 -0700593 printk("Frequency Set to %d\n", nss_cmd_buf.current_freq);
wthomasd39fa822013-08-22 16:44:23 -0700594 return ret;
wthomas442c7972013-08-05 14:28:17 -0700595 }
wthomasd39fa822013-08-22 16:44:23 -0700596
wthomas626147f2013-09-18 13:12:40 -0700597 /* Turn off Auto Scale */
598 nss_cmd_buf.auto_scale = 0;
599 nss_runtime_samples.freq_scale_ready = 0;
wthomasd39fa822013-08-22 16:44:23 -0700600
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800601 /* If support NSS freq is in the table send the new frequency request to NSS or If No Turbo and ask for turbo freq */
602 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 -0700603 printk("Frequency not found. Please check Frequency Table\n");
wthomas626147f2013-09-18 13:12:40 -0700604 return ret;
wthomasd39fa822013-08-22 16:44:23 -0700605 }
606
Thomas Wu7409bce2014-05-21 10:56:07 -0700607 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
wthomas626147f2013-09-18 13:12:40 -0700608 if (!nss_work) {
609 nss_info("NSS Freq WQ kmalloc fail");
610 return ret;
611 }
612 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
613 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530614 nss_work->stats_enable = 0;
615
616 /* Ensure we start with a fresh set of samples later */
617 nss_reset_frequency_stats_samples();
618
wthomas626147f2013-09-18 13:12:40 -0700619 queue_work(nss_wq, (struct work_struct *)nss_work);
620
wthomas442c7972013-08-05 14:28:17 -0700621 return ret;
622}
623
624/*
625 * nss_auto_scale_handler()
626 * Enables or Disable Auto Scaling
627 */
628static int nss_auto_scale_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
629{
630 int ret;
631
632 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
633
wthomas626147f2013-09-18 13:12:40 -0700634 if (!write) {
635 return ret;
636 }
637
Thomas Wufb6a6842013-10-23 13:14:27 -0700638 if (nss_cmd_buf.auto_scale != 1) {
wthomas626147f2013-09-18 13:12:40 -0700639 /*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530640 * Is auto scaling currently enabled? If so, send the command to
641 * disable stats reporting to NSS
wthomas626147f2013-09-18 13:12:40 -0700642 */
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530643 if (nss_runtime_samples.freq_scale_ready != 0) {
644 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
Thomas Wu7409bce2014-05-21 10:56:07 -0700645 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530646 if (!nss_work) {
647 nss_info("NSS Freq WQ kmalloc fail");
648 return ret;
649 }
650 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
651 nss_work->frequency = nss_cmd_buf.current_freq;
652 nss_work->stats_enable = 0;
653 queue_work(nss_wq, (struct work_struct *)nss_work);
654 nss_runtime_samples.freq_scale_ready = 0;
655
656 /*
657 * The current samples would be stale later when scaling is
658 * enabled again, hence reset them
659 */
660 nss_reset_frequency_stats_samples();
661 }
Thomas Wufb6a6842013-10-23 13:14:27 -0700662 return ret;
wthomas626147f2013-09-18 13:12:40 -0700663 }
wthomas442c7972013-08-05 14:28:17 -0700664
Thomas Wufb6a6842013-10-23 13:14:27 -0700665 /*
666 * Auto Scaling is already being done
667 */
668 if (nss_runtime_samples.freq_scale_ready == 1) {
669 return ret;
670 }
671
672 /*
673 * Setup default values - Middle of Freq Scale Band
674 */
675 nss_runtime_samples.freq_scale_index = 1;
676 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
677
Thomas Wu7409bce2014-05-21 10:56:07 -0700678 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Thomas Wufb6a6842013-10-23 13:14:27 -0700679 if (!nss_work) {
680 nss_info("NSS Freq WQ kmalloc fail");
681 return ret;
682 }
683 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
684 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530685 nss_work->stats_enable = 1;
Thomas Wufb6a6842013-10-23 13:14:27 -0700686 queue_work(nss_wq, (struct work_struct *)nss_work);
687
688 nss_runtime_samples.freq_scale_ready = 1;
689
wthomas442c7972013-08-05 14:28:17 -0700690 return ret;
691}
692
693/*
694 * nss_get_freq_table_handler()
695 * Display Support Freq and Ex how to Change.
696 */
Thomas Wu05495be2013-12-19 14:24:24 -0800697static 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 -0700698{
699 int ret;
700
701 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
702
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800703 if (nss_runtime_samples.freq_scale_sup_max != NSS_MAX_CPU_SCALES) {
704 printk("Frequency Supported - 110Mhz 275Mhz 550Mhz\n");
705 printk("Ex. To Change Frequency - echo 110000000 > current_freq \n");
706
707 return ret;
708 }
709
wthomas626147f2013-09-18 13:12:40 -0700710 printk("Frequency Supported - 110Mhz 275Mhz 550Mhz 733Mhz \n");
wthomas442c7972013-08-05 14:28:17 -0700711 printk("Ex. To Change Frequency - echo 110000000 > current_freq \n");
712
713 return ret;
714}
715
716/*
Thomas Wu05495be2013-12-19 14:24:24 -0800717 * nss_get_average_inst_handler()
718 * Display AVG Inst Per Ms.
719 */
720static int nss_get_average_inst_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
721{
722 int ret;
723
724 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
725
726 if (!ret && !write) {
727 printk("Current Inst Per Ms %x\n", nss_runtime_samples.average);
728 }
729
730 return ret;
731}
732
733/*
Abhishek Rastogi1626a902013-11-21 17:09:49 +0530734 * nss_debug_handler()
735 * Enable NSS debug output
736 */
737static int nss_debug_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
738{
739 int ret;
740
741 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
742 if (!ret) {
743 if ((write) && (nss_ctl_debug != 0)) {
744 printk("Enabling NSS SPI Debug\n");
745 nss_hal_debug_enable();
746 }
747 }
748
749 return ret;
750}
751
752/*
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530753 * nss_rps_handler()
754 * Enable NSS RPS
755 */
756static int nss_rpscfg_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
757{
758 struct nss_top_instance *nss_top = &nss_top_main;
759 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
760 int ret;
761
762 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
763 if (!ret) {
764 if ((write) && (nss_rps_cfg == 1)) {
765 printk("Enabling NSS RPS\n");
Sundarajan Srinivasanf1e57462014-09-17 15:24:01 -0700766 nss_n2h_tx(nss_ctx, 1);
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530767 return ret;
768 }
769
770 if ((write) && (nss_rps_cfg == 0)) {
771 printk("Runtime disabling of NSS RPS not supported \n");
772 return ret;
773 }
774
775 if (write) {
776 printk("Invalid input value.Valid values are 0 and 1 \n");
777 }
778
779 }
780
781 return ret;
782}
783
784/*
Thomas Wu52075f42014-02-06 16:32:42 -0800785 * nss_coredump_handler()
786 * Send Signal To Coredump NSS Cores
787 */
788static int nss_coredump_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
789{
790 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *) nss_freq_change_context;
791 int ret;
792
793 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
794 if (!ret) {
795 if ((write) && (nss_ctl_debug != 0)) {
796 printk("Coredumping to DDR\n");
797 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);
798 }
799 }
800
801 return ret;
802}
803
804/*
wthomas442c7972013-08-05 14:28:17 -0700805 * sysctl-tuning infrastructure.
806 */
807static ctl_table nss_freq_table[] = {
808 {
809 .procname = "current_freq",
810 .data = &nss_cmd_buf.current_freq,
811 .maxlen = sizeof(int),
812 .mode = 0644,
813 .proc_handler = &nss_current_freq_handler,
814 },
815 {
816 .procname = "freq_table",
817 .data = &nss_cmd_buf.max_freq,
818 .maxlen = sizeof(int),
819 .mode = 0644,
820 .proc_handler = &nss_get_freq_table_handler,
821 },
822 {
823 .procname = "auto_scale",
824 .data = &nss_cmd_buf.auto_scale,
825 .maxlen = sizeof(int),
826 .mode = 0644,
827 .proc_handler = &nss_auto_scale_handler,
828 },
Thomas Wu05495be2013-12-19 14:24:24 -0800829 {
830 .procname = "inst_per_sec",
831 .data = &nss_cmd_buf.average_inst,
832 .maxlen = sizeof(int),
833 .mode = 0644,
834 .proc_handler = &nss_get_average_inst_handler,
835 },
wthomas442c7972013-08-05 14:28:17 -0700836 { }
837};
838
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530839static ctl_table nss_general_table[] = {
840 {
841 .procname = "redirect",
842 .data = &nss_ctl_redirect,
843 .maxlen = sizeof(int),
844 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700845 .proc_handler = proc_dointvec,
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530846 },
Abhishek Rastogi1626a902013-11-21 17:09:49 +0530847 {
848 .procname = "debug",
849 .data = &nss_ctl_debug,
850 .maxlen = sizeof(int),
851 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700852 .proc_handler = &nss_debug_handler,
Abhishek Rastogi1626a902013-11-21 17:09:49 +0530853 },
Thomas Wu52075f42014-02-06 16:32:42 -0800854 {
855 .procname = "coredump",
856 .data = &nss_cmd_buf.coredump,
857 .maxlen = sizeof(int),
858 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700859 .proc_handler = &nss_coredump_handler,
Thomas Wu52075f42014-02-06 16:32:42 -0800860 },
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530861 {
862 .procname = "rps",
863 .data = &nss_rps_cfg,
864 .maxlen = sizeof(int),
865 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -0700866 .proc_handler = &nss_rpscfg_handler,
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +0530867 },
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530868 { }
869};
870
wthomas442c7972013-08-05 14:28:17 -0700871static ctl_table nss_clock_dir[] = {
872 {
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +0530873 .procname = "clock",
874 .mode = 0555,
875 .child = nss_freq_table,
876 },
877 {
878 .procname = "general",
879 .mode = 0555,
880 .child = nss_general_table,
wthomas442c7972013-08-05 14:28:17 -0700881 },
882 { }
883};
884
885static ctl_table nss_root_dir[] = {
886 {
887 .procname = "nss",
888 .mode = 0555,
889 .child = nss_clock_dir,
890 },
891 { }
892};
893
894static ctl_table nss_root[] = {
895 {
896 .procname = "dev",
897 .mode = 0555,
898 .child = nss_root_dir,
899 },
900 { }
901};
902
903static struct ctl_table_header *nss_dev_header;
904
905/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530906 * nss_init()
907 * Registers nss driver
908 */
909static int __init nss_init(void)
910{
911 nss_info("Init NSS driver");
912
Sundarajan Srinivasandedd8e42014-10-06 11:59:34 -0700913 nss_freq_change_context = nss_freq_get_mgr();
914
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530915 /*
916 * Perform clock init common to all NSS cores
917 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530918 nss_hal_common_reset(&(nss_top_main.clk_src));
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530919
920 /*
921 * Enable spin locks
922 */
923 spin_lock_init(&(nss_top_main.lock));
924 spin_lock_init(&(nss_top_main.stats_lock));
925
926 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530927 * Enable NSS statistics
928 */
929 nss_stats_init();
930
931 /*
wthomas442c7972013-08-05 14:28:17 -0700932 * Register sysctl table.
933 */
934 nss_dev_header = register_sysctl_table(nss_root);
935
936 /*
Vijay Dewangan9db18752014-09-15 16:25:01 -0700937 * Registering sysctl for ipv4/6 specific config.
938 */
939 nss_ipv4_register_sysctl();
940 nss_ipv6_register_sysctl();
941
942 /*
wthomas626147f2013-09-18 13:12:40 -0700943 * Setup Runtime Sample values
944 */
945 nss_runtime_samples.freq_scale[0].frequency = NSS_FREQ_110;
wthomas626147f2013-09-18 13:12:40 -0700946 nss_runtime_samples.freq_scale[0].minimum = NSS_FREQ_110_MIN;
947 nss_runtime_samples.freq_scale[0].maximum = NSS_FREQ_110_MAX;
wthomas626147f2013-09-18 13:12:40 -0700948 nss_runtime_samples.freq_scale[1].frequency = NSS_FREQ_550;
wthomas626147f2013-09-18 13:12:40 -0700949 nss_runtime_samples.freq_scale[1].minimum = NSS_FREQ_550_MIN;
950 nss_runtime_samples.freq_scale[1].maximum = NSS_FREQ_550_MAX;
wthomas626147f2013-09-18 13:12:40 -0700951 nss_runtime_samples.freq_scale[2].frequency = NSS_FREQ_733;
wthomas626147f2013-09-18 13:12:40 -0700952 nss_runtime_samples.freq_scale[2].minimum = NSS_FREQ_733_MIN;
953 nss_runtime_samples.freq_scale[2].maximum = NSS_FREQ_733_MAX;
wthomas626147f2013-09-18 13:12:40 -0700954 nss_runtime_samples.freq_scale_index = 1;
955 nss_runtime_samples.freq_scale_ready = 0;
Thomas Wu9681f7e2013-11-06 13:12:57 -0800956 nss_runtime_samples.freq_scale_rate_limit_up = 0;
957 nss_runtime_samples.freq_scale_rate_limit_down = 0;
wthomas626147f2013-09-18 13:12:40 -0700958 nss_runtime_samples.buffer_index = 0;
959 nss_runtime_samples.sum = 0;
960 nss_runtime_samples.sample_count = 0;
961 nss_runtime_samples.average = 0;
962 nss_runtime_samples.message_rate_limit = 0;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530963 nss_runtime_samples.initialized = 0;
wthomas626147f2013-09-18 13:12:40 -0700964
Thomas Wu05495be2013-12-19 14:24:24 -0800965 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
966
wthomas626147f2013-09-18 13:12:40 -0700967 /*
968 * Initial Workqueue
969 */
970 nss_wq = create_workqueue("nss_freq_queue");
971
972 /*
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +0530973 * Initialize NSS Bus PM module
974 */
975 nss_pm_init();
976
977 /*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530978 * Register with Bus driver
979 */
980 pm_client = nss_pm_client_register(NSS_PM_CLIENT_NETAP);
981 if (!pm_client) {
982 nss_warning("Error registering with PM driver");
983 }
984
985 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530986 * Register platform_driver
987 */
988 return platform_driver_register(&nss_driver);
989}
990
991/*
992 * nss_cleanup()
993 * Unregisters nss driver
994 */
995static void __exit nss_cleanup(void)
996{
997 nss_info("Exit NSS driver");
wthomas442c7972013-08-05 14:28:17 -0700998
999 if (nss_dev_header)
1000 unregister_sysctl_table(nss_dev_header);
1001
Vijay Dewangan9db18752014-09-15 16:25:01 -07001002 /*
1003 * Unregister ipv4/6 specific sysctl
1004 */
1005 nss_ipv4_unregister_sysctl();
1006 nss_ipv6_unregister_sysctl();
1007
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301008 platform_driver_unregister(&nss_driver);
1009}
1010
1011module_init(nss_init);
1012module_exit(nss_cleanup);
1013
1014MODULE_DESCRIPTION("QCA NSS Driver");
1015MODULE_AUTHOR("Qualcomm Atheros Inc");
1016MODULE_LICENSE("Dual BSD/GPL");