blob: 92b8fde4b3ac7861376b91e4ee9f2266a729fd0f [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 */
Thomas Wufb6a6842013-10-23 13:14:27 -070085struct clk *nss_core0_clk;
wthomas626147f2013-09-18 13:12:40 -070086
87/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +053088 * Top level nss context structure
89 */
90struct nss_top_instance nss_top_main;
wthomas442c7972013-08-05 14:28:17 -070091struct nss_cmd_buffer nss_cmd_buf;
wthomas626147f2013-09-18 13:12:40 -070092struct nss_runtime_sampling nss_runtime_samples;
93struct workqueue_struct *nss_wq;
94
95/*
96 * Work Queue to handle messages to Kernel
97 */
98nss_work_t *nss_work;
Abhishek Rastogibc74e432013-04-02 10:28:22 +053099
100/*
101 * File local/Static variables/functions
102 */
103
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530104static const struct net_device_ops nss_netdev_ops;
105static const struct ethtool_ops nss_ethtool_ops;
106
107/*
108 * nss_dummy_netdev_setup()
109 * Dummy setup for net_device handler
110 */
111static void nss_dummy_netdev_setup(struct net_device *ndev)
112{
wthomas626147f2013-09-18 13:12:40 -0700113
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530114}
115
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530116/*
117 * nss_handle_irq()
118 * HLOS interrupt handler for nss interrupts
119 */
120static irqreturn_t nss_handle_irq (int irq, void *ctx)
121{
122 struct int_ctx_instance *int_ctx = (struct int_ctx_instance *) ctx;
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530123 struct nss_ctx_instance *nss_ctx = int_ctx->nss_ctx;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530124
125 /*
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530126 * Mask interrupt until our bottom half re-enables it
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530127 */
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530128 nss_hal_disable_interrupt(nss_ctx->nmap, int_ctx->irq,
129 int_ctx->shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530130
131 /*
132 * Schedule tasklet to process interrupt cause
133 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530134 napi_schedule(&int_ctx->napi);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530135 return IRQ_HANDLED;
136}
137
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800138#if (NSS_DT_SUPPORT == 1)
139/*
140 * nss_drv_of_get_pdata()
141 * Retrieve platform data from device node.
142 */
143static struct nss_platform_data *nss_drv_of_get_pdata(struct device_node *np,
144 struct platform_device *pdev)
145{
146 struct nss_platform_data *npd = NULL;
147 struct nss_ctx_instance *nss_ctx = NULL;
148 struct nss_top_instance *nss_top = &nss_top_main;
149 uint32_t val;
150 struct resource res_nphys, res_vphys;
151 int32_t i;
152
153 npd = devm_kzalloc(&pdev->dev, sizeof(struct nss_platform_data), GFP_KERNEL);
154 if (!npd) {
155 return NULL;
156 }
157
158 if (of_property_read_u32(np, "qcom,id", &npd->id)
159 || of_property_read_u32(np, "qcom,rst_addr", &npd->rst_addr)
160 || of_property_read_u32(np, "qcom,load_addr", &npd->load_addr)
161 || of_property_read_u32(np, "qcom,turbo_frequency", &npd->turbo_frequency)
Thomas Wu9380a7a2015-03-25 13:55:21 -0700162 || of_property_read_u32(np, "qcom,low_frequency", &npd->low_frequency)
163 || of_property_read_u32(np, "qcom,mid_frequency", &npd->mid_frequency)
164 || of_property_read_u32(np, "qcom,max_frequency", &npd->max_frequency)
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800165 || of_property_read_u32(np, "qcom,gmac0_enabled", &npd->gmac_enabled[0])
166 || of_property_read_u32(np, "qcom,gmac1_enabled", &npd->gmac_enabled[1])
167 || of_property_read_u32(np, "qcom,gmac2_enabled", &npd->gmac_enabled[2])
168 || of_property_read_u32(np, "qcom,gmac3_enabled", &npd->gmac_enabled[3])
169 || of_property_read_u32(np, "qcom,num_irq", &npd->num_irq)) {
170 pr_err("%s: error reading critical device node properties\n", np->name);
171 goto out;
172 }
173
174 nss_ctx = &nss_top->nss[npd->id];
175 nss_ctx->id = npd->id;
176
177 if (of_address_to_resource(np, 0, &res_nphys) != 0) {
178 nss_info("%p: nss%d: of_address_to_resource() fail for nphys \n", nss_ctx, nss_ctx->id);
179 goto out;
180 }
181
182 if (of_address_to_resource(np, 1, &res_vphys) != 0) {
183 nss_info("%p: nss%d: of_address_to_resource() fail for vphys \n", nss_ctx, nss_ctx->id);
184 goto out;
185 }
186
187 /*
188 * Save physical addresses
189 */
190 npd->nphys = res_nphys.start;
191 npd->vphys = res_vphys.start;
192
193 npd->nmap = (uint32_t)ioremap_nocache(npd->nphys, resource_size(&res_nphys));
194 if (!npd->nmap) {
195 nss_info("%p: nss%d: ioremap() fail for nphys \n", nss_ctx, nss_ctx->id);
196 goto out;
197 }
198
199 npd->vmap = (uint32_t)ioremap_nocache(npd->vphys, resource_size(&res_vphys));
200 if (!npd->vmap) {
201 nss_info("%p: nss%d: ioremap() fail for vphys \n", nss_ctx, nss_ctx->id);
202 goto out;
203 }
204
205 /*
206 * Clear TCM memory used by this core
207 */
208 for (i = 0; i < resource_size(&res_vphys) ; i += 4) {
209 nss_write_32((uint32_t)npd->vmap, i, 0);
210 }
211
212 /*
213 * Get IRQ numbers
214 */
215 for (val = 0 ; val < npd->num_irq ; val++) {
216 npd->irq[val] = irq_of_parse_and_map(np, val);
217 if (!npd->irq[val]) {
218 nss_info("%p: nss%d: irq_of_parse_and_map() fail for irq %d\n",
219 nss_ctx, nss_ctx->id, val);
220 goto out;
221 }
222 }
223
224 if (of_property_read_u32(np, "qcom,ipv4_enabled", &npd->ipv4_enabled)
225 || of_property_read_u32(np, "qcom,ipv6_enabled", &npd->ipv6_enabled)
226 || of_property_read_u32(np, "qcom,l2switch_enabled", &npd->l2switch_enabled)
227 || of_property_read_u32(np, "qcom,crypto_enabled", &npd->crypto_enabled)
228 || of_property_read_u32(np, "qcom,ipsec_enabled", &npd->ipsec_enabled)
229 || of_property_read_u32(np, "qcom,wlan_enabled", &npd->wlan_enabled)
230 || of_property_read_u32(np, "qcom,tun6rd_enabled", &npd->tun6rd_enabled)
231 || of_property_read_u32(np, "qcom,tunipip6_enabled", &npd->tunipip6_enabled)
232 || of_property_read_u32(np, "qcom,shaping_enabled", &npd->shaping_enabled)) {
233 pr_warn("%s: error reading non-critical device node properties\n", np->name);
234 }
235
236 return npd;
237
238out:
239 if (npd->nmap) {
240 iounmap((void *)npd->nmap);
241 }
242
243 if (npd->vmap) {
244 iounmap((void *)npd->vmap);
245 }
246
247 devm_kfree(&pdev->dev, npd);
248
249 return NULL;
250}
251
252#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530253/*
254 * nss_probe()
255 * HLOS device probe callback
256 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800257#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530258static int __devinit nss_probe(struct platform_device *nss_dev)
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800259#else
260static int nss_probe(struct platform_device *nss_dev)
261#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530262{
263 struct nss_top_instance *nss_top = &nss_top_main;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800264 struct nss_ctx_instance *nss_ctx = NULL;
265 struct nss_platform_data *npd = NULL;
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530266 struct netdev_priv_instance *ndev_priv;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800267#if (NSS_DT_SUPPORT == 1)
268 struct reset_control *rstctl = NULL;
269#endif
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530270 int i, err = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530271
Thomas Wu49008962014-04-02 14:50:47 -0700272 const struct firmware *nss_fw = NULL;
273 int rc = -ENODEV;
274 void __iomem *load_mem;
275
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800276#if (NSS_DT_SUPPORT == 1)
277 struct device_node *np = NULL;
278
279 if (nss_top_main.nss_hal_common_init_done == false) {
280 /*
281 * Perform clock init common to all NSS cores
282 */
283 struct clk *nss_tcm_src = NULL;
284 struct clk *nss_tcm_clk = NULL;
285
286 /*
287 * Attach debug interface to TLMM
288 */
289 nss_write_32((uint32_t)nss_top_main.nss_fpb_base, NSS_REGS_FPB_CSR_CFG_OFFSET, 0x360);
290
291 /*
292 * NSS TCM CLOCK
293 */
294 nss_tcm_src = clk_get(&nss_dev->dev, NSS_TCM_SRC_CLK);
295 if (IS_ERR(nss_tcm_src)) {
296 pr_err("nss-driver: cannot get clock: " NSS_TCM_SRC_CLK);
297 return -EFAULT;
298 }
299
300 clk_set_rate(nss_tcm_src, NSSTCM_FREQ);
301 clk_prepare(nss_tcm_src);
302 clk_enable(nss_tcm_src);
303
304 nss_tcm_clk = clk_get(&nss_dev->dev, NSS_TCM_CLK);
305 if (IS_ERR(nss_tcm_clk)) {
306 pr_err("nss-driver: cannot get clock: " NSS_TCM_CLK);
307 return -EFAULT;
308 }
309
310 clk_prepare(nss_tcm_clk);
311 clk_enable(nss_tcm_clk);
312
313 nss_top_main.nss_hal_common_init_done = true;
314 nss_info("nss_hal_common_reset Done.\n");
315 }
316
317 if (nss_dev->dev.of_node) {
318 /*
319 * Device Tree based init
320 */
321
322 np = of_node_get(nss_dev->dev.of_node);
323 npd = nss_drv_of_get_pdata(np, nss_dev);
324
325 of_node_put(np);
326
327 if (!npd) {
328 return -EFAULT;
329 }
330
331 nss_ctx = &nss_top->nss[npd->id];
332 nss_ctx->id = npd->id;
333 nss_dev->id = nss_ctx->id;
334
335 } else {
336 /*
337 * Platform Device based init
338 */
339
340 npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
341 nss_ctx = &nss_top->nss[nss_dev->id];
342 nss_ctx->id = nss_dev->id;
343 }
344
345#else
346 npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
347 nss_ctx = &nss_top->nss[nss_dev->id];
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530348 nss_ctx->id = nss_dev->id;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800349#endif
350 nss_ctx->nss_top = nss_top;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530351
wthomas442c7972013-08-05 14:28:17 -0700352 nss_info("%p: NSS_DEV_ID %s \n", nss_ctx, dev_name(&nss_dev->dev));
353
Stephen Wang38e89bc2014-11-06 11:34:45 -0800354 /*
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530355 * F/W load from NSS Driver
356 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800357 if (nss_ctx->id == 0) {
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530358 rc = request_firmware(&nss_fw, NETAP0_IMAGE, &(nss_dev->dev));
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800359 } else if (nss_ctx->id == 1) {
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530360 rc = request_firmware(&nss_fw, NETAP1_IMAGE, &(nss_dev->dev));
361 } else {
Samarjeet Banerjee7bce8c52014-05-02 15:32:13 +0530362 nss_warning("%p: Invalid nss dev: %d \n", nss_ctx, nss_dev->id);
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530363 }
364
365 /*
366 * Check if the file read is successful
367 */
368 if (rc) {
369 nss_warning("%p: request_firmware failed with err code: %d", nss_ctx, rc);
370 err = rc;
371 goto err_init_0;
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530372 }
373
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530374 if (nss_fw->size < MIN_IMG_SIZE) {
375 nss_warning("%p: nss firmware is truncated, size:%d", nss_ctx, nss_fw->size);
Thomas Wu49008962014-04-02 14:50:47 -0700376 }
377
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530378 load_mem = ioremap_nocache(npd->load_addr, nss_fw->size);
379 if (load_mem == NULL) {
380 nss_warning("%p: ioremap_nocache failed: %x", nss_ctx, npd->load_addr);
381 release_firmware(nss_fw);
Thomas Wu49008962014-04-02 14:50:47 -0700382 goto err_init_0;
Thomas Wu49008962014-04-02 14:50:47 -0700383 }
384
Saurabh Misra96998db2014-07-10 12:15:48 -0700385 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 +0530386 memcpy_toio(load_mem, nss_fw->data, nss_fw->size);
387 release_firmware(nss_fw);
388 iounmap(load_mem);
389
wthomas442c7972013-08-05 14:28:17 -0700390 /*
391 * Both NSS cores controlled by same regulator, Hook only Once
392 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800393 if (!nss_ctx->id) {
Thomas Wufb6a6842013-10-23 13:14:27 -0700394 nss_core0_clk = clk_get(&nss_dev->dev, "nss_core_clk");
395 if (IS_ERR(nss_core0_clk)) {
wthomas442c7972013-08-05 14:28:17 -0700396
Thomas Wufb6a6842013-10-23 13:14:27 -0700397 err = PTR_ERR(nss_core0_clk);
wthomas442c7972013-08-05 14:28:17 -0700398 nss_info("%p: Regulator %s get failed, err=%d\n", nss_ctx, dev_name(&nss_dev->dev), err);
399 return err;
400
wthomas442c7972013-08-05 14:28:17 -0700401 }
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800402
403 /*
404 * Check if turbo is supported
405 */
406 if (npd->turbo_frequency) {
407 /*
408 * Turbo is supported
409 */
410 printk("nss_driver - Turbo Support %d\n", npd->turbo_frequency);
Thomas Wu0d112192015-04-13 11:37:22 -0700411#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530412 nss_pm_set_turbo();
Thomas Wu0d112192015-04-13 11:37:22 -0700413#endif
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800414 } else {
415 printk("nss_driver - Turbo No Support %d\n", npd->turbo_frequency);
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800416 }
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800417
418 nss_runtime_samples.freq_scale[0].frequency = npd->low_frequency;
419 nss_runtime_samples.freq_scale[1].frequency = npd->mid_frequency;
420 nss_runtime_samples.freq_scale[2].frequency = npd->max_frequency;
421
422 printk("Supported Frequencies - ");
423 for (i =0; i < NSS_MAX_CPU_SCALES; i++) {
424 if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_110) {
425 nss_runtime_samples.freq_scale[i].minimum = NSS_FREQ_110_MIN;
426 nss_runtime_samples.freq_scale[i].maximum = NSS_FREQ_110_MAX;
427 printk("110Mhz ");
428 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_275) {
429 nss_runtime_samples.freq_scale[i].minimum = NSS_FREQ_275_MIN;
430 nss_runtime_samples.freq_scale[i].maximum = NSS_FREQ_275_MAX;
431 printk("275Mhz ");
432 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_550) {
433 nss_runtime_samples.freq_scale[i].minimum = NSS_FREQ_550_MIN;
434 nss_runtime_samples.freq_scale[i].maximum = NSS_FREQ_550_MAX;
435 printk("550Mhz ");
436 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_600) {
437 nss_runtime_samples.freq_scale[i].minimum = NSS_FREQ_600_MIN;
438 nss_runtime_samples.freq_scale[i].maximum = NSS_FREQ_600_MAX;
439 printk("600Mhz ");
440 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_733) {
441 nss_runtime_samples.freq_scale[i].minimum = NSS_FREQ_733_MIN;
442 nss_runtime_samples.freq_scale[i].maximum = NSS_FREQ_733_MAX;
443 printk("733Mhz ");
444 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_800) {
445 nss_runtime_samples.freq_scale[i].minimum = NSS_FREQ_800_MIN;
446 nss_runtime_samples.freq_scale[i].maximum = NSS_FREQ_800_MAX;
447 printk("800Mhz ");
448 } else {
Thomas Wu0d72eae2015-03-26 18:02:25 -0700449 printk("Error \nNo Table/Invalid Frequency Found - Loading Old Tables - ");
450
451 nss_runtime_samples.freq_scale[0].frequency = NSS_FREQ_110;
452 nss_runtime_samples.freq_scale[0].minimum = NSS_FREQ_110_MIN;
453 nss_runtime_samples.freq_scale[0].maximum = NSS_FREQ_110_MAX;
454
455 if (npd->turbo_frequency) {
456 nss_runtime_samples.freq_scale[1].frequency = NSS_FREQ_550;
457 nss_runtime_samples.freq_scale[1].minimum = NSS_FREQ_550_MIN;
458 nss_runtime_samples.freq_scale[1].maximum = NSS_FREQ_550_MAX;
459 nss_runtime_samples.freq_scale[2].frequency = NSS_FREQ_733;
460 nss_runtime_samples.freq_scale[2].minimum = NSS_FREQ_733_MIN;
461 nss_runtime_samples.freq_scale[2].maximum = NSS_FREQ_733_MAX;
462 } else {
463 nss_runtime_samples.freq_scale[1].frequency = NSS_FREQ_275;
464 nss_runtime_samples.freq_scale[1].minimum = NSS_FREQ_275_MIN;
465 nss_runtime_samples.freq_scale[1].maximum = NSS_FREQ_275_MAX;
466 nss_runtime_samples.freq_scale[2].frequency = NSS_FREQ_550;
467 nss_runtime_samples.freq_scale[2].minimum = NSS_FREQ_550_MIN;
468 nss_runtime_samples.freq_scale[2].maximum = NSS_FREQ_550_MAX;
469 }
470
471 for (i = 0; i < NSS_MAX_CPU_SCALES; i++) {
472 printk("%dmhz ", nss_runtime_samples.freq_scale[i].frequency / 1000000);
473 }
474
475 break;
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800476 }
477 }
478 printk("\n");
Thomas Wu9380a7a2015-03-25 13:55:21 -0700479
480 clk_set_rate(nss_core0_clk, npd->max_frequency);
481 clk_prepare(nss_core0_clk);
482 clk_enable(nss_core0_clk);
wthomas442c7972013-08-05 14:28:17 -0700483 }
484
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530485 /*
Sakthi Vignesh Radhakrishnand923e342013-12-09 11:53:03 -0800486 * Get load address of NSS firmware
487 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800488 nss_info("%p: Setting NSS%d Firmware load address to %x\n", nss_ctx, nss_ctx->id, npd->load_addr);
489 nss_top->nss[nss_ctx->id].load = npd->load_addr;
Sakthi Vignesh Radhakrishnand923e342013-12-09 11:53:03 -0800490
491 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530492 * Get virtual and physical memory addresses for nss logical/hardware address maps
493 */
494
495 /*
496 * Virtual address of CSM space
497 */
498 nss_ctx->nmap = npd->nmap;
499 nss_assert(nss_ctx->nmap);
500
501 /*
502 * Physical address of CSM space
503 */
504 nss_ctx->nphys = npd->nphys;
505 nss_assert(nss_ctx->nphys);
506
507 /*
508 * Virtual address of logical registers space
509 */
510 nss_ctx->vmap = npd->vmap;
511 nss_assert(nss_ctx->vmap);
512
513 /*
514 * Physical address of logical registers space
515 */
516 nss_ctx->vphys = npd->vphys;
517 nss_assert(nss_ctx->vphys);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530518 nss_info("%d:ctx=%p, vphys=%x, vmap=%x, nphys=%x, nmap=%x",
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800519 nss_ctx->id, nss_ctx, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530520
521 /*
522 * Register netdevice handlers
523 */
524 nss_ctx->int_ctx[0].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
525 "qca-nss-dev%d", nss_dummy_netdev_setup);
526 if (nss_ctx->int_ctx[0].ndev == NULL) {
527 nss_warning("%p: Could not allocate net_device #0", nss_ctx);
528 err = -ENOMEM;
529 goto err_init_0;
530 }
531
532 nss_ctx->int_ctx[0].ndev->netdev_ops = &nss_netdev_ops;
533 nss_ctx->int_ctx[0].ndev->ethtool_ops = &nss_ethtool_ops;
534 err = register_netdev(nss_ctx->int_ctx[0].ndev);
535 if (err) {
536 nss_warning("%p: Could not register net_device #0", nss_ctx);
537 goto err_init_1;
538 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530539
540 /*
541 * request for IRQs
542 *
543 * WARNING: CPU affinities should be set using OS supported methods
544 */
545 nss_ctx->int_ctx[0].nss_ctx = nss_ctx;
546 nss_ctx->int_ctx[0].shift_factor = 0;
547 nss_ctx->int_ctx[0].irq = npd->irq[0];
548 err = request_irq(npd->irq[0], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[0]);
549 if (err) {
550 nss_warning("%d: IRQ0 request failed", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530551 goto err_init_2;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530552 }
553
554 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530555 * Register NAPI for NSS core interrupt #0
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530556 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530557 ndev_priv = netdev_priv(nss_ctx->int_ctx[0].ndev);
558 ndev_priv->int_ctx = &nss_ctx->int_ctx[0];
559 netif_napi_add(nss_ctx->int_ctx[0].ndev, &nss_ctx->int_ctx[0].napi, nss_core_handle_napi, 64);
560 napi_enable(&nss_ctx->int_ctx[0].napi);
561 nss_ctx->int_ctx[0].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530562
563 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530564 * Check if second interrupt is supported on this nss core
565 */
566 if (npd->num_irq > 1) {
567 nss_info("%d: This NSS core supports two interrupts", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530568
569 /*
570 * Register netdevice handlers
571 */
572 nss_ctx->int_ctx[1].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
573 "qca-nss-dev%d", nss_dummy_netdev_setup);
574 if (nss_ctx->int_ctx[1].ndev == NULL) {
575 nss_warning("%p: Could not allocate net_device #1", nss_ctx);
576 err = -ENOMEM;
577 goto err_init_3;
578 }
579
580 nss_ctx->int_ctx[1].ndev->netdev_ops = &nss_netdev_ops;
581 nss_ctx->int_ctx[1].ndev->ethtool_ops = &nss_ethtool_ops;
582 err = register_netdev(nss_ctx->int_ctx[1].ndev);
583 if (err) {
584 nss_warning("%p: Could not register net_device #1", nss_ctx);
585 goto err_init_4;
586 }
587
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530588 nss_ctx->int_ctx[1].nss_ctx = nss_ctx;
589 nss_ctx->int_ctx[1].shift_factor = 15;
590 nss_ctx->int_ctx[1].irq = npd->irq[1];
591 err = request_irq(npd->irq[1], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[1]);
592 if (err) {
593 nss_warning("%d: IRQ1 request failed for nss", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530594 goto err_init_5;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530595 }
596
597 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530598 * Register NAPI for NSS core interrupt #1
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530599 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530600 ndev_priv = netdev_priv(nss_ctx->int_ctx[1].ndev);
601 ndev_priv->int_ctx = &nss_ctx->int_ctx[1];
602 netif_napi_add(nss_ctx->int_ctx[1].ndev, &nss_ctx->int_ctx[1].napi, nss_core_handle_napi, 64);
603 napi_enable(&nss_ctx->int_ctx[1].napi);
604 nss_ctx->int_ctx[1].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530605 }
606
607 spin_lock_bh(&(nss_top->lock));
608
609 /*
610 * Check functionalities are supported by this NSS core
611 */
Murat Sezgin7a705422014-01-30 16:09:22 -0800612 if (npd->shaping_enabled == NSS_FEATURE_ENABLED) {
613 nss_top->shaping_handler_id = nss_dev->id;
Sakthi Vignesh Radhakrishnanb042f472015-02-23 15:56:51 -0800614 nss_info("%d: NSS shaping is enabled", nss_dev->id);
Murat Sezgin7a705422014-01-30 16:09:22 -0800615 }
616
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530617 if (npd->ipv4_enabled == NSS_FEATURE_ENABLED) {
618 nss_top->ipv4_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530619 nss_ipv4_register_handler();
620 nss_pppoe_register_handler();
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530621 nss_eth_rx_register_handler();
622 nss_n2h_register_handler();
Sol Kavy2783c072014-04-05 12:53:13 -0700623 nss_virt_if_register_handler();
Tushar Mathura3e03052014-04-07 20:17:28 +0530624 nss_lag_register_handler();
Ankit Dhanuka9b430252014-08-12 13:53:41 +0530625 nss_dynamic_interface_register_handler();
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700626 nss_top->capwap_handler_id = nss_dev->id;
627 nss_capwap_init();
Ankit Dhanuka9b430252014-08-12 13:53:41 +0530628
Sol Kavy4013e282014-04-06 15:57:00 -0700629 for (i = 0; i < NSS_MAX_VIRTUAL_INTERFACES; i++) {
630 nss_top->virt_if_handler_id[i] = nss_dev->id;
631 }
Ankit Dhanuka65935322014-10-08 19:20:47 +0530632
633 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR] = nss_dev->id;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530634 }
635
Selin Dag6d9b0c12014-11-04 18:27:21 -0800636 if (npd->ipv4_reasm_enabled == NSS_FEATURE_ENABLED) {
637 nss_top->ipv4_reasm_handler_id = nss_dev->id;
638 nss_ipv4_reasm_register_handler();
639 }
640
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530641 if (npd->ipv6_enabled == NSS_FEATURE_ENABLED) {
642 nss_top->ipv6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530643 nss_ipv6_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530644 }
645
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530646 if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +0530647 nss_top->crypto_enabled = 1;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530648 nss_top->crypto_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530649 nss_crypto_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530650 }
651
652 if (npd->ipsec_enabled == NSS_FEATURE_ENABLED) {
653 nss_top->ipsec_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530654 nss_ipsec_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530655 }
656
657 if (npd->wlan_enabled == NSS_FEATURE_ENABLED) {
658 nss_top->wlan_handler_id = nss_dev->id;
659 }
660
Bharath M Kumar0d87e912013-08-12 18:32:57 +0530661 if (npd->tun6rd_enabled == NSS_FEATURE_ENABLED) {
662 nss_top->tun6rd_handler_id = nss_dev->id;
663 }
664
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530665 if (npd->tunipip6_enabled == NSS_FEATURE_ENABLED) {
666 nss_top->tunipip6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530667 nss_tunipip6_register_handler();
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530668 }
669
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530670 if (npd->gre_redir_enabled == NSS_FEATURE_ENABLED) {
671 nss_top->gre_redir_handler_id = nss_dev->id;
672 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR] = nss_dev->id;
673 nss_gre_redir_register_handler();
Ankit Dhanuka2ae20a82014-08-25 18:04:00 +0530674 nss_sjack_register_handler();
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530675 }
676
Stephen Wang38e89bc2014-11-06 11:34:45 -0800677 /*
678 * Mark data plane enabled so when nss core init done we call register to nss-gmac
679 */
680 for (i = 0 ; i < NSS_MAX_PHYSICAL_INTERFACES ; i ++) {
681 if (npd->gmac_enabled[i] == NSS_FEATURE_ENABLED) {
682 nss_data_plane_set_enabled(i);
683 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530684 }
685
Sundarajan Srinivasandedd8e42014-10-06 11:59:34 -0700686 nss_freq_register_handler();
Thomas Wuc3e382c2014-10-29 15:35:13 -0700687 nss_lso_rx_register_handler();
688
wthomas626147f2013-09-18 13:12:40 -0700689 nss_top->frequency_handler_id = nss_dev->id;
690
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530691 spin_unlock_bh(&(nss_top->lock));
692
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530693 /*
694 * Initialize decongestion callbacks to NULL
695 */
696 for (i = 0; i< NSS_MAX_CLIENTS; i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530697 nss_ctx->queue_decongestion_callback[i] = 0;
698 nss_ctx->queue_decongestion_ctx[i] = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530699 }
700
701 spin_lock_init(&(nss_ctx->decongest_cb_lock));
702 nss_ctx->magic = NSS_CTX_MAGIC;
703
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530704 nss_info("%p: Reseting NSS core %d now", nss_ctx, nss_ctx->id);
705
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530706 /*
707 * Enable clocks and bring NSS core out of reset
708 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800709#if (NSS_DT_SUPPORT == 1)
710 /*
711 * Remove UBI32 reset clamp
712 */
Stephen Wang83e48752015-03-03 18:41:40 -0800713 rstctl = devm_reset_control_get(&nss_dev->dev, "clkrst_clamp");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800714 if (IS_ERR(rstctl)) {
715 nss_info("%p: Deassert UBI32 reset clamp failed", nss_ctx, nss_ctx->id);
716 err = -EFAULT;
717 goto err_init_5;
718 }
719 reset_control_deassert(rstctl);
720 mdelay(1);
721 reset_control_put(rstctl);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530722
723 /*
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800724 * Remove UBI32 core clamp
725 */
Stephen Wang83e48752015-03-03 18:41:40 -0800726 rstctl = devm_reset_control_get(&nss_dev->dev, "clamp");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800727 if (IS_ERR(rstctl)) {
728 nss_info("%p: Deassert UBI32 core clamp failed", nss_ctx, nss_ctx->id);
729 err = -EFAULT;
730 goto err_init_5;
731 }
732 reset_control_deassert(rstctl);
733 mdelay(1);
734 reset_control_put(rstctl);
735
736 /*
737 * Remove UBI32 AHB reset
738 */
Stephen Wang83e48752015-03-03 18:41:40 -0800739 rstctl = devm_reset_control_get(&nss_dev->dev, "ahb");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800740 if (IS_ERR(rstctl)) {
741 nss_info("%p: Deassert AHB reset failed", nss_ctx, nss_ctx->id);
742 err = -EFAULT;
743 goto err_init_5;
744 }
745 reset_control_deassert(rstctl);
746 mdelay(1);
747 reset_control_put(rstctl);
748
749 /*
750 * Remove UBI32 AXI reset
751 */
Stephen Wang83e48752015-03-03 18:41:40 -0800752 rstctl = devm_reset_control_get(&nss_dev->dev, "axi");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800753 if (IS_ERR(rstctl)) {
754 nss_info("%p: Deassert AXI reset failed", nss_ctx, nss_ctx->id);
755 err = -EFAULT;
756 goto err_init_5;
757 }
758 reset_control_deassert(rstctl);
759 mdelay(1);
760 reset_control_put(rstctl);
761
762 nss_hal_core_reset(nss_ctx->nmap, nss_ctx->load);
763#else
764 nss_hal_core_reset(nss_dev->id, nss_ctx->nmap, nss_ctx->load, nss_top->clk_src);
765#endif
766 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530767 * Enable interrupts for NSS core
768 */
769 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
770 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
771
772 if (npd->num_irq > 1) {
773 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
774 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
775 }
776
Radhakrishna Jigurub7346cf2013-12-16 13:08:43 +0530777 /*
778 * Initialize max buffer size for NSS core
779 */
780 nss_ctx->max_buf_size = NSS_NBUF_PAYLOAD_SIZE;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530781 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 +0530782 goto err_init_0;
783
784err_init_5:
785 unregister_netdev(nss_ctx->int_ctx[1].ndev);
786err_init_4:
787 free_netdev(nss_ctx->int_ctx[1].ndev);
788err_init_3:
789 free_irq(npd->irq[0], &nss_ctx->int_ctx[0]);
790err_init_2:
791 unregister_netdev(nss_ctx->int_ctx[0].ndev);
792err_init_1:
793 free_netdev(nss_ctx->int_ctx[0].ndev);
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800794
795#if (NSS_DT_SUPPORT == 1)
796 if (nss_dev->dev.of_node) {
797 if (npd->nmap) {
798 iounmap((void *)npd->nmap);
799 }
800
801 if (npd->vmap) {
802 iounmap((void *)npd->vmap);
803 }
804 }
805#endif
806
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530807err_init_0:
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800808
809#if (NSS_DT_SUPPORT == 1)
810 if (nss_dev->dev.of_node) {
811 devm_kfree(&nss_dev->dev, npd);
812 }
813
814#endif
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530815 return err;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530816}
817
818/*
819 * nss_remove()
820 * HLOS device remove callback
821 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800822#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530823static int __devexit nss_remove(struct platform_device *nss_dev)
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800824#else
825static int nss_remove(struct platform_device *nss_dev)
826#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530827{
828 struct nss_top_instance *nss_top = &nss_top_main;
829 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
Stephen Wang38e89bc2014-11-06 11:34:45 -0800830 int i;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530831
832 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530833 * Clean-up debugfs
834 */
835 nss_stats_clean();
836
837 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530838 * Disable interrupts and bottom halves in HLOS
839 * Disable interrupts from NSS to HLOS
840 */
841 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
842 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530843
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530844 free_irq(nss_ctx->int_ctx[0].irq, &nss_ctx->int_ctx[0]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530845 unregister_netdev(nss_ctx->int_ctx[0].ndev);
846 free_netdev(nss_ctx->int_ctx[0].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530847
848 /*
849 * Check if second interrupt is supported
850 * If so then clear resources for second interrupt as well
851 */
852 if (nss_ctx->int_ctx[1].irq) {
853 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
854 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530855 free_irq(nss_ctx->int_ctx[1].irq, &nss_ctx->int_ctx[1]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530856 unregister_netdev(nss_ctx->int_ctx[1].ndev);
857 free_netdev(nss_ctx->int_ctx[1].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530858 }
859
Stephen Wang38e89bc2014-11-06 11:34:45 -0800860 /*
861 * nss-drv is exiting, remove from nss-gmac
862 */
863 for (i = 0 ; i < NSS_MAX_PHYSICAL_INTERFACES ; i ++) {
Sundarajan Srinivasan70374842014-11-19 15:22:52 -0800864 if (nss_top->subsys_dp_register[i].ndev) {
Stephen Wang38e89bc2014-11-06 11:34:45 -0800865 nss_data_plane_unregister_from_nss_gmac(i);
866 }
867 }
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800868#if (NSS_DT_SUPPORT == 1)
869 if (nss_dev->dev.of_node) {
870 if (nss_ctx->nmap) {
871 iounmap((void *)nss_ctx->nmap);
872 nss_ctx->nmap = 0;
873 }
874
875 if (nss_ctx->vmap) {
876 iounmap((void *)nss_ctx->vmap);
877 nss_ctx->vmap = 0;
878 }
879 }
880#endif
Stephen Wang38e89bc2014-11-06 11:34:45 -0800881
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530882 nss_info("%p: All resources freed for nss core%d", nss_ctx, nss_dev->id);
883 return 0;
884}
885
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800886#if (NSS_DT_SUPPORT == 1)
887static struct of_device_id nss_dt_ids[] = {
888 { .compatible = "qcom,nss0" },
889 { .compatible = "qcom,nss1" },
890 {},
891};
892MODULE_DEVICE_TABLE(of, nss_dt_ids);
893#endif
894
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530895/*
896 * nss_driver
897 * Platform driver structure for NSS
898 */
899struct platform_driver nss_driver = {
900 .probe = nss_probe,
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800901#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530902 .remove = __devexit_p(nss_remove),
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800903#else
904 .remove = nss_remove,
905#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530906 .driver = {
907 .name = "qca-nss",
908 .owner = THIS_MODULE,
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800909#if (NSS_DT_SUPPORT == 1)
910 .of_match_table = of_match_ptr(nss_dt_ids),
911#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530912 },
913};
914
915/*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530916 * nss_reset_frequency_stats_samples()
917 * Reset all frequency sampling state when auto scaling is turned off.
918 */
919static void nss_reset_frequency_stats_samples (void)
920{
921 nss_runtime_samples.buffer_index = 0;
922 nss_runtime_samples.sum = 0;
923 nss_runtime_samples.average = 0;
924 nss_runtime_samples.sample_count = 0;
925 nss_runtime_samples.message_rate_limit = 0;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530926 nss_runtime_samples.freq_scale_rate_limit_down = 0;
927}
928
929/*
wthomas626147f2013-09-18 13:12:40 -0700930 ***************************************************************************************************
Thomas Wufb6a6842013-10-23 13:14:27 -0700931 * nss_wq_function() is used to queue up requests to change NSS frequencies.
932 * The function will take care of NSS notices and also control clock.
933 * The auto rate algorithmn will queue up requests or the procfs may also queue up these requests.
wthomas626147f2013-09-18 13:12:40 -0700934 ***************************************************************************************************
935 */
936
937/*
938 * nss_wq_function()
939 * Added to Handle BH requests to kernel
940 */
941void nss_wq_function (struct work_struct *work)
942{
943 nss_work_t *my_work = (nss_work_t *)work;
944
Guojun Jin32a3c6d2015-05-06 12:27:52 -0700945 nss_freq_change(&nss_top_main.nss[NSS_CORE_0], my_work->frequency, my_work->stats_enable, 0);
Guojun Jin9d782812015-05-12 14:01:25 -0700946 if (nss_top_main.nss[NSS_CORE_1].state == NSS_CORE_STATE_INITIALIZED) {
947 nss_freq_change(&nss_top_main.nss[NSS_CORE_1], my_work->frequency, my_work->stats_enable, 0);
948 }
Thomas Wufb6a6842013-10-23 13:14:27 -0700949 clk_set_rate(nss_core0_clk, my_work->frequency);
Guojun Jin32a3c6d2015-05-06 12:27:52 -0700950 nss_freq_change(&nss_top_main.nss[NSS_CORE_0], my_work->frequency, my_work->stats_enable, 1);
Guojun Jin9d782812015-05-12 14:01:25 -0700951 if (nss_top_main.nss[NSS_CORE_1].state == NSS_CORE_STATE_INITIALIZED) {
952 nss_freq_change(&nss_top_main.nss[NSS_CORE_1], my_work->frequency, my_work->stats_enable, 1);
953 }
wthomas626147f2013-09-18 13:12:40 -0700954
Thomas Wu0d112192015-04-13 11:37:22 -0700955#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530956 if(!pm_client) {
957 goto out;
958 }
959
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800960 if (my_work->frequency >= NSS_FREQ_733) {
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530961 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_TURBO);
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800962 } else if (my_work->frequency > NSS_FREQ_110) {
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530963 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_NOMINAL);
964 } else {
965 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_IDLE);
966 }
Thomas Wu0d112192015-04-13 11:37:22 -0700967
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530968out:
Thomas Wu0d112192015-04-13 11:37:22 -0700969#endif
wthomas626147f2013-09-18 13:12:40 -0700970 kfree((void *)work);
971}
972
973/*
wthomas442c7972013-08-05 14:28:17 -0700974 * nss_current_freq_handler()
975 * Handle Userspace Frequency Change Requests
976 */
977static int nss_current_freq_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
978{
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800979 int ret, i;
wthomas626147f2013-09-18 13:12:40 -0700980
981 BUG_ON(!nss_wq);
wthomas442c7972013-08-05 14:28:17 -0700982
983 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
984
wthomasd39fa822013-08-22 16:44:23 -0700985 if (!write) {
wthomas626147f2013-09-18 13:12:40 -0700986 printk("Frequency Set to %d\n", nss_cmd_buf.current_freq);
wthomasd39fa822013-08-22 16:44:23 -0700987 return ret;
wthomas442c7972013-08-05 14:28:17 -0700988 }
wthomasd39fa822013-08-22 16:44:23 -0700989
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800990 /*
991 * Check if frequency exists in frequency Table
992 */
993 i = 0;
994 while (i < NSS_MAX_CPU_SCALES) {
995 if (nss_runtime_samples.freq_scale[i].frequency == nss_cmd_buf.current_freq) {
996 break;
997 }
998 i++;
999 }
1000 if (i == NSS_MAX_CPU_SCALES) {
Thomas Wufb6a6842013-10-23 13:14:27 -07001001 printk("Frequency not found. Please check Frequency Table\n");
wthomas626147f2013-09-18 13:12:40 -07001002 return ret;
wthomasd39fa822013-08-22 16:44:23 -07001003 }
1004
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001005 /* Turn off Auto Scale */
1006 nss_cmd_buf.auto_scale = 0;
1007 nss_runtime_samples.freq_scale_ready = 0;
1008
Thomas Wu7409bce2014-05-21 10:56:07 -07001009 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
wthomas626147f2013-09-18 13:12:40 -07001010 if (!nss_work) {
1011 nss_info("NSS Freq WQ kmalloc fail");
1012 return ret;
1013 }
1014 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
1015 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301016 nss_work->stats_enable = 0;
1017
1018 /* Ensure we start with a fresh set of samples later */
1019 nss_reset_frequency_stats_samples();
1020
wthomas626147f2013-09-18 13:12:40 -07001021 queue_work(nss_wq, (struct work_struct *)nss_work);
1022
wthomas442c7972013-08-05 14:28:17 -07001023 return ret;
1024}
1025
1026/*
1027 * nss_auto_scale_handler()
1028 * Enables or Disable Auto Scaling
1029 */
1030static int nss_auto_scale_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1031{
1032 int ret;
1033
1034 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1035
wthomas626147f2013-09-18 13:12:40 -07001036 if (!write) {
1037 return ret;
1038 }
1039
Thomas Wufb6a6842013-10-23 13:14:27 -07001040 if (nss_cmd_buf.auto_scale != 1) {
wthomas626147f2013-09-18 13:12:40 -07001041 /*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301042 * Is auto scaling currently enabled? If so, send the command to
1043 * disable stats reporting to NSS
wthomas626147f2013-09-18 13:12:40 -07001044 */
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301045 if (nss_runtime_samples.freq_scale_ready != 0) {
1046 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
Thomas Wu7409bce2014-05-21 10:56:07 -07001047 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301048 if (!nss_work) {
1049 nss_info("NSS Freq WQ kmalloc fail");
1050 return ret;
1051 }
1052 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
1053 nss_work->frequency = nss_cmd_buf.current_freq;
1054 nss_work->stats_enable = 0;
1055 queue_work(nss_wq, (struct work_struct *)nss_work);
1056 nss_runtime_samples.freq_scale_ready = 0;
1057
1058 /*
1059 * The current samples would be stale later when scaling is
1060 * enabled again, hence reset them
1061 */
1062 nss_reset_frequency_stats_samples();
1063 }
Thomas Wufb6a6842013-10-23 13:14:27 -07001064 return ret;
wthomas626147f2013-09-18 13:12:40 -07001065 }
wthomas442c7972013-08-05 14:28:17 -07001066
Thomas Wufb6a6842013-10-23 13:14:27 -07001067 /*
1068 * Auto Scaling is already being done
1069 */
1070 if (nss_runtime_samples.freq_scale_ready == 1) {
1071 return ret;
1072 }
1073
1074 /*
1075 * Setup default values - Middle of Freq Scale Band
1076 */
1077 nss_runtime_samples.freq_scale_index = 1;
1078 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
1079
Thomas Wu7409bce2014-05-21 10:56:07 -07001080 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Thomas Wufb6a6842013-10-23 13:14:27 -07001081 if (!nss_work) {
1082 nss_info("NSS Freq WQ kmalloc fail");
1083 return ret;
1084 }
1085 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
1086 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301087 nss_work->stats_enable = 1;
Thomas Wufb6a6842013-10-23 13:14:27 -07001088 queue_work(nss_wq, (struct work_struct *)nss_work);
1089
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001090 nss_cmd_buf.auto_scale = 0;
Thomas Wufb6a6842013-10-23 13:14:27 -07001091 nss_runtime_samples.freq_scale_ready = 1;
1092
wthomas442c7972013-08-05 14:28:17 -07001093 return ret;
1094}
1095
1096/*
1097 * nss_get_freq_table_handler()
1098 * Display Support Freq and Ex how to Change.
1099 */
Thomas Wu05495be2013-12-19 14:24:24 -08001100static 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 -07001101{
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001102 int ret, i;
wthomas442c7972013-08-05 14:28:17 -07001103
1104 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1105
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001106 printk("Frequency Supported - ");
1107 i = 0;
1108 while (i < NSS_MAX_CPU_SCALES) {
1109 printk("%dMhz ", nss_runtime_samples.freq_scale[i].frequency/1000000);
1110 i++;
Thomas Wu0a0a9c92013-11-21 15:28:19 -08001111 }
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001112 printk("\n");
wthomas442c7972013-08-05 14:28:17 -07001113
1114 return ret;
1115}
1116
1117/*
Thomas Wu05495be2013-12-19 14:24:24 -08001118 * nss_get_average_inst_handler()
1119 * Display AVG Inst Per Ms.
1120 */
1121static int nss_get_average_inst_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1122{
1123 int ret;
1124
1125 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1126
1127 if (!ret && !write) {
1128 printk("Current Inst Per Ms %x\n", nss_runtime_samples.average);
1129 }
1130
1131 return ret;
1132}
1133
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001134#if (NSS_FW_DBG_SUPPORT == 1)
Thomas Wu05495be2013-12-19 14:24:24 -08001135/*
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301136 * nss_debug_handler()
1137 * Enable NSS debug output
1138 */
1139static int nss_debug_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1140{
1141 int ret;
1142
1143 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1144 if (!ret) {
1145 if ((write) && (nss_ctl_debug != 0)) {
1146 printk("Enabling NSS SPI Debug\n");
1147 nss_hal_debug_enable();
1148 }
1149 }
1150
1151 return ret;
1152}
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001153#endif
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301154
1155/*
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301156 * nss_rps_handler()
1157 * Enable NSS RPS
1158 */
1159static int nss_rpscfg_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1160{
1161 struct nss_top_instance *nss_top = &nss_top_main;
1162 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
1163 int ret;
1164
1165 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1166 if (!ret) {
1167 if ((write) && (nss_rps_cfg == 1)) {
1168 printk("Enabling NSS RPS\n");
Vijay Dewangan634ce592015-01-07 17:21:09 -08001169
1170 return nss_n2h_rps_cfg(nss_ctx, 1);
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301171 }
1172
1173 if ((write) && (nss_rps_cfg == 0)) {
1174 printk("Runtime disabling of NSS RPS not supported \n");
1175 return ret;
1176 }
1177
1178 if (write) {
1179 printk("Invalid input value.Valid values are 0 and 1 \n");
1180 }
1181
1182 }
1183
1184 return ret;
1185}
1186
1187/*
Thomas Wu52075f42014-02-06 16:32:42 -08001188 * nss_coredump_handler()
1189 * Send Signal To Coredump NSS Cores
1190 */
1191static int nss_coredump_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1192{
Guojun Jin32a3c6d2015-05-06 12:27:52 -07001193 struct nss_ctx_instance *nss_ctx = &nss_top_main.nss[NSS_CORE_0];
Thomas Wu52075f42014-02-06 16:32:42 -08001194 int ret;
1195
1196 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1197 if (!ret) {
1198 if ((write) && (nss_ctl_debug != 0)) {
1199 printk("Coredumping to DDR\n");
1200 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);
1201 }
1202 }
1203
1204 return ret;
1205}
1206
1207/*
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -08001208 * nss_jumbo_mru_handler()
1209 * Sysctl to modify nss_jumbo_mru
1210 */
1211static int nss_jumbo_mru_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1212{
1213 int ret;
1214
1215 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1216 if (ret) {
1217 return ret;
1218 }
1219
1220 if (write) {
1221 nss_core_set_jumbo_mru(nss_jumbo_mru);
1222 nss_info("jumbo_mru set to %d\n", nss_jumbo_mru);
1223 }
1224
1225 return ret;
1226}
1227
1228/* nss_paged_mode_handler()
1229 * Sysctl to modify nss_paged_mode.
1230 */
1231
1232static int nss_paged_mode_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1233{
1234 int ret;
1235
1236 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1237 if (ret) {
1238 return ret;
1239 }
1240
1241 if (write) {
1242 nss_core_set_paged_mode(nss_paged_mode);
1243 nss_info("paged_mode set to %d\n", nss_paged_mode);
1244 }
1245
1246 return ret;
1247}
1248
1249/*
wthomas442c7972013-08-05 14:28:17 -07001250 * sysctl-tuning infrastructure.
1251 */
1252static ctl_table nss_freq_table[] = {
1253 {
1254 .procname = "current_freq",
1255 .data = &nss_cmd_buf.current_freq,
1256 .maxlen = sizeof(int),
1257 .mode = 0644,
1258 .proc_handler = &nss_current_freq_handler,
1259 },
1260 {
1261 .procname = "freq_table",
1262 .data = &nss_cmd_buf.max_freq,
1263 .maxlen = sizeof(int),
1264 .mode = 0644,
1265 .proc_handler = &nss_get_freq_table_handler,
1266 },
1267 {
1268 .procname = "auto_scale",
1269 .data = &nss_cmd_buf.auto_scale,
1270 .maxlen = sizeof(int),
1271 .mode = 0644,
1272 .proc_handler = &nss_auto_scale_handler,
1273 },
Thomas Wu05495be2013-12-19 14:24:24 -08001274 {
1275 .procname = "inst_per_sec",
1276 .data = &nss_cmd_buf.average_inst,
1277 .maxlen = sizeof(int),
1278 .mode = 0644,
1279 .proc_handler = &nss_get_average_inst_handler,
1280 },
wthomas442c7972013-08-05 14:28:17 -07001281 { }
1282};
1283
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301284static ctl_table nss_general_table[] = {
1285 {
1286 .procname = "redirect",
1287 .data = &nss_ctl_redirect,
1288 .maxlen = sizeof(int),
1289 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001290 .proc_handler = proc_dointvec,
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301291 },
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001292#if (NSS_FW_DBG_SUPPORT == 1)
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301293 {
1294 .procname = "debug",
1295 .data = &nss_ctl_debug,
1296 .maxlen = sizeof(int),
1297 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001298 .proc_handler = &nss_debug_handler,
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301299 },
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001300#endif
Thomas Wu52075f42014-02-06 16:32:42 -08001301 {
1302 .procname = "coredump",
1303 .data = &nss_cmd_buf.coredump,
1304 .maxlen = sizeof(int),
1305 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001306 .proc_handler = &nss_coredump_handler,
Thomas Wu52075f42014-02-06 16:32:42 -08001307 },
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301308 {
1309 .procname = "rps",
1310 .data = &nss_rps_cfg,
1311 .maxlen = sizeof(int),
1312 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001313 .proc_handler = &nss_rpscfg_handler,
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301314 },
Saurabh Misra96998db2014-07-10 12:15:48 -07001315 {
1316 .procname = "logbuf",
1317 .data = &nss_ctl_logbuf,
1318 .maxlen = sizeof(int),
1319 .mode = 0644,
1320 .proc_handler = &nss_logbuffer_handler,
1321 },
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -08001322 {
1323 .procname = "jumbo_mru",
1324 .data = &nss_jumbo_mru,
1325 .maxlen = sizeof(int),
1326 .mode = 0644,
1327 .proc_handler = &nss_jumbo_mru_handler,
1328 },
1329 {
1330 .procname = "paged_mode",
1331 .data = &nss_paged_mode,
1332 .maxlen = sizeof(int),
1333 .mode = 0644,
1334 .proc_handler = &nss_paged_mode_handler,
1335 },
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301336 { }
1337};
1338
wthomas442c7972013-08-05 14:28:17 -07001339static ctl_table nss_clock_dir[] = {
1340 {
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301341 .procname = "clock",
1342 .mode = 0555,
1343 .child = nss_freq_table,
1344 },
1345 {
1346 .procname = "general",
1347 .mode = 0555,
1348 .child = nss_general_table,
wthomas442c7972013-08-05 14:28:17 -07001349 },
1350 { }
1351};
1352
1353static ctl_table nss_root_dir[] = {
1354 {
1355 .procname = "nss",
1356 .mode = 0555,
1357 .child = nss_clock_dir,
1358 },
1359 { }
1360};
1361
1362static ctl_table nss_root[] = {
1363 {
1364 .procname = "dev",
1365 .mode = 0555,
1366 .child = nss_root_dir,
1367 },
1368 { }
1369};
1370
1371static struct ctl_table_header *nss_dev_header;
1372
1373/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301374 * nss_init()
1375 * Registers nss driver
1376 */
1377static int __init nss_init(void)
1378{
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001379#if (NSS_DT_SUPPORT == 1)
1380 struct device_node *cmn = NULL;
1381 struct resource res_nss_fpb_base;
1382#endif
1383
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301384 nss_info("Init NSS driver");
1385
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001386#if (NSS_DT_SUPPORT == 1)
1387 /*
1388 * Get reference to NSS common device node
1389 */
1390 cmn = of_find_node_by_name(NULL, "nss-common");
1391 if (!cmn) {
1392 nss_info("cannot find nss-common node\n");
1393 return -EFAULT;
1394 }
1395
1396 if (of_address_to_resource(cmn, 0, &res_nss_fpb_base) != 0) {
1397 nss_info("of_address_to_resource() return error for nss_fpb_base\n");
1398 of_node_put(cmn);
1399 return -EFAULT;
1400 }
1401
1402 nss_top_main.nss_fpb_base = ioremap_nocache(res_nss_fpb_base.start,
1403 resource_size(&res_nss_fpb_base));
1404 if (!nss_top_main.nss_fpb_base) {
1405 nss_info("ioremap fail for nss_fpb_base\n");
1406 of_node_put(cmn);
1407 return -EFAULT;
1408 }
1409
1410 nss_top_main.nss_hal_common_init_done = false;
1411
1412 /*
1413 * Release reference to NSS common device node
1414 */
1415 of_node_put(cmn);
1416 cmn = NULL;
1417#else
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301418 /*
1419 * Perform clock init common to all NSS cores
1420 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301421 nss_hal_common_reset(&(nss_top_main.clk_src));
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301422
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001423#endif /* NSS_DT_SUPPORT */
1424
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301425 /*
1426 * Enable spin locks
1427 */
1428 spin_lock_init(&(nss_top_main.lock));
1429 spin_lock_init(&(nss_top_main.stats_lock));
1430
1431 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301432 * Enable NSS statistics
1433 */
1434 nss_stats_init();
1435
1436 /*
wthomas442c7972013-08-05 14:28:17 -07001437 * Register sysctl table.
1438 */
1439 nss_dev_header = register_sysctl_table(nss_root);
1440
1441 /*
Vijay Dewangan9db18752014-09-15 16:25:01 -07001442 * Registering sysctl for ipv4/6 specific config.
1443 */
1444 nss_ipv4_register_sysctl();
1445 nss_ipv6_register_sysctl();
1446
Vijay Dewanganac7efc42015-02-09 16:04:53 -08001447 /*
1448 * Registering sysctl for n2h empty pool buffer.
1449 */
1450 nss_n2h_empty_pool_buf_register_sysctl();
1451
Sundarajan Srinivasan6e0366b2015-01-20 12:10:42 -08001452#ifdef CONFIG_DEBUG_KMEMLEAK
1453 /*
1454 * If the system is under kmemleak debugging, track our
1455 * skbs by putting them in a list.
1456 */
1457
1458 skb_queue_head_init(&nss_skb_list);
1459#endif
1460
Vijay Dewangan9db18752014-09-15 16:25:01 -07001461 /*
wthomas626147f2013-09-18 13:12:40 -07001462 * Setup Runtime Sample values
1463 */
wthomas626147f2013-09-18 13:12:40 -07001464 nss_runtime_samples.freq_scale_index = 1;
1465 nss_runtime_samples.freq_scale_ready = 0;
Thomas Wu9681f7e2013-11-06 13:12:57 -08001466 nss_runtime_samples.freq_scale_rate_limit_down = 0;
wthomas626147f2013-09-18 13:12:40 -07001467 nss_runtime_samples.buffer_index = 0;
1468 nss_runtime_samples.sum = 0;
1469 nss_runtime_samples.sample_count = 0;
1470 nss_runtime_samples.average = 0;
1471 nss_runtime_samples.message_rate_limit = 0;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301472 nss_runtime_samples.initialized = 0;
wthomas626147f2013-09-18 13:12:40 -07001473
Thomas Wu05495be2013-12-19 14:24:24 -08001474 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
1475
wthomas626147f2013-09-18 13:12:40 -07001476 /*
1477 * Initial Workqueue
1478 */
1479 nss_wq = create_workqueue("nss_freq_queue");
1480
Thomas Wu0d112192015-04-13 11:37:22 -07001481#if (NSS_PM_SUPPORT == 1)
wthomas626147f2013-09-18 13:12:40 -07001482 /*
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +05301483 * Initialize NSS Bus PM module
1484 */
1485 nss_pm_init();
1486
1487 /*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +05301488 * Register with Bus driver
1489 */
1490 pm_client = nss_pm_client_register(NSS_PM_CLIENT_NETAP);
1491 if (!pm_client) {
1492 nss_warning("Error registering with PM driver");
1493 }
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001494#endif
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +05301495
1496 /*
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +05301497 * Initialize mtu size needed as start
1498 */
1499 nss_top_main.prev_mtu_sz = NSS_GMAC_NORMAL_FRAME_MTU;
1500
1501 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301502 * Register platform_driver
1503 */
1504 return platform_driver_register(&nss_driver);
1505}
1506
1507/*
1508 * nss_cleanup()
1509 * Unregisters nss driver
1510 */
1511static void __exit nss_cleanup(void)
1512{
1513 nss_info("Exit NSS driver");
wthomas442c7972013-08-05 14:28:17 -07001514
1515 if (nss_dev_header)
1516 unregister_sysctl_table(nss_dev_header);
1517
Vijay Dewangan9db18752014-09-15 16:25:01 -07001518 /*
Vijay Dewangan488e5372014-12-29 21:40:11 -08001519 * Unregister n2h specific sysctl
1520 */
1521 nss_n2h_empty_pool_buf_unregister_sysctl();
1522
1523 /*
Vijay Dewangan9db18752014-09-15 16:25:01 -07001524 * Unregister ipv4/6 specific sysctl
1525 */
1526 nss_ipv4_unregister_sysctl();
1527 nss_ipv6_unregister_sysctl();
1528
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001529#if (NSS_DT_SUPPORT == 1)
1530 if(nss_top_main.nss_fpb_base) {
1531 iounmap(nss_top_main.nss_fpb_base);
1532 nss_top_main.nss_fpb_base = 0;
1533 }
1534#endif
1535
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301536 platform_driver_unregister(&nss_driver);
1537}
1538
1539module_init(nss_init);
1540module_exit(nss_cleanup);
1541
1542MODULE_DESCRIPTION("QCA NSS Driver");
1543MODULE_AUTHOR("Qualcomm Atheros Inc");
1544MODULE_LICENSE("Dual BSD/GPL");