blob: 9def3078dd15d5aabc4319b60d52668a8d736b00 [file] [log] [blame]
Radhakrishna Jiguru1c9b2252013-08-27 23:57:48 +05301/*
2 **************************************************************************
Vijay Dewangan488e5372014-12-29 21:40:11 -08003 * Copyright (c) 2013 - 2015, 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"
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080023#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053024#include "nss_pm.h"
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080025#endif
Abhishek Rastogi9da47472014-03-18 19:46:15 +053026#include "nss_tx_rx_common.h"
Stephen Wang38e89bc2014-11-06 11:34:45 -080027#include "nss_data_plane.h"
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053028
Abhishek Rastogibc74e432013-04-02 10:28:22 +053029#include <nss_hal.h>
Thomas Wufb6a6842013-10-23 13:14:27 -070030#include <nss_clocks.h>
Abhishek Rastogibc74e432013-04-02 10:28:22 +053031
32#include <linux/module.h>
33#include <linux/platform_device.h>
wthomas442c7972013-08-05 14:28:17 -070034#include <linux/proc_fs.h>
35#include <linux/device.h>
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080036
37#if (NSS_DT_SUPPORT == 1)
38#include <linux/of.h>
39#include <linux/of_net.h>
40#include <linux/of_irq.h>
41#include <linux/of_address.h>
42#include <linux/reset.h>
43#else
Abhishek Rastogibc74e432013-04-02 10:28:22 +053044#include <mach/msm_nss.h>
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080045#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +053046
wthomas442c7972013-08-05 14:28:17 -070047#include <linux/sysctl.h>
48#include <linux/regulator/consumer.h>
Thomas Wufb6a6842013-10-23 13:14:27 -070049#include <linux/clk.h>
Thomas Wu49008962014-04-02 14:50:47 -070050#include <linux/firmware.h>
51
Saurabh Misra09dddeb2014-09-30 16:38:07 -070052#include "nss_capwap.h"
53
Thomas Wu49008962014-04-02 14:50:47 -070054/*
55 * Macros
56 */
57#define MIN_IMG_SIZE 64*1024
Radha krishna Simha Jiguru6e74d572014-05-13 11:30:20 +053058#define NETAP0_IMAGE "qca-nss0.bin"
59#define NETAP1_IMAGE "qca-nss1.bin"
wthomas442c7972013-08-05 14:28:17 -070060
Abhishek Rastogibc74e432013-04-02 10:28:22 +053061/*
62 * Global declarations
63 */
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +053064int nss_ctl_redirect __read_mostly = 0;
Sakthi Vignesh Radhakrishnanaf39aad2014-03-31 11:31:03 -070065int nss_ctl_debug __read_mostly = 0;
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053066int nss_rps_cfg __read_mostly = 0;
Saurabh Misra96998db2014-07-10 12:15:48 -070067int nss_ctl_logbuf __read_mostly = 0;
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -080068int nss_jumbo_mru __read_mostly = 0;
69int nss_paged_mode __read_mostly = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +053070
Sundarajan Srinivasan6e0366b2015-01-20 12:10:42 -080071#ifdef CONFIG_DEBUG_KMEMLEAK
72extern struct sk_buff_head nss_skb_list;
73#endif
74
Abhishek Rastogibc74e432013-04-02 10:28:22 +053075/*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053076 * PM client handle
77 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080078#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053079static void *pm_client;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080080#endif
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053081
82/*
wthomas626147f2013-09-18 13:12:40 -070083 * Handler to send NSS messages
84 */
85void *nss_freq_change_context;
Thomas Wufb6a6842013-10-23 13:14:27 -070086struct clk *nss_core0_clk;
wthomas626147f2013-09-18 13:12:40 -070087
88/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +053089 * Top level nss context structure
90 */
91struct nss_top_instance nss_top_main;
wthomas442c7972013-08-05 14:28:17 -070092struct nss_cmd_buffer nss_cmd_buf;
wthomas626147f2013-09-18 13:12:40 -070093struct nss_runtime_sampling nss_runtime_samples;
94struct workqueue_struct *nss_wq;
95
96/*
97 * Work Queue to handle messages to Kernel
98 */
99nss_work_t *nss_work;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530100
101/*
102 * File local/Static variables/functions
103 */
104
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530105static const struct net_device_ops nss_netdev_ops;
106static const struct ethtool_ops nss_ethtool_ops;
107
108/*
109 * nss_dummy_netdev_setup()
110 * Dummy setup for net_device handler
111 */
112static void nss_dummy_netdev_setup(struct net_device *ndev)
113{
wthomas626147f2013-09-18 13:12:40 -0700114
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530115}
116
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530117/*
118 * nss_handle_irq()
119 * HLOS interrupt handler for nss interrupts
120 */
121static irqreturn_t nss_handle_irq (int irq, void *ctx)
122{
123 struct int_ctx_instance *int_ctx = (struct int_ctx_instance *) ctx;
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530124 struct nss_ctx_instance *nss_ctx = int_ctx->nss_ctx;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530125
126 /*
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530127 * Mask interrupt until our bottom half re-enables it
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530128 */
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530129 nss_hal_disable_interrupt(nss_ctx->nmap, int_ctx->irq,
130 int_ctx->shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530131
132 /*
133 * Schedule tasklet to process interrupt cause
134 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530135 napi_schedule(&int_ctx->napi);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530136 return IRQ_HANDLED;
137}
138
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800139#if (NSS_DT_SUPPORT == 1)
140/*
141 * nss_drv_of_get_pdata()
142 * Retrieve platform data from device node.
143 */
144static struct nss_platform_data *nss_drv_of_get_pdata(struct device_node *np,
145 struct platform_device *pdev)
146{
147 struct nss_platform_data *npd = NULL;
148 struct nss_ctx_instance *nss_ctx = NULL;
149 struct nss_top_instance *nss_top = &nss_top_main;
150 uint32_t val;
151 struct resource res_nphys, res_vphys;
152 int32_t i;
153
154 npd = devm_kzalloc(&pdev->dev, sizeof(struct nss_platform_data), GFP_KERNEL);
155 if (!npd) {
156 return NULL;
157 }
158
159 if (of_property_read_u32(np, "qcom,id", &npd->id)
160 || of_property_read_u32(np, "qcom,rst_addr", &npd->rst_addr)
161 || of_property_read_u32(np, "qcom,load_addr", &npd->load_addr)
162 || of_property_read_u32(np, "qcom,turbo_frequency", &npd->turbo_frequency)
163 || of_property_read_u32(np, "qcom,gmac0_enabled", &npd->gmac_enabled[0])
164 || of_property_read_u32(np, "qcom,gmac1_enabled", &npd->gmac_enabled[1])
165 || of_property_read_u32(np, "qcom,gmac2_enabled", &npd->gmac_enabled[2])
166 || of_property_read_u32(np, "qcom,gmac3_enabled", &npd->gmac_enabled[3])
167 || of_property_read_u32(np, "qcom,num_irq", &npd->num_irq)) {
168 pr_err("%s: error reading critical device node properties\n", np->name);
169 goto out;
170 }
171
172 nss_ctx = &nss_top->nss[npd->id];
173 nss_ctx->id = npd->id;
174
175 if (of_address_to_resource(np, 0, &res_nphys) != 0) {
176 nss_info("%p: nss%d: of_address_to_resource() fail for nphys \n", nss_ctx, nss_ctx->id);
177 goto out;
178 }
179
180 if (of_address_to_resource(np, 1, &res_vphys) != 0) {
181 nss_info("%p: nss%d: of_address_to_resource() fail for vphys \n", nss_ctx, nss_ctx->id);
182 goto out;
183 }
184
185 /*
186 * Save physical addresses
187 */
188 npd->nphys = res_nphys.start;
189 npd->vphys = res_vphys.start;
190
191 npd->nmap = (uint32_t)ioremap_nocache(npd->nphys, resource_size(&res_nphys));
192 if (!npd->nmap) {
193 nss_info("%p: nss%d: ioremap() fail for nphys \n", nss_ctx, nss_ctx->id);
194 goto out;
195 }
196
197 npd->vmap = (uint32_t)ioremap_nocache(npd->vphys, resource_size(&res_vphys));
198 if (!npd->vmap) {
199 nss_info("%p: nss%d: ioremap() fail for vphys \n", nss_ctx, nss_ctx->id);
200 goto out;
201 }
202
203 /*
204 * Clear TCM memory used by this core
205 */
206 for (i = 0; i < resource_size(&res_vphys) ; i += 4) {
207 nss_write_32((uint32_t)npd->vmap, i, 0);
208 }
209
210 /*
211 * Get IRQ numbers
212 */
213 for (val = 0 ; val < npd->num_irq ; val++) {
214 npd->irq[val] = irq_of_parse_and_map(np, val);
215 if (!npd->irq[val]) {
216 nss_info("%p: nss%d: irq_of_parse_and_map() fail for irq %d\n",
217 nss_ctx, nss_ctx->id, val);
218 goto out;
219 }
220 }
221
222 if (of_property_read_u32(np, "qcom,ipv4_enabled", &npd->ipv4_enabled)
223 || of_property_read_u32(np, "qcom,ipv6_enabled", &npd->ipv6_enabled)
224 || of_property_read_u32(np, "qcom,l2switch_enabled", &npd->l2switch_enabled)
225 || of_property_read_u32(np, "qcom,crypto_enabled", &npd->crypto_enabled)
226 || of_property_read_u32(np, "qcom,ipsec_enabled", &npd->ipsec_enabled)
227 || of_property_read_u32(np, "qcom,wlan_enabled", &npd->wlan_enabled)
228 || of_property_read_u32(np, "qcom,tun6rd_enabled", &npd->tun6rd_enabled)
229 || of_property_read_u32(np, "qcom,tunipip6_enabled", &npd->tunipip6_enabled)
230 || of_property_read_u32(np, "qcom,shaping_enabled", &npd->shaping_enabled)) {
231 pr_warn("%s: error reading non-critical device node properties\n", np->name);
232 }
233
234 return npd;
235
236out:
237 if (npd->nmap) {
238 iounmap((void *)npd->nmap);
239 }
240
241 if (npd->vmap) {
242 iounmap((void *)npd->vmap);
243 }
244
245 devm_kfree(&pdev->dev, npd);
246
247 return NULL;
248}
249
250#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530251/*
252 * nss_probe()
253 * HLOS device probe callback
254 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800255#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530256static int __devinit nss_probe(struct platform_device *nss_dev)
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800257#else
258static int nss_probe(struct platform_device *nss_dev)
259#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530260{
261 struct nss_top_instance *nss_top = &nss_top_main;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800262 struct nss_ctx_instance *nss_ctx = NULL;
263 struct nss_platform_data *npd = NULL;
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530264 struct netdev_priv_instance *ndev_priv;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800265#if (NSS_DT_SUPPORT == 1)
266 struct reset_control *rstctl = NULL;
267#endif
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530268 int i, err = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530269
Thomas Wu49008962014-04-02 14:50:47 -0700270 const struct firmware *nss_fw = NULL;
271 int rc = -ENODEV;
272 void __iomem *load_mem;
273
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800274#if (NSS_DT_SUPPORT == 1)
275 struct device_node *np = NULL;
276
277 if (nss_top_main.nss_hal_common_init_done == false) {
278 /*
279 * Perform clock init common to all NSS cores
280 */
281 struct clk *nss_tcm_src = NULL;
282 struct clk *nss_tcm_clk = NULL;
283
284 /*
285 * Attach debug interface to TLMM
286 */
287 nss_write_32((uint32_t)nss_top_main.nss_fpb_base, NSS_REGS_FPB_CSR_CFG_OFFSET, 0x360);
288
289 /*
290 * NSS TCM CLOCK
291 */
292 nss_tcm_src = clk_get(&nss_dev->dev, NSS_TCM_SRC_CLK);
293 if (IS_ERR(nss_tcm_src)) {
294 pr_err("nss-driver: cannot get clock: " NSS_TCM_SRC_CLK);
295 return -EFAULT;
296 }
297
298 clk_set_rate(nss_tcm_src, NSSTCM_FREQ);
299 clk_prepare(nss_tcm_src);
300 clk_enable(nss_tcm_src);
301
302 nss_tcm_clk = clk_get(&nss_dev->dev, NSS_TCM_CLK);
303 if (IS_ERR(nss_tcm_clk)) {
304 pr_err("nss-driver: cannot get clock: " NSS_TCM_CLK);
305 return -EFAULT;
306 }
307
308 clk_prepare(nss_tcm_clk);
309 clk_enable(nss_tcm_clk);
310
311 nss_top_main.nss_hal_common_init_done = true;
312 nss_info("nss_hal_common_reset Done.\n");
313 }
314
315 if (nss_dev->dev.of_node) {
316 /*
317 * Device Tree based init
318 */
319
320 np = of_node_get(nss_dev->dev.of_node);
321 npd = nss_drv_of_get_pdata(np, nss_dev);
322
323 of_node_put(np);
324
325 if (!npd) {
326 return -EFAULT;
327 }
328
329 nss_ctx = &nss_top->nss[npd->id];
330 nss_ctx->id = npd->id;
331 nss_dev->id = nss_ctx->id;
332
333 } else {
334 /*
335 * Platform Device based init
336 */
337
338 npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
339 nss_ctx = &nss_top->nss[nss_dev->id];
340 nss_ctx->id = nss_dev->id;
341 }
342
343#else
344 npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
345 nss_ctx = &nss_top->nss[nss_dev->id];
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530346 nss_ctx->id = nss_dev->id;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800347#endif
348 nss_ctx->nss_top = nss_top;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530349
wthomas442c7972013-08-05 14:28:17 -0700350 nss_info("%p: NSS_DEV_ID %s \n", nss_ctx, dev_name(&nss_dev->dev));
351
Stephen Wang38e89bc2014-11-06 11:34:45 -0800352 /*
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530353 * F/W load from NSS Driver
354 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800355 if (nss_ctx->id == 0) {
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530356 rc = request_firmware(&nss_fw, NETAP0_IMAGE, &(nss_dev->dev));
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800357 } else if (nss_ctx->id == 1) {
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530358 rc = request_firmware(&nss_fw, NETAP1_IMAGE, &(nss_dev->dev));
359 } else {
Samarjeet Banerjee7bce8c52014-05-02 15:32:13 +0530360 nss_warning("%p: Invalid nss dev: %d \n", nss_ctx, nss_dev->id);
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530361 }
362
363 /*
364 * Check if the file read is successful
365 */
366 if (rc) {
367 nss_warning("%p: request_firmware failed with err code: %d", nss_ctx, rc);
368 err = rc;
369 goto err_init_0;
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530370 }
371
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530372 if (nss_fw->size < MIN_IMG_SIZE) {
373 nss_warning("%p: nss firmware is truncated, size:%d", nss_ctx, nss_fw->size);
Thomas Wu49008962014-04-02 14:50:47 -0700374 }
375
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530376 load_mem = ioremap_nocache(npd->load_addr, nss_fw->size);
377 if (load_mem == NULL) {
378 nss_warning("%p: ioremap_nocache failed: %x", nss_ctx, npd->load_addr);
379 release_firmware(nss_fw);
Thomas Wu49008962014-04-02 14:50:47 -0700380 goto err_init_0;
Thomas Wu49008962014-04-02 14:50:47 -0700381 }
382
Saurabh Misra96998db2014-07-10 12:15:48 -0700383 printk("nss_driver - fw of size %u bytes copied to load addr: %x, nss_id : %d\n", nss_fw->size, npd->load_addr, nss_dev->id);
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530384 memcpy_toio(load_mem, nss_fw->data, nss_fw->size);
385 release_firmware(nss_fw);
386 iounmap(load_mem);
387
wthomas442c7972013-08-05 14:28:17 -0700388 /*
389 * Both NSS cores controlled by same regulator, Hook only Once
390 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800391 if (!nss_ctx->id) {
Thomas Wufb6a6842013-10-23 13:14:27 -0700392 nss_core0_clk = clk_get(&nss_dev->dev, "nss_core_clk");
393 if (IS_ERR(nss_core0_clk)) {
wthomas442c7972013-08-05 14:28:17 -0700394
Thomas Wufb6a6842013-10-23 13:14:27 -0700395 err = PTR_ERR(nss_core0_clk);
wthomas442c7972013-08-05 14:28:17 -0700396 nss_info("%p: Regulator %s get failed, err=%d\n", nss_ctx, dev_name(&nss_dev->dev), err);
397 return err;
398
wthomas442c7972013-08-05 14:28:17 -0700399 }
Thomas Wufb6a6842013-10-23 13:14:27 -0700400 clk_set_rate(nss_core0_clk, NSS_FREQ_550);
401 clk_prepare(nss_core0_clk);
402 clk_enable(nss_core0_clk);
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800403
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800404#if (NSS_PM_SUPPORT == 1)
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800405 /*
406 * Check if turbo is supported
407 */
408 if (npd->turbo_frequency) {
409 /*
410 * Turbo is supported
411 */
412 printk("nss_driver - Turbo Support %d\n", npd->turbo_frequency);
413 nss_runtime_samples.freq_scale_sup_max = NSS_MAX_CPU_SCALES;
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530414 nss_pm_set_turbo();
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800415 } else {
416 printk("nss_driver - Turbo No Support %d\n", npd->turbo_frequency);
417 nss_runtime_samples.freq_scale_sup_max = NSS_MAX_CPU_SCALES - 1;
418 }
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800419#else
420 printk("nss_driver - Turbo Not Supported\n");
421#endif
wthomas442c7972013-08-05 14:28:17 -0700422 }
423
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530424 /*
Sakthi Vignesh Radhakrishnand923e342013-12-09 11:53:03 -0800425 * Get load address of NSS firmware
426 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800427 nss_info("%p: Setting NSS%d Firmware load address to %x\n", nss_ctx, nss_ctx->id, npd->load_addr);
428 nss_top->nss[nss_ctx->id].load = npd->load_addr;
Sakthi Vignesh Radhakrishnand923e342013-12-09 11:53:03 -0800429
430 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530431 * Get virtual and physical memory addresses for nss logical/hardware address maps
432 */
433
434 /*
435 * Virtual address of CSM space
436 */
437 nss_ctx->nmap = npd->nmap;
438 nss_assert(nss_ctx->nmap);
439
440 /*
441 * Physical address of CSM space
442 */
443 nss_ctx->nphys = npd->nphys;
444 nss_assert(nss_ctx->nphys);
445
446 /*
447 * Virtual address of logical registers space
448 */
449 nss_ctx->vmap = npd->vmap;
450 nss_assert(nss_ctx->vmap);
451
452 /*
453 * Physical address of logical registers space
454 */
455 nss_ctx->vphys = npd->vphys;
456 nss_assert(nss_ctx->vphys);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530457 nss_info("%d:ctx=%p, vphys=%x, vmap=%x, nphys=%x, nmap=%x",
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800458 nss_ctx->id, nss_ctx, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530459
460 /*
461 * Register netdevice handlers
462 */
463 nss_ctx->int_ctx[0].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
464 "qca-nss-dev%d", nss_dummy_netdev_setup);
465 if (nss_ctx->int_ctx[0].ndev == NULL) {
466 nss_warning("%p: Could not allocate net_device #0", nss_ctx);
467 err = -ENOMEM;
468 goto err_init_0;
469 }
470
471 nss_ctx->int_ctx[0].ndev->netdev_ops = &nss_netdev_ops;
472 nss_ctx->int_ctx[0].ndev->ethtool_ops = &nss_ethtool_ops;
473 err = register_netdev(nss_ctx->int_ctx[0].ndev);
474 if (err) {
475 nss_warning("%p: Could not register net_device #0", nss_ctx);
476 goto err_init_1;
477 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530478
479 /*
480 * request for IRQs
481 *
482 * WARNING: CPU affinities should be set using OS supported methods
483 */
484 nss_ctx->int_ctx[0].nss_ctx = nss_ctx;
485 nss_ctx->int_ctx[0].shift_factor = 0;
486 nss_ctx->int_ctx[0].irq = npd->irq[0];
487 err = request_irq(npd->irq[0], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[0]);
488 if (err) {
489 nss_warning("%d: IRQ0 request failed", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530490 goto err_init_2;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530491 }
492
493 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530494 * Register NAPI for NSS core interrupt #0
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530495 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530496 ndev_priv = netdev_priv(nss_ctx->int_ctx[0].ndev);
497 ndev_priv->int_ctx = &nss_ctx->int_ctx[0];
498 netif_napi_add(nss_ctx->int_ctx[0].ndev, &nss_ctx->int_ctx[0].napi, nss_core_handle_napi, 64);
499 napi_enable(&nss_ctx->int_ctx[0].napi);
500 nss_ctx->int_ctx[0].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530501
502 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530503 * Check if second interrupt is supported on this nss core
504 */
505 if (npd->num_irq > 1) {
506 nss_info("%d: This NSS core supports two interrupts", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530507
508 /*
509 * Register netdevice handlers
510 */
511 nss_ctx->int_ctx[1].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
512 "qca-nss-dev%d", nss_dummy_netdev_setup);
513 if (nss_ctx->int_ctx[1].ndev == NULL) {
514 nss_warning("%p: Could not allocate net_device #1", nss_ctx);
515 err = -ENOMEM;
516 goto err_init_3;
517 }
518
519 nss_ctx->int_ctx[1].ndev->netdev_ops = &nss_netdev_ops;
520 nss_ctx->int_ctx[1].ndev->ethtool_ops = &nss_ethtool_ops;
521 err = register_netdev(nss_ctx->int_ctx[1].ndev);
522 if (err) {
523 nss_warning("%p: Could not register net_device #1", nss_ctx);
524 goto err_init_4;
525 }
526
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530527 nss_ctx->int_ctx[1].nss_ctx = nss_ctx;
528 nss_ctx->int_ctx[1].shift_factor = 15;
529 nss_ctx->int_ctx[1].irq = npd->irq[1];
530 err = request_irq(npd->irq[1], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[1]);
531 if (err) {
532 nss_warning("%d: IRQ1 request failed for nss", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530533 goto err_init_5;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530534 }
535
536 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530537 * Register NAPI for NSS core interrupt #1
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530538 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530539 ndev_priv = netdev_priv(nss_ctx->int_ctx[1].ndev);
540 ndev_priv->int_ctx = &nss_ctx->int_ctx[1];
541 netif_napi_add(nss_ctx->int_ctx[1].ndev, &nss_ctx->int_ctx[1].napi, nss_core_handle_napi, 64);
542 napi_enable(&nss_ctx->int_ctx[1].napi);
543 nss_ctx->int_ctx[1].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530544 }
545
546 spin_lock_bh(&(nss_top->lock));
547
548 /*
549 * Check functionalities are supported by this NSS core
550 */
Murat Sezgin7a705422014-01-30 16:09:22 -0800551 if (npd->shaping_enabled == NSS_FEATURE_ENABLED) {
552 nss_top->shaping_handler_id = nss_dev->id;
Sakthi Vignesh Radhakrishnanb042f472015-02-23 15:56:51 -0800553 nss_info("%d: NSS shaping is enabled", nss_dev->id);
Murat Sezgin7a705422014-01-30 16:09:22 -0800554 }
555
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530556 if (npd->ipv4_enabled == NSS_FEATURE_ENABLED) {
557 nss_top->ipv4_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530558 nss_ipv4_register_handler();
559 nss_pppoe_register_handler();
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530560 nss_eth_rx_register_handler();
561 nss_n2h_register_handler();
Sol Kavy2783c072014-04-05 12:53:13 -0700562 nss_virt_if_register_handler();
Tushar Mathura3e03052014-04-07 20:17:28 +0530563 nss_lag_register_handler();
Ankit Dhanuka9b430252014-08-12 13:53:41 +0530564 nss_dynamic_interface_register_handler();
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700565 nss_top->capwap_handler_id = nss_dev->id;
566 nss_capwap_init();
Ankit Dhanuka9b430252014-08-12 13:53:41 +0530567
Sol Kavy4013e282014-04-06 15:57:00 -0700568 for (i = 0; i < NSS_MAX_VIRTUAL_INTERFACES; i++) {
569 nss_top->virt_if_handler_id[i] = nss_dev->id;
570 }
Ankit Dhanuka65935322014-10-08 19:20:47 +0530571
572 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR] = nss_dev->id;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530573 }
574
Selin Dag6d9b0c12014-11-04 18:27:21 -0800575 if (npd->ipv4_reasm_enabled == NSS_FEATURE_ENABLED) {
576 nss_top->ipv4_reasm_handler_id = nss_dev->id;
577 nss_ipv4_reasm_register_handler();
578 }
579
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530580 if (npd->ipv6_enabled == NSS_FEATURE_ENABLED) {
581 nss_top->ipv6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530582 nss_ipv6_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530583 }
584
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530585 if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +0530586 nss_top->crypto_enabled = 1;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530587 nss_top->crypto_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530588 nss_crypto_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530589 }
590
591 if (npd->ipsec_enabled == NSS_FEATURE_ENABLED) {
592 nss_top->ipsec_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530593 nss_ipsec_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530594 }
595
596 if (npd->wlan_enabled == NSS_FEATURE_ENABLED) {
597 nss_top->wlan_handler_id = nss_dev->id;
598 }
599
Bharath M Kumar0d87e912013-08-12 18:32:57 +0530600 if (npd->tun6rd_enabled == NSS_FEATURE_ENABLED) {
601 nss_top->tun6rd_handler_id = nss_dev->id;
602 }
603
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530604 if (npd->tunipip6_enabled == NSS_FEATURE_ENABLED) {
605 nss_top->tunipip6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530606 nss_tunipip6_register_handler();
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530607 }
608
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530609 if (npd->gre_redir_enabled == NSS_FEATURE_ENABLED) {
610 nss_top->gre_redir_handler_id = nss_dev->id;
611 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR] = nss_dev->id;
612 nss_gre_redir_register_handler();
Ankit Dhanuka2ae20a82014-08-25 18:04:00 +0530613 nss_sjack_register_handler();
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530614 }
615
Stephen Wang38e89bc2014-11-06 11:34:45 -0800616 /*
617 * Mark data plane enabled so when nss core init done we call register to nss-gmac
618 */
619 for (i = 0 ; i < NSS_MAX_PHYSICAL_INTERFACES ; i ++) {
620 if (npd->gmac_enabled[i] == NSS_FEATURE_ENABLED) {
621 nss_data_plane_set_enabled(i);
622 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530623 }
624
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800625#if (NSS_PM_SUPPORT == 1)
Sundarajan Srinivasandedd8e42014-10-06 11:59:34 -0700626 nss_freq_register_handler();
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800627#endif
Thomas Wuc3e382c2014-10-29 15:35:13 -0700628 nss_lso_rx_register_handler();
629
wthomas626147f2013-09-18 13:12:40 -0700630 nss_top->frequency_handler_id = nss_dev->id;
631
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530632 spin_unlock_bh(&(nss_top->lock));
633
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530634 /*
635 * Initialize decongestion callbacks to NULL
636 */
637 for (i = 0; i< NSS_MAX_CLIENTS; i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530638 nss_ctx->queue_decongestion_callback[i] = 0;
639 nss_ctx->queue_decongestion_ctx[i] = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530640 }
641
642 spin_lock_init(&(nss_ctx->decongest_cb_lock));
643 nss_ctx->magic = NSS_CTX_MAGIC;
644
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530645 nss_info("%p: Reseting NSS core %d now", nss_ctx, nss_ctx->id);
646
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530647 /*
648 * Enable clocks and bring NSS core out of reset
649 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800650#if (NSS_DT_SUPPORT == 1)
651 /*
652 * Remove UBI32 reset clamp
653 */
Stephen Wang83e48752015-03-03 18:41:40 -0800654 rstctl = devm_reset_control_get(&nss_dev->dev, "clkrst_clamp");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800655 if (IS_ERR(rstctl)) {
656 nss_info("%p: Deassert UBI32 reset clamp failed", nss_ctx, nss_ctx->id);
657 err = -EFAULT;
658 goto err_init_5;
659 }
660 reset_control_deassert(rstctl);
661 mdelay(1);
662 reset_control_put(rstctl);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530663
664 /*
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800665 * Remove UBI32 core clamp
666 */
Stephen Wang83e48752015-03-03 18:41:40 -0800667 rstctl = devm_reset_control_get(&nss_dev->dev, "clamp");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800668 if (IS_ERR(rstctl)) {
669 nss_info("%p: Deassert UBI32 core clamp failed", nss_ctx, nss_ctx->id);
670 err = -EFAULT;
671 goto err_init_5;
672 }
673 reset_control_deassert(rstctl);
674 mdelay(1);
675 reset_control_put(rstctl);
676
677 /*
678 * Remove UBI32 AHB reset
679 */
Stephen Wang83e48752015-03-03 18:41:40 -0800680 rstctl = devm_reset_control_get(&nss_dev->dev, "ahb");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800681 if (IS_ERR(rstctl)) {
682 nss_info("%p: Deassert AHB reset failed", nss_ctx, nss_ctx->id);
683 err = -EFAULT;
684 goto err_init_5;
685 }
686 reset_control_deassert(rstctl);
687 mdelay(1);
688 reset_control_put(rstctl);
689
690 /*
691 * Remove UBI32 AXI reset
692 */
Stephen Wang83e48752015-03-03 18:41:40 -0800693 rstctl = devm_reset_control_get(&nss_dev->dev, "axi");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800694 if (IS_ERR(rstctl)) {
695 nss_info("%p: Deassert AXI reset failed", nss_ctx, nss_ctx->id);
696 err = -EFAULT;
697 goto err_init_5;
698 }
699 reset_control_deassert(rstctl);
700 mdelay(1);
701 reset_control_put(rstctl);
702
703 nss_hal_core_reset(nss_ctx->nmap, nss_ctx->load);
704#else
705 nss_hal_core_reset(nss_dev->id, nss_ctx->nmap, nss_ctx->load, nss_top->clk_src);
706#endif
707 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530708 * Enable interrupts for NSS core
709 */
710 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
711 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
712
713 if (npd->num_irq > 1) {
714 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
715 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
716 }
717
Radhakrishna Jigurub7346cf2013-12-16 13:08:43 +0530718 /*
719 * Initialize max buffer size for NSS core
720 */
721 nss_ctx->max_buf_size = NSS_NBUF_PAYLOAD_SIZE;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530722 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 +0530723 goto err_init_0;
724
725err_init_5:
726 unregister_netdev(nss_ctx->int_ctx[1].ndev);
727err_init_4:
728 free_netdev(nss_ctx->int_ctx[1].ndev);
729err_init_3:
730 free_irq(npd->irq[0], &nss_ctx->int_ctx[0]);
731err_init_2:
732 unregister_netdev(nss_ctx->int_ctx[0].ndev);
733err_init_1:
734 free_netdev(nss_ctx->int_ctx[0].ndev);
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800735
736#if (NSS_DT_SUPPORT == 1)
737 if (nss_dev->dev.of_node) {
738 if (npd->nmap) {
739 iounmap((void *)npd->nmap);
740 }
741
742 if (npd->vmap) {
743 iounmap((void *)npd->vmap);
744 }
745 }
746#endif
747
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530748err_init_0:
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800749
750#if (NSS_DT_SUPPORT == 1)
751 if (nss_dev->dev.of_node) {
752 devm_kfree(&nss_dev->dev, npd);
753 }
754
755#endif
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530756 return err;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530757}
758
759/*
760 * nss_remove()
761 * HLOS device remove callback
762 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800763#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530764static int __devexit nss_remove(struct platform_device *nss_dev)
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800765#else
766static int nss_remove(struct platform_device *nss_dev)
767#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530768{
769 struct nss_top_instance *nss_top = &nss_top_main;
770 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
Stephen Wang38e89bc2014-11-06 11:34:45 -0800771 int i;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530772
773 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530774 * Clean-up debugfs
775 */
776 nss_stats_clean();
777
778 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530779 * Disable interrupts and bottom halves in HLOS
780 * Disable interrupts from NSS to HLOS
781 */
782 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
783 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530784
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530785 free_irq(nss_ctx->int_ctx[0].irq, &nss_ctx->int_ctx[0]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530786 unregister_netdev(nss_ctx->int_ctx[0].ndev);
787 free_netdev(nss_ctx->int_ctx[0].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530788
789 /*
790 * Check if second interrupt is supported
791 * If so then clear resources for second interrupt as well
792 */
793 if (nss_ctx->int_ctx[1].irq) {
794 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
795 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530796 free_irq(nss_ctx->int_ctx[1].irq, &nss_ctx->int_ctx[1]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530797 unregister_netdev(nss_ctx->int_ctx[1].ndev);
798 free_netdev(nss_ctx->int_ctx[1].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530799 }
800
Stephen Wang38e89bc2014-11-06 11:34:45 -0800801 /*
802 * nss-drv is exiting, remove from nss-gmac
803 */
804 for (i = 0 ; i < NSS_MAX_PHYSICAL_INTERFACES ; i ++) {
Sundarajan Srinivasan70374842014-11-19 15:22:52 -0800805 if (nss_top->subsys_dp_register[i].ndev) {
Stephen Wang38e89bc2014-11-06 11:34:45 -0800806 nss_data_plane_unregister_from_nss_gmac(i);
807 }
808 }
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800809#if (NSS_DT_SUPPORT == 1)
810 if (nss_dev->dev.of_node) {
811 if (nss_ctx->nmap) {
812 iounmap((void *)nss_ctx->nmap);
813 nss_ctx->nmap = 0;
814 }
815
816 if (nss_ctx->vmap) {
817 iounmap((void *)nss_ctx->vmap);
818 nss_ctx->vmap = 0;
819 }
820 }
821#endif
Stephen Wang38e89bc2014-11-06 11:34:45 -0800822
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530823 nss_info("%p: All resources freed for nss core%d", nss_ctx, nss_dev->id);
824 return 0;
825}
826
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800827#if (NSS_DT_SUPPORT == 1)
828static struct of_device_id nss_dt_ids[] = {
829 { .compatible = "qcom,nss0" },
830 { .compatible = "qcom,nss1" },
831 {},
832};
833MODULE_DEVICE_TABLE(of, nss_dt_ids);
834#endif
835
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530836/*
837 * nss_driver
838 * Platform driver structure for NSS
839 */
840struct platform_driver nss_driver = {
841 .probe = nss_probe,
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800842#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530843 .remove = __devexit_p(nss_remove),
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800844#else
845 .remove = nss_remove,
846#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530847 .driver = {
848 .name = "qca-nss",
849 .owner = THIS_MODULE,
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800850#if (NSS_DT_SUPPORT == 1)
851 .of_match_table = of_match_ptr(nss_dt_ids),
852#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530853 },
854};
855
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800856#if (NSS_PM_SUPPORT == 1)
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530857/*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530858 * nss_reset_frequency_stats_samples()
859 * Reset all frequency sampling state when auto scaling is turned off.
860 */
861static void nss_reset_frequency_stats_samples (void)
862{
863 nss_runtime_samples.buffer_index = 0;
864 nss_runtime_samples.sum = 0;
865 nss_runtime_samples.average = 0;
866 nss_runtime_samples.sample_count = 0;
867 nss_runtime_samples.message_rate_limit = 0;
868 nss_runtime_samples.freq_scale_rate_limit_up = 0;
869 nss_runtime_samples.freq_scale_rate_limit_down = 0;
870}
871
872/*
wthomas626147f2013-09-18 13:12:40 -0700873 ***************************************************************************************************
Thomas Wufb6a6842013-10-23 13:14:27 -0700874 * nss_wq_function() is used to queue up requests to change NSS frequencies.
875 * The function will take care of NSS notices and also control clock.
876 * The auto rate algorithmn will queue up requests or the procfs may also queue up these requests.
wthomas626147f2013-09-18 13:12:40 -0700877 ***************************************************************************************************
878 */
879
880/*
881 * nss_wq_function()
882 * Added to Handle BH requests to kernel
883 */
884void nss_wq_function (struct work_struct *work)
885{
886 nss_work_t *my_work = (nss_work_t *)work;
887
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530888 nss_freq_change(nss_freq_change_context, my_work->frequency, my_work->stats_enable, 0);
Thomas Wufb6a6842013-10-23 13:14:27 -0700889 clk_set_rate(nss_core0_clk, my_work->frequency);
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530890 nss_freq_change(nss_freq_change_context, my_work->frequency, my_work->stats_enable, 1);
wthomas626147f2013-09-18 13:12:40 -0700891
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530892 if(!pm_client) {
893 goto out;
894 }
895
896 if (my_work->frequency == NSS_FREQ_733) {
897 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_TURBO);
898 } else if ((my_work->frequency == NSS_FREQ_275) || (my_work->frequency == NSS_FREQ_550)) {
899 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_NOMINAL);
900 } else {
901 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_IDLE);
902 }
903out:
wthomas626147f2013-09-18 13:12:40 -0700904 kfree((void *)work);
905}
906
907/*
wthomas442c7972013-08-05 14:28:17 -0700908 * nss_current_freq_handler()
909 * Handle Userspace Frequency Change Requests
910 */
911static int nss_current_freq_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
912{
wthomas442c7972013-08-05 14:28:17 -0700913 int ret;
wthomas626147f2013-09-18 13:12:40 -0700914
915 BUG_ON(!nss_wq);
wthomas442c7972013-08-05 14:28:17 -0700916
917 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
918
wthomasd39fa822013-08-22 16:44:23 -0700919 if (!write) {
wthomas626147f2013-09-18 13:12:40 -0700920 printk("Frequency Set to %d\n", nss_cmd_buf.current_freq);
wthomasd39fa822013-08-22 16:44:23 -0700921 return ret;
wthomas442c7972013-08-05 14:28:17 -0700922 }
wthomasd39fa822013-08-22 16:44:23 -0700923
wthomas626147f2013-09-18 13:12:40 -0700924 /* Turn off Auto Scale */
925 nss_cmd_buf.auto_scale = 0;
926 nss_runtime_samples.freq_scale_ready = 0;
wthomasd39fa822013-08-22 16:44:23 -0700927
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800928 /* If support NSS freq is in the table send the new frequency request to NSS or If No Turbo and ask for turbo freq */
929 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 -0700930 printk("Frequency not found. Please check Frequency Table\n");
wthomas626147f2013-09-18 13:12:40 -0700931 return ret;
wthomasd39fa822013-08-22 16:44:23 -0700932 }
933
Thomas Wu7409bce2014-05-21 10:56:07 -0700934 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
wthomas626147f2013-09-18 13:12:40 -0700935 if (!nss_work) {
936 nss_info("NSS Freq WQ kmalloc fail");
937 return ret;
938 }
939 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
940 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530941 nss_work->stats_enable = 0;
942
943 /* Ensure we start with a fresh set of samples later */
944 nss_reset_frequency_stats_samples();
945
wthomas626147f2013-09-18 13:12:40 -0700946 queue_work(nss_wq, (struct work_struct *)nss_work);
947
wthomas442c7972013-08-05 14:28:17 -0700948 return ret;
949}
950
951/*
952 * nss_auto_scale_handler()
953 * Enables or Disable Auto Scaling
954 */
955static int nss_auto_scale_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
956{
957 int ret;
958
959 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
960
wthomas626147f2013-09-18 13:12:40 -0700961 if (!write) {
962 return ret;
963 }
964
Thomas Wufb6a6842013-10-23 13:14:27 -0700965 if (nss_cmd_buf.auto_scale != 1) {
wthomas626147f2013-09-18 13:12:40 -0700966 /*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530967 * Is auto scaling currently enabled? If so, send the command to
968 * disable stats reporting to NSS
wthomas626147f2013-09-18 13:12:40 -0700969 */
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530970 if (nss_runtime_samples.freq_scale_ready != 0) {
971 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
Thomas Wu7409bce2014-05-21 10:56:07 -0700972 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530973 if (!nss_work) {
974 nss_info("NSS Freq WQ kmalloc fail");
975 return ret;
976 }
977 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
978 nss_work->frequency = nss_cmd_buf.current_freq;
979 nss_work->stats_enable = 0;
980 queue_work(nss_wq, (struct work_struct *)nss_work);
981 nss_runtime_samples.freq_scale_ready = 0;
982
983 /*
984 * The current samples would be stale later when scaling is
985 * enabled again, hence reset them
986 */
987 nss_reset_frequency_stats_samples();
988 }
Thomas Wufb6a6842013-10-23 13:14:27 -0700989 return ret;
wthomas626147f2013-09-18 13:12:40 -0700990 }
wthomas442c7972013-08-05 14:28:17 -0700991
Thomas Wufb6a6842013-10-23 13:14:27 -0700992 /*
993 * Auto Scaling is already being done
994 */
995 if (nss_runtime_samples.freq_scale_ready == 1) {
996 return ret;
997 }
998
999 /*
1000 * Setup default values - Middle of Freq Scale Band
1001 */
1002 nss_runtime_samples.freq_scale_index = 1;
1003 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
1004
Thomas Wu7409bce2014-05-21 10:56:07 -07001005 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Thomas Wufb6a6842013-10-23 13:14:27 -07001006 if (!nss_work) {
1007 nss_info("NSS Freq WQ kmalloc fail");
1008 return ret;
1009 }
1010 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
1011 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301012 nss_work->stats_enable = 1;
Thomas Wufb6a6842013-10-23 13:14:27 -07001013 queue_work(nss_wq, (struct work_struct *)nss_work);
1014
1015 nss_runtime_samples.freq_scale_ready = 1;
1016
wthomas442c7972013-08-05 14:28:17 -07001017 return ret;
1018}
1019
1020/*
1021 * nss_get_freq_table_handler()
1022 * Display Support Freq and Ex how to Change.
1023 */
Thomas Wu05495be2013-12-19 14:24:24 -08001024static 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 -07001025{
1026 int ret;
1027
1028 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1029
Thomas Wu0a0a9c92013-11-21 15:28:19 -08001030 if (nss_runtime_samples.freq_scale_sup_max != NSS_MAX_CPU_SCALES) {
1031 printk("Frequency Supported - 110Mhz 275Mhz 550Mhz\n");
1032 printk("Ex. To Change Frequency - echo 110000000 > current_freq \n");
1033
1034 return ret;
1035 }
1036
wthomas626147f2013-09-18 13:12:40 -07001037 printk("Frequency Supported - 110Mhz 275Mhz 550Mhz 733Mhz \n");
wthomas442c7972013-08-05 14:28:17 -07001038 printk("Ex. To Change Frequency - echo 110000000 > current_freq \n");
1039
1040 return ret;
1041}
1042
1043/*
Thomas Wu05495be2013-12-19 14:24:24 -08001044 * nss_get_average_inst_handler()
1045 * Display AVG Inst Per Ms.
1046 */
1047static int nss_get_average_inst_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1048{
1049 int ret;
1050
1051 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1052
1053 if (!ret && !write) {
1054 printk("Current Inst Per Ms %x\n", nss_runtime_samples.average);
1055 }
1056
1057 return ret;
1058}
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001059#endif /* NSS_PM_SUPPORT */
Thomas Wu05495be2013-12-19 14:24:24 -08001060
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001061#if (NSS_FW_DBG_SUPPORT == 1)
Thomas Wu05495be2013-12-19 14:24:24 -08001062/*
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301063 * nss_debug_handler()
1064 * Enable NSS debug output
1065 */
1066static int nss_debug_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1067{
1068 int ret;
1069
1070 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1071 if (!ret) {
1072 if ((write) && (nss_ctl_debug != 0)) {
1073 printk("Enabling NSS SPI Debug\n");
1074 nss_hal_debug_enable();
1075 }
1076 }
1077
1078 return ret;
1079}
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001080#endif
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301081
1082/*
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301083 * nss_rps_handler()
1084 * Enable NSS RPS
1085 */
1086static int nss_rpscfg_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1087{
1088 struct nss_top_instance *nss_top = &nss_top_main;
1089 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
1090 int ret;
1091
1092 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1093 if (!ret) {
1094 if ((write) && (nss_rps_cfg == 1)) {
1095 printk("Enabling NSS RPS\n");
Vijay Dewangan634ce592015-01-07 17:21:09 -08001096
1097 return nss_n2h_rps_cfg(nss_ctx, 1);
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301098 }
1099
1100 if ((write) && (nss_rps_cfg == 0)) {
1101 printk("Runtime disabling of NSS RPS not supported \n");
1102 return ret;
1103 }
1104
1105 if (write) {
1106 printk("Invalid input value.Valid values are 0 and 1 \n");
1107 }
1108
1109 }
1110
1111 return ret;
1112}
1113
1114/*
Thomas Wu52075f42014-02-06 16:32:42 -08001115 * nss_coredump_handler()
1116 * Send Signal To Coredump NSS Cores
1117 */
1118static int nss_coredump_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1119{
1120 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *) nss_freq_change_context;
1121 int ret;
1122
1123 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1124 if (!ret) {
1125 if ((write) && (nss_ctl_debug != 0)) {
1126 printk("Coredumping to DDR\n");
1127 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);
1128 }
1129 }
1130
1131 return ret;
1132}
1133
1134/*
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -08001135 * nss_jumbo_mru_handler()
1136 * Sysctl to modify nss_jumbo_mru
1137 */
1138static int nss_jumbo_mru_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1139{
1140 int ret;
1141
1142 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1143 if (ret) {
1144 return ret;
1145 }
1146
1147 if (write) {
1148 nss_core_set_jumbo_mru(nss_jumbo_mru);
1149 nss_info("jumbo_mru set to %d\n", nss_jumbo_mru);
1150 }
1151
1152 return ret;
1153}
1154
1155/* nss_paged_mode_handler()
1156 * Sysctl to modify nss_paged_mode.
1157 */
1158
1159static int nss_paged_mode_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1160{
1161 int ret;
1162
1163 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1164 if (ret) {
1165 return ret;
1166 }
1167
1168 if (write) {
1169 nss_core_set_paged_mode(nss_paged_mode);
1170 nss_info("paged_mode set to %d\n", nss_paged_mode);
1171 }
1172
1173 return ret;
1174}
1175
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001176#if (NSS_PM_SUPPORT == 1)
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -08001177/*
wthomas442c7972013-08-05 14:28:17 -07001178 * sysctl-tuning infrastructure.
1179 */
1180static ctl_table nss_freq_table[] = {
1181 {
1182 .procname = "current_freq",
1183 .data = &nss_cmd_buf.current_freq,
1184 .maxlen = sizeof(int),
1185 .mode = 0644,
1186 .proc_handler = &nss_current_freq_handler,
1187 },
1188 {
1189 .procname = "freq_table",
1190 .data = &nss_cmd_buf.max_freq,
1191 .maxlen = sizeof(int),
1192 .mode = 0644,
1193 .proc_handler = &nss_get_freq_table_handler,
1194 },
1195 {
1196 .procname = "auto_scale",
1197 .data = &nss_cmd_buf.auto_scale,
1198 .maxlen = sizeof(int),
1199 .mode = 0644,
1200 .proc_handler = &nss_auto_scale_handler,
1201 },
Thomas Wu05495be2013-12-19 14:24:24 -08001202 {
1203 .procname = "inst_per_sec",
1204 .data = &nss_cmd_buf.average_inst,
1205 .maxlen = sizeof(int),
1206 .mode = 0644,
1207 .proc_handler = &nss_get_average_inst_handler,
1208 },
wthomas442c7972013-08-05 14:28:17 -07001209 { }
1210};
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001211#endif
wthomas442c7972013-08-05 14:28:17 -07001212
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301213static ctl_table nss_general_table[] = {
1214 {
1215 .procname = "redirect",
1216 .data = &nss_ctl_redirect,
1217 .maxlen = sizeof(int),
1218 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001219 .proc_handler = proc_dointvec,
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301220 },
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001221#if (NSS_FW_DBG_SUPPORT == 1)
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301222 {
1223 .procname = "debug",
1224 .data = &nss_ctl_debug,
1225 .maxlen = sizeof(int),
1226 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001227 .proc_handler = &nss_debug_handler,
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301228 },
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001229#endif
Thomas Wu52075f42014-02-06 16:32:42 -08001230 {
1231 .procname = "coredump",
1232 .data = &nss_cmd_buf.coredump,
1233 .maxlen = sizeof(int),
1234 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001235 .proc_handler = &nss_coredump_handler,
Thomas Wu52075f42014-02-06 16:32:42 -08001236 },
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301237 {
1238 .procname = "rps",
1239 .data = &nss_rps_cfg,
1240 .maxlen = sizeof(int),
1241 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001242 .proc_handler = &nss_rpscfg_handler,
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301243 },
Saurabh Misra96998db2014-07-10 12:15:48 -07001244 {
1245 .procname = "logbuf",
1246 .data = &nss_ctl_logbuf,
1247 .maxlen = sizeof(int),
1248 .mode = 0644,
1249 .proc_handler = &nss_logbuffer_handler,
1250 },
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -08001251 {
1252 .procname = "jumbo_mru",
1253 .data = &nss_jumbo_mru,
1254 .maxlen = sizeof(int),
1255 .mode = 0644,
1256 .proc_handler = &nss_jumbo_mru_handler,
1257 },
1258 {
1259 .procname = "paged_mode",
1260 .data = &nss_paged_mode,
1261 .maxlen = sizeof(int),
1262 .mode = 0644,
1263 .proc_handler = &nss_paged_mode_handler,
1264 },
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301265 { }
1266};
1267
wthomas442c7972013-08-05 14:28:17 -07001268static ctl_table nss_clock_dir[] = {
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001269#if (NSS_PM_SUPPORT == 1)
wthomas442c7972013-08-05 14:28:17 -07001270 {
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301271 .procname = "clock",
1272 .mode = 0555,
1273 .child = nss_freq_table,
1274 },
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001275#endif
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301276 {
1277 .procname = "general",
1278 .mode = 0555,
1279 .child = nss_general_table,
wthomas442c7972013-08-05 14:28:17 -07001280 },
1281 { }
1282};
1283
1284static ctl_table nss_root_dir[] = {
1285 {
1286 .procname = "nss",
1287 .mode = 0555,
1288 .child = nss_clock_dir,
1289 },
1290 { }
1291};
1292
1293static ctl_table nss_root[] = {
1294 {
1295 .procname = "dev",
1296 .mode = 0555,
1297 .child = nss_root_dir,
1298 },
1299 { }
1300};
1301
1302static struct ctl_table_header *nss_dev_header;
1303
1304/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301305 * nss_init()
1306 * Registers nss driver
1307 */
1308static int __init nss_init(void)
1309{
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001310#if (NSS_DT_SUPPORT == 1)
1311 struct device_node *cmn = NULL;
1312 struct resource res_nss_fpb_base;
1313#endif
1314
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301315 nss_info("Init NSS driver");
1316
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001317#if (NSS_PM_SUPPORT == 1)
Sundarajan Srinivasandedd8e42014-10-06 11:59:34 -07001318 nss_freq_change_context = nss_freq_get_mgr();
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001319#else
1320 nss_freq_change_context = NULL;
1321#endif
Sundarajan Srinivasandedd8e42014-10-06 11:59:34 -07001322
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001323#if (NSS_DT_SUPPORT == 1)
1324 /*
1325 * Get reference to NSS common device node
1326 */
1327 cmn = of_find_node_by_name(NULL, "nss-common");
1328 if (!cmn) {
1329 nss_info("cannot find nss-common node\n");
1330 return -EFAULT;
1331 }
1332
1333 if (of_address_to_resource(cmn, 0, &res_nss_fpb_base) != 0) {
1334 nss_info("of_address_to_resource() return error for nss_fpb_base\n");
1335 of_node_put(cmn);
1336 return -EFAULT;
1337 }
1338
1339 nss_top_main.nss_fpb_base = ioremap_nocache(res_nss_fpb_base.start,
1340 resource_size(&res_nss_fpb_base));
1341 if (!nss_top_main.nss_fpb_base) {
1342 nss_info("ioremap fail for nss_fpb_base\n");
1343 of_node_put(cmn);
1344 return -EFAULT;
1345 }
1346
1347 nss_top_main.nss_hal_common_init_done = false;
1348
1349 /*
1350 * Release reference to NSS common device node
1351 */
1352 of_node_put(cmn);
1353 cmn = NULL;
1354#else
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301355 /*
1356 * Perform clock init common to all NSS cores
1357 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301358 nss_hal_common_reset(&(nss_top_main.clk_src));
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301359
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001360#endif /* NSS_DT_SUPPORT */
1361
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301362 /*
1363 * Enable spin locks
1364 */
1365 spin_lock_init(&(nss_top_main.lock));
1366 spin_lock_init(&(nss_top_main.stats_lock));
1367
1368 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301369 * Enable NSS statistics
1370 */
1371 nss_stats_init();
1372
1373 /*
wthomas442c7972013-08-05 14:28:17 -07001374 * Register sysctl table.
1375 */
1376 nss_dev_header = register_sysctl_table(nss_root);
1377
1378 /*
Vijay Dewangan9db18752014-09-15 16:25:01 -07001379 * Registering sysctl for ipv4/6 specific config.
1380 */
1381 nss_ipv4_register_sysctl();
1382 nss_ipv6_register_sysctl();
1383
Vijay Dewanganac7efc42015-02-09 16:04:53 -08001384 /*
1385 * Registering sysctl for n2h empty pool buffer.
1386 */
1387 nss_n2h_empty_pool_buf_register_sysctl();
1388
Sundarajan Srinivasan6e0366b2015-01-20 12:10:42 -08001389#ifdef CONFIG_DEBUG_KMEMLEAK
1390 /*
1391 * If the system is under kmemleak debugging, track our
1392 * skbs by putting them in a list.
1393 */
1394
1395 skb_queue_head_init(&nss_skb_list);
1396#endif
1397
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001398#if (NSS_PM_SUPPORT == 1)
Vijay Dewangan9db18752014-09-15 16:25:01 -07001399 /*
wthomas626147f2013-09-18 13:12:40 -07001400 * Setup Runtime Sample values
1401 */
1402 nss_runtime_samples.freq_scale[0].frequency = NSS_FREQ_110;
wthomas626147f2013-09-18 13:12:40 -07001403 nss_runtime_samples.freq_scale[0].minimum = NSS_FREQ_110_MIN;
1404 nss_runtime_samples.freq_scale[0].maximum = NSS_FREQ_110_MAX;
wthomas626147f2013-09-18 13:12:40 -07001405 nss_runtime_samples.freq_scale[1].frequency = NSS_FREQ_550;
wthomas626147f2013-09-18 13:12:40 -07001406 nss_runtime_samples.freq_scale[1].minimum = NSS_FREQ_550_MIN;
1407 nss_runtime_samples.freq_scale[1].maximum = NSS_FREQ_550_MAX;
wthomas626147f2013-09-18 13:12:40 -07001408 nss_runtime_samples.freq_scale[2].frequency = NSS_FREQ_733;
wthomas626147f2013-09-18 13:12:40 -07001409 nss_runtime_samples.freq_scale[2].minimum = NSS_FREQ_733_MIN;
1410 nss_runtime_samples.freq_scale[2].maximum = NSS_FREQ_733_MAX;
wthomas626147f2013-09-18 13:12:40 -07001411 nss_runtime_samples.freq_scale_index = 1;
1412 nss_runtime_samples.freq_scale_ready = 0;
Thomas Wu9681f7e2013-11-06 13:12:57 -08001413 nss_runtime_samples.freq_scale_rate_limit_up = 0;
1414 nss_runtime_samples.freq_scale_rate_limit_down = 0;
wthomas626147f2013-09-18 13:12:40 -07001415 nss_runtime_samples.buffer_index = 0;
1416 nss_runtime_samples.sum = 0;
1417 nss_runtime_samples.sample_count = 0;
1418 nss_runtime_samples.average = 0;
1419 nss_runtime_samples.message_rate_limit = 0;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301420 nss_runtime_samples.initialized = 0;
wthomas626147f2013-09-18 13:12:40 -07001421
Thomas Wu05495be2013-12-19 14:24:24 -08001422 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
1423
wthomas626147f2013-09-18 13:12:40 -07001424 /*
1425 * Initial Workqueue
1426 */
1427 nss_wq = create_workqueue("nss_freq_queue");
1428
1429 /*
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +05301430 * Initialize NSS Bus PM module
1431 */
1432 nss_pm_init();
1433
1434 /*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +05301435 * Register with Bus driver
1436 */
1437 pm_client = nss_pm_client_register(NSS_PM_CLIENT_NETAP);
1438 if (!pm_client) {
1439 nss_warning("Error registering with PM driver");
1440 }
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001441#endif
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +05301442
1443 /*
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +05301444 * Initialize mtu size needed as start
1445 */
1446 nss_top_main.prev_mtu_sz = NSS_GMAC_NORMAL_FRAME_MTU;
1447
1448 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301449 * Register platform_driver
1450 */
1451 return platform_driver_register(&nss_driver);
1452}
1453
1454/*
1455 * nss_cleanup()
1456 * Unregisters nss driver
1457 */
1458static void __exit nss_cleanup(void)
1459{
1460 nss_info("Exit NSS driver");
wthomas442c7972013-08-05 14:28:17 -07001461
1462 if (nss_dev_header)
1463 unregister_sysctl_table(nss_dev_header);
1464
Vijay Dewangan9db18752014-09-15 16:25:01 -07001465 /*
Vijay Dewangan488e5372014-12-29 21:40:11 -08001466 * Unregister n2h specific sysctl
1467 */
1468 nss_n2h_empty_pool_buf_unregister_sysctl();
1469
1470 /*
Vijay Dewangan9db18752014-09-15 16:25:01 -07001471 * Unregister ipv4/6 specific sysctl
1472 */
1473 nss_ipv4_unregister_sysctl();
1474 nss_ipv6_unregister_sysctl();
1475
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001476#if (NSS_DT_SUPPORT == 1)
1477 if(nss_top_main.nss_fpb_base) {
1478 iounmap(nss_top_main.nss_fpb_base);
1479 nss_top_main.nss_fpb_base = 0;
1480 }
1481#endif
1482
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301483 platform_driver_unregister(&nss_driver);
1484}
1485
1486module_init(nss_init);
1487module_exit(nss_cleanup);
1488
1489MODULE_DESCRIPTION("QCA NSS Driver");
1490MODULE_AUTHOR("Qualcomm Atheros Inc");
1491MODULE_LICENSE("Dual BSD/GPL");