blob: b7399bd65a8ec43927ef7dacd6bb1cb32c20838a [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
71/*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053072 * PM client handle
73 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080074#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053075static void *pm_client;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080076#endif
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053077
78/*
wthomas626147f2013-09-18 13:12:40 -070079 * Handler to send NSS messages
80 */
Thomas Wufb6a6842013-10-23 13:14:27 -070081struct clk *nss_core0_clk;
wthomas626147f2013-09-18 13:12:40 -070082
83/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +053084 * Top level nss context structure
85 */
86struct nss_top_instance nss_top_main;
wthomas442c7972013-08-05 14:28:17 -070087struct nss_cmd_buffer nss_cmd_buf;
wthomas626147f2013-09-18 13:12:40 -070088struct nss_runtime_sampling nss_runtime_samples;
89struct workqueue_struct *nss_wq;
90
91/*
92 * Work Queue to handle messages to Kernel
93 */
94nss_work_t *nss_work;
Abhishek Rastogibc74e432013-04-02 10:28:22 +053095
96/*
97 * File local/Static variables/functions
98 */
99
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530100static const struct net_device_ops nss_netdev_ops;
101static const struct ethtool_ops nss_ethtool_ops;
102
103/*
104 * nss_dummy_netdev_setup()
105 * Dummy setup for net_device handler
106 */
107static void nss_dummy_netdev_setup(struct net_device *ndev)
108{
wthomas626147f2013-09-18 13:12:40 -0700109
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530110}
111
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530112/*
113 * nss_handle_irq()
114 * HLOS interrupt handler for nss interrupts
115 */
116static irqreturn_t nss_handle_irq (int irq, void *ctx)
117{
118 struct int_ctx_instance *int_ctx = (struct int_ctx_instance *) ctx;
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530119 struct nss_ctx_instance *nss_ctx = int_ctx->nss_ctx;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530120
121 /*
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530122 * Mask interrupt until our bottom half re-enables it
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530123 */
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530124 nss_hal_disable_interrupt(nss_ctx->nmap, int_ctx->irq,
125 int_ctx->shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530126
127 /*
128 * Schedule tasklet to process interrupt cause
129 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530130 napi_schedule(&int_ctx->napi);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530131 return IRQ_HANDLED;
132}
133
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800134#if (NSS_DT_SUPPORT == 1)
135/*
136 * nss_drv_of_get_pdata()
137 * Retrieve platform data from device node.
138 */
139static struct nss_platform_data *nss_drv_of_get_pdata(struct device_node *np,
140 struct platform_device *pdev)
141{
142 struct nss_platform_data *npd = NULL;
143 struct nss_ctx_instance *nss_ctx = NULL;
144 struct nss_top_instance *nss_top = &nss_top_main;
145 uint32_t val;
146 struct resource res_nphys, res_vphys;
147 int32_t i;
148
149 npd = devm_kzalloc(&pdev->dev, sizeof(struct nss_platform_data), GFP_KERNEL);
150 if (!npd) {
151 return NULL;
152 }
153
154 if (of_property_read_u32(np, "qcom,id", &npd->id)
155 || of_property_read_u32(np, "qcom,rst_addr", &npd->rst_addr)
156 || of_property_read_u32(np, "qcom,load_addr", &npd->load_addr)
157 || of_property_read_u32(np, "qcom,turbo_frequency", &npd->turbo_frequency)
158 || of_property_read_u32(np, "qcom,gmac0_enabled", &npd->gmac_enabled[0])
159 || of_property_read_u32(np, "qcom,gmac1_enabled", &npd->gmac_enabled[1])
160 || of_property_read_u32(np, "qcom,gmac2_enabled", &npd->gmac_enabled[2])
161 || of_property_read_u32(np, "qcom,gmac3_enabled", &npd->gmac_enabled[3])
162 || of_property_read_u32(np, "qcom,num_irq", &npd->num_irq)) {
163 pr_err("%s: error reading critical device node properties\n", np->name);
164 goto out;
165 }
166
167 nss_ctx = &nss_top->nss[npd->id];
168 nss_ctx->id = npd->id;
169
170 if (of_address_to_resource(np, 0, &res_nphys) != 0) {
171 nss_info("%p: nss%d: of_address_to_resource() fail for nphys \n", nss_ctx, nss_ctx->id);
172 goto out;
173 }
174
175 if (of_address_to_resource(np, 1, &res_vphys) != 0) {
176 nss_info("%p: nss%d: of_address_to_resource() fail for vphys \n", nss_ctx, nss_ctx->id);
177 goto out;
178 }
179
180 /*
181 * Save physical addresses
182 */
183 npd->nphys = res_nphys.start;
184 npd->vphys = res_vphys.start;
185
186 npd->nmap = (uint32_t)ioremap_nocache(npd->nphys, resource_size(&res_nphys));
187 if (!npd->nmap) {
188 nss_info("%p: nss%d: ioremap() fail for nphys \n", nss_ctx, nss_ctx->id);
189 goto out;
190 }
191
192 npd->vmap = (uint32_t)ioremap_nocache(npd->vphys, resource_size(&res_vphys));
193 if (!npd->vmap) {
194 nss_info("%p: nss%d: ioremap() fail for vphys \n", nss_ctx, nss_ctx->id);
195 goto out;
196 }
197
198 /*
199 * Clear TCM memory used by this core
200 */
201 for (i = 0; i < resource_size(&res_vphys) ; i += 4) {
202 nss_write_32((uint32_t)npd->vmap, i, 0);
203 }
204
205 /*
206 * Get IRQ numbers
207 */
208 for (val = 0 ; val < npd->num_irq ; val++) {
209 npd->irq[val] = irq_of_parse_and_map(np, val);
210 if (!npd->irq[val]) {
211 nss_info("%p: nss%d: irq_of_parse_and_map() fail for irq %d\n",
212 nss_ctx, nss_ctx->id, val);
213 goto out;
214 }
215 }
216
217 if (of_property_read_u32(np, "qcom,ipv4_enabled", &npd->ipv4_enabled)
218 || of_property_read_u32(np, "qcom,ipv6_enabled", &npd->ipv6_enabled)
219 || of_property_read_u32(np, "qcom,l2switch_enabled", &npd->l2switch_enabled)
220 || of_property_read_u32(np, "qcom,crypto_enabled", &npd->crypto_enabled)
221 || of_property_read_u32(np, "qcom,ipsec_enabled", &npd->ipsec_enabled)
222 || of_property_read_u32(np, "qcom,wlan_enabled", &npd->wlan_enabled)
223 || of_property_read_u32(np, "qcom,tun6rd_enabled", &npd->tun6rd_enabled)
224 || of_property_read_u32(np, "qcom,tunipip6_enabled", &npd->tunipip6_enabled)
225 || of_property_read_u32(np, "qcom,shaping_enabled", &npd->shaping_enabled)) {
226 pr_warn("%s: error reading non-critical device node properties\n", np->name);
227 }
228
229 return npd;
230
231out:
232 if (npd->nmap) {
233 iounmap((void *)npd->nmap);
234 }
235
236 if (npd->vmap) {
237 iounmap((void *)npd->vmap);
238 }
239
240 devm_kfree(&pdev->dev, npd);
241
242 return NULL;
243}
244
245#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530246/*
247 * nss_probe()
248 * HLOS device probe callback
249 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800250#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530251static int __devinit nss_probe(struct platform_device *nss_dev)
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800252#else
253static int nss_probe(struct platform_device *nss_dev)
254#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530255{
256 struct nss_top_instance *nss_top = &nss_top_main;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800257 struct nss_ctx_instance *nss_ctx = NULL;
258 struct nss_platform_data *npd = NULL;
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530259 struct netdev_priv_instance *ndev_priv;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800260#if (NSS_DT_SUPPORT == 1)
261 struct reset_control *rstctl = NULL;
262#endif
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530263 int i, err = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530264
Thomas Wu49008962014-04-02 14:50:47 -0700265 const struct firmware *nss_fw = NULL;
266 int rc = -ENODEV;
267 void __iomem *load_mem;
268
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800269#if (NSS_DT_SUPPORT == 1)
270 struct device_node *np = NULL;
271
272 if (nss_top_main.nss_hal_common_init_done == false) {
273 /*
274 * Perform clock init common to all NSS cores
275 */
276 struct clk *nss_tcm_src = NULL;
277 struct clk *nss_tcm_clk = NULL;
278
279 /*
280 * Attach debug interface to TLMM
281 */
282 nss_write_32((uint32_t)nss_top_main.nss_fpb_base, NSS_REGS_FPB_CSR_CFG_OFFSET, 0x360);
283
284 /*
285 * NSS TCM CLOCK
286 */
287 nss_tcm_src = clk_get(&nss_dev->dev, NSS_TCM_SRC_CLK);
288 if (IS_ERR(nss_tcm_src)) {
289 pr_err("nss-driver: cannot get clock: " NSS_TCM_SRC_CLK);
290 return -EFAULT;
291 }
292
293 clk_set_rate(nss_tcm_src, NSSTCM_FREQ);
294 clk_prepare(nss_tcm_src);
295 clk_enable(nss_tcm_src);
296
297 nss_tcm_clk = clk_get(&nss_dev->dev, NSS_TCM_CLK);
298 if (IS_ERR(nss_tcm_clk)) {
299 pr_err("nss-driver: cannot get clock: " NSS_TCM_CLK);
300 return -EFAULT;
301 }
302
303 clk_prepare(nss_tcm_clk);
304 clk_enable(nss_tcm_clk);
305
306 nss_top_main.nss_hal_common_init_done = true;
307 nss_info("nss_hal_common_reset Done.\n");
308 }
309
310 if (nss_dev->dev.of_node) {
311 /*
312 * Device Tree based init
313 */
314
315 np = of_node_get(nss_dev->dev.of_node);
316 npd = nss_drv_of_get_pdata(np, nss_dev);
317
318 of_node_put(np);
319
320 if (!npd) {
321 return -EFAULT;
322 }
323
324 nss_ctx = &nss_top->nss[npd->id];
325 nss_ctx->id = npd->id;
326 nss_dev->id = nss_ctx->id;
327
328 } else {
329 /*
330 * Platform Device based init
331 */
332
333 npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
334 nss_ctx = &nss_top->nss[nss_dev->id];
335 nss_ctx->id = nss_dev->id;
336 }
337
338#else
339 npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
340 nss_ctx = &nss_top->nss[nss_dev->id];
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530341 nss_ctx->id = nss_dev->id;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800342#endif
343 nss_ctx->nss_top = nss_top;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530344
wthomas442c7972013-08-05 14:28:17 -0700345 nss_info("%p: NSS_DEV_ID %s \n", nss_ctx, dev_name(&nss_dev->dev));
346
Stephen Wang38e89bc2014-11-06 11:34:45 -0800347 /*
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530348 * F/W load from NSS Driver
349 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800350 if (nss_ctx->id == 0) {
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530351 rc = request_firmware(&nss_fw, NETAP0_IMAGE, &(nss_dev->dev));
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800352 } else if (nss_ctx->id == 1) {
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530353 rc = request_firmware(&nss_fw, NETAP1_IMAGE, &(nss_dev->dev));
354 } else {
Samarjeet Banerjee7bce8c52014-05-02 15:32:13 +0530355 nss_warning("%p: Invalid nss dev: %d \n", nss_ctx, nss_dev->id);
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530356 }
357
358 /*
359 * Check if the file read is successful
360 */
361 if (rc) {
362 nss_warning("%p: request_firmware failed with err code: %d", nss_ctx, rc);
363 err = rc;
364 goto err_init_0;
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530365 }
366
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530367 if (nss_fw->size < MIN_IMG_SIZE) {
368 nss_warning("%p: nss firmware is truncated, size:%d", nss_ctx, nss_fw->size);
Thomas Wu49008962014-04-02 14:50:47 -0700369 }
370
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530371 load_mem = ioremap_nocache(npd->load_addr, nss_fw->size);
372 if (load_mem == NULL) {
373 nss_warning("%p: ioremap_nocache failed: %x", nss_ctx, npd->load_addr);
374 release_firmware(nss_fw);
Thomas Wu49008962014-04-02 14:50:47 -0700375 goto err_init_0;
Thomas Wu49008962014-04-02 14:50:47 -0700376 }
377
Saurabh Misra96998db2014-07-10 12:15:48 -0700378 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 +0530379 memcpy_toio(load_mem, nss_fw->data, nss_fw->size);
380 release_firmware(nss_fw);
381 iounmap(load_mem);
382
wthomas442c7972013-08-05 14:28:17 -0700383 /*
384 * Both NSS cores controlled by same regulator, Hook only Once
385 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800386 if (!nss_ctx->id) {
Thomas Wufb6a6842013-10-23 13:14:27 -0700387 nss_core0_clk = clk_get(&nss_dev->dev, "nss_core_clk");
388 if (IS_ERR(nss_core0_clk)) {
wthomas442c7972013-08-05 14:28:17 -0700389
Thomas Wufb6a6842013-10-23 13:14:27 -0700390 err = PTR_ERR(nss_core0_clk);
wthomas442c7972013-08-05 14:28:17 -0700391 nss_info("%p: Regulator %s get failed, err=%d\n", nss_ctx, dev_name(&nss_dev->dev), err);
392 return err;
393
wthomas442c7972013-08-05 14:28:17 -0700394 }
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800395
396 /*
397 * Check if turbo is supported
398 */
399 if (npd->turbo_frequency) {
400 /*
401 * Turbo is supported
402 */
403 printk("nss_driver - Turbo Support %d\n", npd->turbo_frequency);
Thomas Wu0d112192015-04-13 11:37:22 -0700404#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530405 nss_pm_set_turbo();
Thomas Wu0d112192015-04-13 11:37:22 -0700406#endif
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800407 } else {
408 printk("nss_driver - Turbo No Support %d\n", npd->turbo_frequency);
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800409 }
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800410
Thomas Wu7132bd32015-05-07 15:03:06 -0700411 nss_runtime_samples.freq_scale[NSS_FREQ_LOW_SCALE].frequency = 0;
412 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].frequency = 0;
413 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].frequency = 0;
414
415 /*
416 * Load default scales, then query for higher.
417 * If basic set cannot be set, then go to error, and abort
418 * Two set of defaults, 110, 550, 733 or 110, 275 and 550
419 */
420 if (clk_set_rate(nss_core0_clk, NSS_FREQ_110) != 0) {
421 goto err_init_0;
422 }
423
424 nss_runtime_samples.freq_scale[NSS_FREQ_LOW_SCALE].frequency = NSS_FREQ_110;
425 nss_runtime_samples.freq_scale[NSS_FREQ_LOW_SCALE].minimum = NSS_FREQ_110_MIN;
426 nss_runtime_samples.freq_scale[NSS_FREQ_LOW_SCALE].maximum = NSS_FREQ_110_MAX;
427
428 if (npd->turbo_frequency) {
429 /*
430 * Figure out the middle scale
431 */
432 if (clk_set_rate(nss_core0_clk, NSS_FREQ_600) == 0) {
433 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].frequency = NSS_FREQ_600;
434 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].minimum = NSS_FREQ_600_MIN;
435 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].maximum = NSS_FREQ_600_MAX;
436 }else if (clk_set_rate(nss_core0_clk, NSS_FREQ_550) == 0) {
437 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].frequency = NSS_FREQ_550;
438 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].minimum = NSS_FREQ_550_MIN;
439 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].maximum = NSS_FREQ_550_MAX;
440 } else {
441 goto err_init_0;
442 }
443
444 /*
445 * Figure out the max scale
446 */
447 if (clk_set_rate(nss_core0_clk, NSS_FREQ_800) == 0) {
448 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].frequency = NSS_FREQ_800;
449 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].minimum = NSS_FREQ_800_MIN;
450 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].maximum = NSS_FREQ_800_MAX;
451 } else if (clk_set_rate(nss_core0_clk, NSS_FREQ_733) == 0) {
452 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].frequency = NSS_FREQ_733;
453 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].minimum = NSS_FREQ_733_MIN;
454 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].maximum = NSS_FREQ_733_MAX;
455 } else {
456 goto err_init_0;
457 }
458
459 } else {
460 if (clk_set_rate(nss_core0_clk, NSS_FREQ_275) != 0) {
461 goto err_init_0;
462 }
463 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].frequency = NSS_FREQ_275;
464 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].minimum = NSS_FREQ_275_MIN;
465 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].maximum = NSS_FREQ_275_MAX;
466
467 if (clk_set_rate(nss_core0_clk, NSS_FREQ_550) != 0) {
468 goto err_init_0;
469 }
470 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].frequency = NSS_FREQ_550;
471 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].minimum = NSS_FREQ_550_MIN;
472 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].maximum = NSS_FREQ_550_MAX;
473 }
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800474
475 printk("Supported Frequencies - ");
Thomas Wu7132bd32015-05-07 15:03:06 -0700476 for (i = 0; i < NSS_FREQ_MAX_SCALE; i++) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800477 if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_110) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800478 printk("110Mhz ");
479 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_275) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800480 printk("275Mhz ");
481 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_550) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800482 printk("550Mhz ");
483 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_600) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800484 printk("600Mhz ");
485 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_733) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800486 printk("733Mhz ");
487 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_800) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800488 printk("800Mhz ");
489 } else {
Thomas Wu0d72eae2015-03-26 18:02:25 -0700490 printk("Error \nNo Table/Invalid Frequency Found - Loading Old Tables - ");
Thomas Wu7132bd32015-05-07 15:03:06 -0700491 goto err_init_0;
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800492 }
493 }
494 printk("\n");
Thomas Wu9380a7a2015-03-25 13:55:21 -0700495
Thomas Wu7132bd32015-05-07 15:03:06 -0700496 /*
497 * Set default frequency
498 */
499 clk_set_rate(nss_core0_clk, nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].frequency);
Thomas Wu9380a7a2015-03-25 13:55:21 -0700500 clk_prepare(nss_core0_clk);
501 clk_enable(nss_core0_clk);
wthomas442c7972013-08-05 14:28:17 -0700502 }
503
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530504 /*
Sakthi Vignesh Radhakrishnand923e342013-12-09 11:53:03 -0800505 * Get load address of NSS firmware
506 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800507 nss_info("%p: Setting NSS%d Firmware load address to %x\n", nss_ctx, nss_ctx->id, npd->load_addr);
508 nss_top->nss[nss_ctx->id].load = npd->load_addr;
Sakthi Vignesh Radhakrishnand923e342013-12-09 11:53:03 -0800509
510 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530511 * Get virtual and physical memory addresses for nss logical/hardware address maps
512 */
513
514 /*
515 * Virtual address of CSM space
516 */
517 nss_ctx->nmap = npd->nmap;
518 nss_assert(nss_ctx->nmap);
519
520 /*
521 * Physical address of CSM space
522 */
523 nss_ctx->nphys = npd->nphys;
524 nss_assert(nss_ctx->nphys);
525
526 /*
527 * Virtual address of logical registers space
528 */
529 nss_ctx->vmap = npd->vmap;
530 nss_assert(nss_ctx->vmap);
531
532 /*
533 * Physical address of logical registers space
534 */
535 nss_ctx->vphys = npd->vphys;
536 nss_assert(nss_ctx->vphys);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530537 nss_info("%d:ctx=%p, vphys=%x, vmap=%x, nphys=%x, nmap=%x",
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800538 nss_ctx->id, nss_ctx, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530539
540 /*
541 * Register netdevice handlers
542 */
543 nss_ctx->int_ctx[0].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
544 "qca-nss-dev%d", nss_dummy_netdev_setup);
545 if (nss_ctx->int_ctx[0].ndev == NULL) {
546 nss_warning("%p: Could not allocate net_device #0", nss_ctx);
547 err = -ENOMEM;
548 goto err_init_0;
549 }
550
551 nss_ctx->int_ctx[0].ndev->netdev_ops = &nss_netdev_ops;
552 nss_ctx->int_ctx[0].ndev->ethtool_ops = &nss_ethtool_ops;
553 err = register_netdev(nss_ctx->int_ctx[0].ndev);
554 if (err) {
555 nss_warning("%p: Could not register net_device #0", nss_ctx);
556 goto err_init_1;
557 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530558
559 /*
560 * request for IRQs
561 *
562 * WARNING: CPU affinities should be set using OS supported methods
563 */
564 nss_ctx->int_ctx[0].nss_ctx = nss_ctx;
565 nss_ctx->int_ctx[0].shift_factor = 0;
566 nss_ctx->int_ctx[0].irq = npd->irq[0];
567 err = request_irq(npd->irq[0], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[0]);
568 if (err) {
569 nss_warning("%d: IRQ0 request failed", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530570 goto err_init_2;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530571 }
572
573 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530574 * Register NAPI for NSS core interrupt #0
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530575 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530576 ndev_priv = netdev_priv(nss_ctx->int_ctx[0].ndev);
577 ndev_priv->int_ctx = &nss_ctx->int_ctx[0];
578 netif_napi_add(nss_ctx->int_ctx[0].ndev, &nss_ctx->int_ctx[0].napi, nss_core_handle_napi, 64);
579 napi_enable(&nss_ctx->int_ctx[0].napi);
580 nss_ctx->int_ctx[0].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530581
582 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530583 * Check if second interrupt is supported on this nss core
584 */
585 if (npd->num_irq > 1) {
586 nss_info("%d: This NSS core supports two interrupts", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530587
588 /*
589 * Register netdevice handlers
590 */
591 nss_ctx->int_ctx[1].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
592 "qca-nss-dev%d", nss_dummy_netdev_setup);
593 if (nss_ctx->int_ctx[1].ndev == NULL) {
594 nss_warning("%p: Could not allocate net_device #1", nss_ctx);
595 err = -ENOMEM;
596 goto err_init_3;
597 }
598
599 nss_ctx->int_ctx[1].ndev->netdev_ops = &nss_netdev_ops;
600 nss_ctx->int_ctx[1].ndev->ethtool_ops = &nss_ethtool_ops;
601 err = register_netdev(nss_ctx->int_ctx[1].ndev);
602 if (err) {
603 nss_warning("%p: Could not register net_device #1", nss_ctx);
604 goto err_init_4;
605 }
606
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530607 nss_ctx->int_ctx[1].nss_ctx = nss_ctx;
608 nss_ctx->int_ctx[1].shift_factor = 15;
609 nss_ctx->int_ctx[1].irq = npd->irq[1];
610 err = request_irq(npd->irq[1], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[1]);
611 if (err) {
612 nss_warning("%d: IRQ1 request failed for nss", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530613 goto err_init_5;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530614 }
615
616 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530617 * Register NAPI for NSS core interrupt #1
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530618 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530619 ndev_priv = netdev_priv(nss_ctx->int_ctx[1].ndev);
620 ndev_priv->int_ctx = &nss_ctx->int_ctx[1];
621 netif_napi_add(nss_ctx->int_ctx[1].ndev, &nss_ctx->int_ctx[1].napi, nss_core_handle_napi, 64);
622 napi_enable(&nss_ctx->int_ctx[1].napi);
623 nss_ctx->int_ctx[1].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530624 }
625
626 spin_lock_bh(&(nss_top->lock));
627
628 /*
629 * Check functionalities are supported by this NSS core
630 */
Murat Sezgin7a705422014-01-30 16:09:22 -0800631 if (npd->shaping_enabled == NSS_FEATURE_ENABLED) {
632 nss_top->shaping_handler_id = nss_dev->id;
Sakthi Vignesh Radhakrishnanb042f472015-02-23 15:56:51 -0800633 nss_info("%d: NSS shaping is enabled", nss_dev->id);
Murat Sezgin7a705422014-01-30 16:09:22 -0800634 }
635
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530636 if (npd->ipv4_enabled == NSS_FEATURE_ENABLED) {
637 nss_top->ipv4_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530638 nss_ipv4_register_handler();
639 nss_pppoe_register_handler();
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530640 nss_eth_rx_register_handler();
641 nss_n2h_register_handler();
Sol Kavy2783c072014-04-05 12:53:13 -0700642 nss_virt_if_register_handler();
Tushar Mathura3e03052014-04-07 20:17:28 +0530643 nss_lag_register_handler();
Ankit Dhanuka9b430252014-08-12 13:53:41 +0530644 nss_dynamic_interface_register_handler();
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700645 nss_top->capwap_handler_id = nss_dev->id;
646 nss_capwap_init();
Ankit Dhanuka9b430252014-08-12 13:53:41 +0530647
Sol Kavy4013e282014-04-06 15:57:00 -0700648 for (i = 0; i < NSS_MAX_VIRTUAL_INTERFACES; i++) {
649 nss_top->virt_if_handler_id[i] = nss_dev->id;
650 }
Ankit Dhanuka65935322014-10-08 19:20:47 +0530651
652 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR] = nss_dev->id;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530653 }
654
Selin Dag6d9b0c12014-11-04 18:27:21 -0800655 if (npd->ipv4_reasm_enabled == NSS_FEATURE_ENABLED) {
656 nss_top->ipv4_reasm_handler_id = nss_dev->id;
657 nss_ipv4_reasm_register_handler();
658 }
659
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530660 if (npd->ipv6_enabled == NSS_FEATURE_ENABLED) {
661 nss_top->ipv6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530662 nss_ipv6_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530663 }
664
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530665 if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +0530666 nss_top->crypto_enabled = 1;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530667 nss_top->crypto_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530668 nss_crypto_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530669 }
670
671 if (npd->ipsec_enabled == NSS_FEATURE_ENABLED) {
672 nss_top->ipsec_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530673 nss_ipsec_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530674 }
675
676 if (npd->wlan_enabled == NSS_FEATURE_ENABLED) {
677 nss_top->wlan_handler_id = nss_dev->id;
678 }
679
Bharath M Kumar0d87e912013-08-12 18:32:57 +0530680 if (npd->tun6rd_enabled == NSS_FEATURE_ENABLED) {
681 nss_top->tun6rd_handler_id = nss_dev->id;
682 }
683
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530684 if (npd->tunipip6_enabled == NSS_FEATURE_ENABLED) {
685 nss_top->tunipip6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530686 nss_tunipip6_register_handler();
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530687 }
688
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530689 if (npd->gre_redir_enabled == NSS_FEATURE_ENABLED) {
690 nss_top->gre_redir_handler_id = nss_dev->id;
691 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR] = nss_dev->id;
692 nss_gre_redir_register_handler();
Ankit Dhanuka2ae20a82014-08-25 18:04:00 +0530693 nss_sjack_register_handler();
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530694 }
695
Stephen Wang38e89bc2014-11-06 11:34:45 -0800696 /*
697 * Mark data plane enabled so when nss core init done we call register to nss-gmac
698 */
699 for (i = 0 ; i < NSS_MAX_PHYSICAL_INTERFACES ; i ++) {
700 if (npd->gmac_enabled[i] == NSS_FEATURE_ENABLED) {
701 nss_data_plane_set_enabled(i);
702 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530703 }
704
Arunkumar T28b2d742015-06-16 22:15:58 +0530705#if (NSS_FREQ_SCALE_SUPPORT == 1)
Sundarajan Srinivasandedd8e42014-10-06 11:59:34 -0700706 nss_freq_register_handler();
Arunkumar T28b2d742015-06-16 22:15:58 +0530707#endif
Thomas Wuc3e382c2014-10-29 15:35:13 -0700708 nss_lso_rx_register_handler();
709
wthomas626147f2013-09-18 13:12:40 -0700710 nss_top->frequency_handler_id = nss_dev->id;
711
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530712 spin_unlock_bh(&(nss_top->lock));
713
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530714 /*
715 * Initialize decongestion callbacks to NULL
716 */
717 for (i = 0; i< NSS_MAX_CLIENTS; i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530718 nss_ctx->queue_decongestion_callback[i] = 0;
719 nss_ctx->queue_decongestion_ctx[i] = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530720 }
721
722 spin_lock_init(&(nss_ctx->decongest_cb_lock));
723 nss_ctx->magic = NSS_CTX_MAGIC;
724
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530725 nss_info("%p: Reseting NSS core %d now", nss_ctx, nss_ctx->id);
726
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530727 /*
728 * Enable clocks and bring NSS core out of reset
729 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800730#if (NSS_DT_SUPPORT == 1)
731 /*
732 * Remove UBI32 reset clamp
733 */
Stephen Wang83e48752015-03-03 18:41:40 -0800734 rstctl = devm_reset_control_get(&nss_dev->dev, "clkrst_clamp");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800735 if (IS_ERR(rstctl)) {
736 nss_info("%p: Deassert UBI32 reset clamp failed", nss_ctx, nss_ctx->id);
737 err = -EFAULT;
738 goto err_init_5;
739 }
740 reset_control_deassert(rstctl);
741 mdelay(1);
742 reset_control_put(rstctl);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530743
744 /*
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800745 * Remove UBI32 core clamp
746 */
Stephen Wang83e48752015-03-03 18:41:40 -0800747 rstctl = devm_reset_control_get(&nss_dev->dev, "clamp");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800748 if (IS_ERR(rstctl)) {
749 nss_info("%p: Deassert UBI32 core clamp failed", nss_ctx, nss_ctx->id);
750 err = -EFAULT;
751 goto err_init_5;
752 }
753 reset_control_deassert(rstctl);
754 mdelay(1);
755 reset_control_put(rstctl);
756
757 /*
758 * Remove UBI32 AHB reset
759 */
Stephen Wang83e48752015-03-03 18:41:40 -0800760 rstctl = devm_reset_control_get(&nss_dev->dev, "ahb");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800761 if (IS_ERR(rstctl)) {
762 nss_info("%p: Deassert AHB reset failed", nss_ctx, nss_ctx->id);
763 err = -EFAULT;
764 goto err_init_5;
765 }
766 reset_control_deassert(rstctl);
767 mdelay(1);
768 reset_control_put(rstctl);
769
770 /*
771 * Remove UBI32 AXI reset
772 */
Stephen Wang83e48752015-03-03 18:41:40 -0800773 rstctl = devm_reset_control_get(&nss_dev->dev, "axi");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800774 if (IS_ERR(rstctl)) {
775 nss_info("%p: Deassert AXI reset failed", nss_ctx, nss_ctx->id);
776 err = -EFAULT;
777 goto err_init_5;
778 }
779 reset_control_deassert(rstctl);
780 mdelay(1);
781 reset_control_put(rstctl);
782
783 nss_hal_core_reset(nss_ctx->nmap, nss_ctx->load);
784#else
785 nss_hal_core_reset(nss_dev->id, nss_ctx->nmap, nss_ctx->load, nss_top->clk_src);
786#endif
787 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530788 * Enable interrupts for NSS core
789 */
790 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
791 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
792
793 if (npd->num_irq > 1) {
794 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
795 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
796 }
797
Radhakrishna Jigurub7346cf2013-12-16 13:08:43 +0530798 /*
799 * Initialize max buffer size for NSS core
800 */
801 nss_ctx->max_buf_size = NSS_NBUF_PAYLOAD_SIZE;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530802 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 +0530803 goto err_init_0;
804
805err_init_5:
806 unregister_netdev(nss_ctx->int_ctx[1].ndev);
807err_init_4:
808 free_netdev(nss_ctx->int_ctx[1].ndev);
809err_init_3:
810 free_irq(npd->irq[0], &nss_ctx->int_ctx[0]);
811err_init_2:
812 unregister_netdev(nss_ctx->int_ctx[0].ndev);
813err_init_1:
814 free_netdev(nss_ctx->int_ctx[0].ndev);
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800815
816#if (NSS_DT_SUPPORT == 1)
817 if (nss_dev->dev.of_node) {
818 if (npd->nmap) {
819 iounmap((void *)npd->nmap);
820 }
821
822 if (npd->vmap) {
823 iounmap((void *)npd->vmap);
824 }
825 }
826#endif
827
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530828err_init_0:
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800829
830#if (NSS_DT_SUPPORT == 1)
831 if (nss_dev->dev.of_node) {
832 devm_kfree(&nss_dev->dev, npd);
833 }
834
835#endif
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530836 return err;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530837}
838
839/*
840 * nss_remove()
841 * HLOS device remove callback
842 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800843#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530844static int __devexit nss_remove(struct platform_device *nss_dev)
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800845#else
846static int nss_remove(struct platform_device *nss_dev)
847#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530848{
849 struct nss_top_instance *nss_top = &nss_top_main;
850 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
Stephen Wang38e89bc2014-11-06 11:34:45 -0800851 int i;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530852
853 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530854 * Clean-up debugfs
855 */
856 nss_stats_clean();
857
858 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530859 * Disable interrupts and bottom halves in HLOS
860 * Disable interrupts from NSS to HLOS
861 */
862 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
863 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530864
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530865 free_irq(nss_ctx->int_ctx[0].irq, &nss_ctx->int_ctx[0]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530866 unregister_netdev(nss_ctx->int_ctx[0].ndev);
867 free_netdev(nss_ctx->int_ctx[0].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530868
869 /*
870 * Check if second interrupt is supported
871 * If so then clear resources for second interrupt as well
872 */
873 if (nss_ctx->int_ctx[1].irq) {
874 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
875 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530876 free_irq(nss_ctx->int_ctx[1].irq, &nss_ctx->int_ctx[1]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530877 unregister_netdev(nss_ctx->int_ctx[1].ndev);
878 free_netdev(nss_ctx->int_ctx[1].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530879 }
880
Stephen Wang38e89bc2014-11-06 11:34:45 -0800881 /*
882 * nss-drv is exiting, remove from nss-gmac
883 */
884 for (i = 0 ; i < NSS_MAX_PHYSICAL_INTERFACES ; i ++) {
Sundarajan Srinivasan70374842014-11-19 15:22:52 -0800885 if (nss_top->subsys_dp_register[i].ndev) {
Stephen Wang38e89bc2014-11-06 11:34:45 -0800886 nss_data_plane_unregister_from_nss_gmac(i);
887 }
888 }
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800889#if (NSS_DT_SUPPORT == 1)
890 if (nss_dev->dev.of_node) {
891 if (nss_ctx->nmap) {
892 iounmap((void *)nss_ctx->nmap);
893 nss_ctx->nmap = 0;
894 }
895
896 if (nss_ctx->vmap) {
897 iounmap((void *)nss_ctx->vmap);
898 nss_ctx->vmap = 0;
899 }
900 }
901#endif
Stephen Wang38e89bc2014-11-06 11:34:45 -0800902
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530903 nss_info("%p: All resources freed for nss core%d", nss_ctx, nss_dev->id);
904 return 0;
905}
906
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800907#if (NSS_DT_SUPPORT == 1)
908static struct of_device_id nss_dt_ids[] = {
909 { .compatible = "qcom,nss0" },
910 { .compatible = "qcom,nss1" },
911 {},
912};
913MODULE_DEVICE_TABLE(of, nss_dt_ids);
914#endif
915
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530916/*
917 * nss_driver
918 * Platform driver structure for NSS
919 */
920struct platform_driver nss_driver = {
921 .probe = nss_probe,
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800922#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530923 .remove = __devexit_p(nss_remove),
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800924#else
925 .remove = nss_remove,
926#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530927 .driver = {
928 .name = "qca-nss",
929 .owner = THIS_MODULE,
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800930#if (NSS_DT_SUPPORT == 1)
931 .of_match_table = of_match_ptr(nss_dt_ids),
932#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530933 },
934};
935
Arunkumar T28b2d742015-06-16 22:15:58 +0530936#if (NSS_FREQ_SCALE_SUPPORT == 1)
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530937/*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530938 * nss_reset_frequency_stats_samples()
939 * Reset all frequency sampling state when auto scaling is turned off.
940 */
941static void nss_reset_frequency_stats_samples (void)
942{
943 nss_runtime_samples.buffer_index = 0;
944 nss_runtime_samples.sum = 0;
945 nss_runtime_samples.average = 0;
946 nss_runtime_samples.sample_count = 0;
947 nss_runtime_samples.message_rate_limit = 0;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530948 nss_runtime_samples.freq_scale_rate_limit_down = 0;
949}
950
951/*
wthomas626147f2013-09-18 13:12:40 -0700952 ***************************************************************************************************
Thomas Wufb6a6842013-10-23 13:14:27 -0700953 * nss_wq_function() is used to queue up requests to change NSS frequencies.
954 * The function will take care of NSS notices and also control clock.
955 * The auto rate algorithmn will queue up requests or the procfs may also queue up these requests.
wthomas626147f2013-09-18 13:12:40 -0700956 ***************************************************************************************************
957 */
958
959/*
960 * nss_wq_function()
961 * Added to Handle BH requests to kernel
962 */
963void nss_wq_function (struct work_struct *work)
964{
965 nss_work_t *my_work = (nss_work_t *)work;
966
Guojun Jin32a3c6d2015-05-06 12:27:52 -0700967 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 -0700968 if (nss_top_main.nss[NSS_CORE_1].state == NSS_CORE_STATE_INITIALIZED) {
969 nss_freq_change(&nss_top_main.nss[NSS_CORE_1], my_work->frequency, my_work->stats_enable, 0);
970 }
Thomas Wufb6a6842013-10-23 13:14:27 -0700971 clk_set_rate(nss_core0_clk, my_work->frequency);
Guojun Jin32a3c6d2015-05-06 12:27:52 -0700972 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 -0700973 if (nss_top_main.nss[NSS_CORE_1].state == NSS_CORE_STATE_INITIALIZED) {
974 nss_freq_change(&nss_top_main.nss[NSS_CORE_1], my_work->frequency, my_work->stats_enable, 1);
975 }
wthomas626147f2013-09-18 13:12:40 -0700976
Thomas Wu0d112192015-04-13 11:37:22 -0700977#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530978 if(!pm_client) {
979 goto out;
980 }
981
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800982 if (my_work->frequency >= NSS_FREQ_733) {
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530983 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_TURBO);
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800984 } else if (my_work->frequency > NSS_FREQ_110) {
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530985 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_NOMINAL);
986 } else {
987 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_IDLE);
988 }
Thomas Wu0d112192015-04-13 11:37:22 -0700989
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530990out:
Thomas Wu0d112192015-04-13 11:37:22 -0700991#endif
wthomas626147f2013-09-18 13:12:40 -0700992 kfree((void *)work);
993}
994
995/*
wthomas442c7972013-08-05 14:28:17 -0700996 * nss_current_freq_handler()
997 * Handle Userspace Frequency Change Requests
998 */
999static int nss_current_freq_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1000{
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001001 int ret, i;
wthomas626147f2013-09-18 13:12:40 -07001002
1003 BUG_ON(!nss_wq);
wthomas442c7972013-08-05 14:28:17 -07001004
1005 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1006
wthomasd39fa822013-08-22 16:44:23 -07001007 if (!write) {
wthomas626147f2013-09-18 13:12:40 -07001008 printk("Frequency Set to %d\n", nss_cmd_buf.current_freq);
wthomasd39fa822013-08-22 16:44:23 -07001009 return ret;
wthomas442c7972013-08-05 14:28:17 -07001010 }
wthomasd39fa822013-08-22 16:44:23 -07001011
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001012 /*
1013 * Check if frequency exists in frequency Table
1014 */
1015 i = 0;
Thomas Wu7132bd32015-05-07 15:03:06 -07001016 while (i < NSS_FREQ_MAX_SCALE) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001017 if (nss_runtime_samples.freq_scale[i].frequency == nss_cmd_buf.current_freq) {
1018 break;
1019 }
1020 i++;
1021 }
Thomas Wu7132bd32015-05-07 15:03:06 -07001022 if (i == NSS_FREQ_MAX_SCALE) {
Thomas Wufb6a6842013-10-23 13:14:27 -07001023 printk("Frequency not found. Please check Frequency Table\n");
wthomas626147f2013-09-18 13:12:40 -07001024 return ret;
wthomasd39fa822013-08-22 16:44:23 -07001025 }
1026
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001027 /* Turn off Auto Scale */
1028 nss_cmd_buf.auto_scale = 0;
1029 nss_runtime_samples.freq_scale_ready = 0;
1030
Thomas Wu7409bce2014-05-21 10:56:07 -07001031 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
wthomas626147f2013-09-18 13:12:40 -07001032 if (!nss_work) {
1033 nss_info("NSS Freq WQ kmalloc fail");
1034 return ret;
1035 }
1036 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
1037 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301038 nss_work->stats_enable = 0;
1039
1040 /* Ensure we start with a fresh set of samples later */
1041 nss_reset_frequency_stats_samples();
1042
wthomas626147f2013-09-18 13:12:40 -07001043 queue_work(nss_wq, (struct work_struct *)nss_work);
1044
wthomas442c7972013-08-05 14:28:17 -07001045 return ret;
1046}
1047
1048/*
1049 * nss_auto_scale_handler()
1050 * Enables or Disable Auto Scaling
1051 */
1052static int nss_auto_scale_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1053{
1054 int ret;
1055
1056 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1057
wthomas626147f2013-09-18 13:12:40 -07001058 if (!write) {
1059 return ret;
1060 }
1061
Thomas Wufb6a6842013-10-23 13:14:27 -07001062 if (nss_cmd_buf.auto_scale != 1) {
wthomas626147f2013-09-18 13:12:40 -07001063 /*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301064 * Is auto scaling currently enabled? If so, send the command to
1065 * disable stats reporting to NSS
wthomas626147f2013-09-18 13:12:40 -07001066 */
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301067 if (nss_runtime_samples.freq_scale_ready != 0) {
1068 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
Thomas Wu7409bce2014-05-21 10:56:07 -07001069 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301070 if (!nss_work) {
1071 nss_info("NSS Freq WQ kmalloc fail");
1072 return ret;
1073 }
1074 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
1075 nss_work->frequency = nss_cmd_buf.current_freq;
1076 nss_work->stats_enable = 0;
1077 queue_work(nss_wq, (struct work_struct *)nss_work);
1078 nss_runtime_samples.freq_scale_ready = 0;
1079
1080 /*
1081 * The current samples would be stale later when scaling is
1082 * enabled again, hence reset them
1083 */
1084 nss_reset_frequency_stats_samples();
1085 }
Thomas Wufb6a6842013-10-23 13:14:27 -07001086 return ret;
wthomas626147f2013-09-18 13:12:40 -07001087 }
wthomas442c7972013-08-05 14:28:17 -07001088
Thomas Wufb6a6842013-10-23 13:14:27 -07001089 /*
1090 * Auto Scaling is already being done
1091 */
1092 if (nss_runtime_samples.freq_scale_ready == 1) {
1093 return ret;
1094 }
1095
1096 /*
1097 * Setup default values - Middle of Freq Scale Band
1098 */
1099 nss_runtime_samples.freq_scale_index = 1;
1100 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
1101
Thomas Wu7409bce2014-05-21 10:56:07 -07001102 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Thomas Wufb6a6842013-10-23 13:14:27 -07001103 if (!nss_work) {
1104 nss_info("NSS Freq WQ kmalloc fail");
1105 return ret;
1106 }
1107 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
1108 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301109 nss_work->stats_enable = 1;
Thomas Wufb6a6842013-10-23 13:14:27 -07001110 queue_work(nss_wq, (struct work_struct *)nss_work);
1111
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001112 nss_cmd_buf.auto_scale = 0;
Thomas Wufb6a6842013-10-23 13:14:27 -07001113 nss_runtime_samples.freq_scale_ready = 1;
1114
wthomas442c7972013-08-05 14:28:17 -07001115 return ret;
1116}
1117
1118/*
1119 * nss_get_freq_table_handler()
1120 * Display Support Freq and Ex how to Change.
1121 */
Thomas Wu05495be2013-12-19 14:24:24 -08001122static 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 -07001123{
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001124 int ret, i;
wthomas442c7972013-08-05 14:28:17 -07001125
1126 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1127
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001128 printk("Frequency Supported - ");
1129 i = 0;
Thomas Wu7132bd32015-05-07 15:03:06 -07001130 while (i < NSS_FREQ_MAX_SCALE) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001131 printk("%dMhz ", nss_runtime_samples.freq_scale[i].frequency/1000000);
1132 i++;
Thomas Wu0a0a9c92013-11-21 15:28:19 -08001133 }
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001134 printk("\n");
wthomas442c7972013-08-05 14:28:17 -07001135
1136 return ret;
1137}
1138
1139/*
Thomas Wu05495be2013-12-19 14:24:24 -08001140 * nss_get_average_inst_handler()
1141 * Display AVG Inst Per Ms.
1142 */
1143static int nss_get_average_inst_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1144{
1145 int ret;
1146
1147 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1148
1149 if (!ret && !write) {
1150 printk("Current Inst Per Ms %x\n", nss_runtime_samples.average);
1151 }
1152
1153 return ret;
1154}
Arunkumar T28b2d742015-06-16 22:15:58 +05301155#endif
Thomas Wu05495be2013-12-19 14:24:24 -08001156
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001157#if (NSS_FW_DBG_SUPPORT == 1)
Thomas Wu05495be2013-12-19 14:24:24 -08001158/*
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301159 * nss_debug_handler()
1160 * Enable NSS debug output
1161 */
1162static int nss_debug_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1163{
1164 int ret;
1165
1166 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1167 if (!ret) {
1168 if ((write) && (nss_ctl_debug != 0)) {
1169 printk("Enabling NSS SPI Debug\n");
1170 nss_hal_debug_enable();
1171 }
1172 }
1173
1174 return ret;
1175}
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001176#endif
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301177
1178/*
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301179 * nss_rps_handler()
1180 * Enable NSS RPS
1181 */
1182static int nss_rpscfg_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1183{
1184 struct nss_top_instance *nss_top = &nss_top_main;
1185 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
1186 int ret;
1187
1188 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1189 if (!ret) {
1190 if ((write) && (nss_rps_cfg == 1)) {
1191 printk("Enabling NSS RPS\n");
Vijay Dewangan634ce592015-01-07 17:21:09 -08001192
1193 return nss_n2h_rps_cfg(nss_ctx, 1);
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301194 }
1195
1196 if ((write) && (nss_rps_cfg == 0)) {
1197 printk("Runtime disabling of NSS RPS not supported \n");
1198 return ret;
1199 }
1200
1201 if (write) {
1202 printk("Invalid input value.Valid values are 0 and 1 \n");
1203 }
1204
1205 }
1206
1207 return ret;
1208}
1209
1210/*
Thomas Wu52075f42014-02-06 16:32:42 -08001211 * nss_coredump_handler()
1212 * Send Signal To Coredump NSS Cores
1213 */
1214static int nss_coredump_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1215{
Guojun Jin32a3c6d2015-05-06 12:27:52 -07001216 struct nss_ctx_instance *nss_ctx = &nss_top_main.nss[NSS_CORE_0];
Thomas Wu52075f42014-02-06 16:32:42 -08001217 int ret;
1218
1219 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1220 if (!ret) {
1221 if ((write) && (nss_ctl_debug != 0)) {
1222 printk("Coredumping to DDR\n");
1223 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);
1224 }
1225 }
1226
1227 return ret;
1228}
1229
1230/*
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -08001231 * nss_jumbo_mru_handler()
1232 * Sysctl to modify nss_jumbo_mru
1233 */
1234static int nss_jumbo_mru_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1235{
1236 int ret;
1237
1238 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1239 if (ret) {
1240 return ret;
1241 }
1242
1243 if (write) {
1244 nss_core_set_jumbo_mru(nss_jumbo_mru);
1245 nss_info("jumbo_mru set to %d\n", nss_jumbo_mru);
1246 }
1247
1248 return ret;
1249}
1250
1251/* nss_paged_mode_handler()
1252 * Sysctl to modify nss_paged_mode.
1253 */
1254
1255static int nss_paged_mode_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1256{
1257 int ret;
1258
1259 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1260 if (ret) {
1261 return ret;
1262 }
1263
1264 if (write) {
1265 nss_core_set_paged_mode(nss_paged_mode);
1266 nss_info("paged_mode set to %d\n", nss_paged_mode);
1267 }
1268
1269 return ret;
1270}
1271
Arunkumar T28b2d742015-06-16 22:15:58 +05301272#if (NSS_FREQ_SCALE_SUPPORT == 1)
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -08001273/*
wthomas442c7972013-08-05 14:28:17 -07001274 * sysctl-tuning infrastructure.
1275 */
1276static ctl_table nss_freq_table[] = {
1277 {
1278 .procname = "current_freq",
1279 .data = &nss_cmd_buf.current_freq,
1280 .maxlen = sizeof(int),
1281 .mode = 0644,
1282 .proc_handler = &nss_current_freq_handler,
1283 },
1284 {
1285 .procname = "freq_table",
1286 .data = &nss_cmd_buf.max_freq,
1287 .maxlen = sizeof(int),
1288 .mode = 0644,
1289 .proc_handler = &nss_get_freq_table_handler,
1290 },
1291 {
1292 .procname = "auto_scale",
1293 .data = &nss_cmd_buf.auto_scale,
1294 .maxlen = sizeof(int),
1295 .mode = 0644,
1296 .proc_handler = &nss_auto_scale_handler,
1297 },
Thomas Wu05495be2013-12-19 14:24:24 -08001298 {
1299 .procname = "inst_per_sec",
1300 .data = &nss_cmd_buf.average_inst,
1301 .maxlen = sizeof(int),
1302 .mode = 0644,
1303 .proc_handler = &nss_get_average_inst_handler,
1304 },
wthomas442c7972013-08-05 14:28:17 -07001305 { }
1306};
Arunkumar T28b2d742015-06-16 22:15:58 +05301307#endif
wthomas442c7972013-08-05 14:28:17 -07001308
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301309static ctl_table nss_general_table[] = {
1310 {
1311 .procname = "redirect",
1312 .data = &nss_ctl_redirect,
1313 .maxlen = sizeof(int),
1314 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001315 .proc_handler = proc_dointvec,
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301316 },
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001317#if (NSS_FW_DBG_SUPPORT == 1)
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301318 {
1319 .procname = "debug",
1320 .data = &nss_ctl_debug,
1321 .maxlen = sizeof(int),
1322 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001323 .proc_handler = &nss_debug_handler,
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301324 },
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001325#endif
Thomas Wu52075f42014-02-06 16:32:42 -08001326 {
1327 .procname = "coredump",
1328 .data = &nss_cmd_buf.coredump,
1329 .maxlen = sizeof(int),
1330 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001331 .proc_handler = &nss_coredump_handler,
Thomas Wu52075f42014-02-06 16:32:42 -08001332 },
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301333 {
1334 .procname = "rps",
1335 .data = &nss_rps_cfg,
1336 .maxlen = sizeof(int),
1337 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001338 .proc_handler = &nss_rpscfg_handler,
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301339 },
Saurabh Misra96998db2014-07-10 12:15:48 -07001340 {
1341 .procname = "logbuf",
1342 .data = &nss_ctl_logbuf,
1343 .maxlen = sizeof(int),
1344 .mode = 0644,
1345 .proc_handler = &nss_logbuffer_handler,
1346 },
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -08001347 {
1348 .procname = "jumbo_mru",
1349 .data = &nss_jumbo_mru,
1350 .maxlen = sizeof(int),
1351 .mode = 0644,
1352 .proc_handler = &nss_jumbo_mru_handler,
1353 },
1354 {
1355 .procname = "paged_mode",
1356 .data = &nss_paged_mode,
1357 .maxlen = sizeof(int),
1358 .mode = 0644,
1359 .proc_handler = &nss_paged_mode_handler,
1360 },
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301361 { }
1362};
1363
wthomas442c7972013-08-05 14:28:17 -07001364static ctl_table nss_clock_dir[] = {
Arunkumar T28b2d742015-06-16 22:15:58 +05301365#if (NSS_FREQ_SCALE_SUPPORT == 1)
wthomas442c7972013-08-05 14:28:17 -07001366 {
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301367 .procname = "clock",
1368 .mode = 0555,
1369 .child = nss_freq_table,
1370 },
Arunkumar T28b2d742015-06-16 22:15:58 +05301371#endif
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301372 {
1373 .procname = "general",
1374 .mode = 0555,
1375 .child = nss_general_table,
wthomas442c7972013-08-05 14:28:17 -07001376 },
1377 { }
1378};
1379
1380static ctl_table nss_root_dir[] = {
1381 {
1382 .procname = "nss",
1383 .mode = 0555,
1384 .child = nss_clock_dir,
1385 },
1386 { }
1387};
1388
1389static ctl_table nss_root[] = {
1390 {
1391 .procname = "dev",
1392 .mode = 0555,
1393 .child = nss_root_dir,
1394 },
1395 { }
1396};
1397
1398static struct ctl_table_header *nss_dev_header;
1399
1400/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301401 * nss_init()
1402 * Registers nss driver
1403 */
1404static int __init nss_init(void)
1405{
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001406#if (NSS_DT_SUPPORT == 1)
1407 struct device_node *cmn = NULL;
1408 struct resource res_nss_fpb_base;
1409#endif
1410
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301411 nss_info("Init NSS driver");
1412
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001413#if (NSS_DT_SUPPORT == 1)
1414 /*
1415 * Get reference to NSS common device node
1416 */
1417 cmn = of_find_node_by_name(NULL, "nss-common");
1418 if (!cmn) {
1419 nss_info("cannot find nss-common node\n");
1420 return -EFAULT;
1421 }
1422
1423 if (of_address_to_resource(cmn, 0, &res_nss_fpb_base) != 0) {
1424 nss_info("of_address_to_resource() return error for nss_fpb_base\n");
1425 of_node_put(cmn);
1426 return -EFAULT;
1427 }
1428
1429 nss_top_main.nss_fpb_base = ioremap_nocache(res_nss_fpb_base.start,
1430 resource_size(&res_nss_fpb_base));
1431 if (!nss_top_main.nss_fpb_base) {
1432 nss_info("ioremap fail for nss_fpb_base\n");
1433 of_node_put(cmn);
1434 return -EFAULT;
1435 }
1436
1437 nss_top_main.nss_hal_common_init_done = false;
1438
1439 /*
1440 * Release reference to NSS common device node
1441 */
1442 of_node_put(cmn);
1443 cmn = NULL;
1444#else
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301445 /*
1446 * Perform clock init common to all NSS cores
1447 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301448 nss_hal_common_reset(&(nss_top_main.clk_src));
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301449
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001450#endif /* NSS_DT_SUPPORT */
1451
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301452 /*
1453 * Enable spin locks
1454 */
1455 spin_lock_init(&(nss_top_main.lock));
1456 spin_lock_init(&(nss_top_main.stats_lock));
1457
1458 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301459 * Enable NSS statistics
1460 */
1461 nss_stats_init();
1462
1463 /*
wthomas442c7972013-08-05 14:28:17 -07001464 * Register sysctl table.
1465 */
1466 nss_dev_header = register_sysctl_table(nss_root);
1467
1468 /*
Vijay Dewangan9db18752014-09-15 16:25:01 -07001469 * Registering sysctl for ipv4/6 specific config.
1470 */
1471 nss_ipv4_register_sysctl();
1472 nss_ipv6_register_sysctl();
1473
Vijay Dewanganac7efc42015-02-09 16:04:53 -08001474 /*
1475 * Registering sysctl for n2h empty pool buffer.
1476 */
1477 nss_n2h_empty_pool_buf_register_sysctl();
1478
Vijay Dewangan9db18752014-09-15 16:25:01 -07001479 /*
wthomas626147f2013-09-18 13:12:40 -07001480 * Setup Runtime Sample values
1481 */
wthomas626147f2013-09-18 13:12:40 -07001482 nss_runtime_samples.freq_scale_index = 1;
1483 nss_runtime_samples.freq_scale_ready = 0;
Thomas Wu9681f7e2013-11-06 13:12:57 -08001484 nss_runtime_samples.freq_scale_rate_limit_down = 0;
wthomas626147f2013-09-18 13:12:40 -07001485 nss_runtime_samples.buffer_index = 0;
1486 nss_runtime_samples.sum = 0;
1487 nss_runtime_samples.sample_count = 0;
1488 nss_runtime_samples.average = 0;
1489 nss_runtime_samples.message_rate_limit = 0;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301490 nss_runtime_samples.initialized = 0;
wthomas626147f2013-09-18 13:12:40 -07001491
Thomas Wu05495be2013-12-19 14:24:24 -08001492 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
1493
wthomas626147f2013-09-18 13:12:40 -07001494 /*
1495 * Initial Workqueue
1496 */
1497 nss_wq = create_workqueue("nss_freq_queue");
1498
Thomas Wu0d112192015-04-13 11:37:22 -07001499#if (NSS_PM_SUPPORT == 1)
wthomas626147f2013-09-18 13:12:40 -07001500 /*
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +05301501 * Initialize NSS Bus PM module
1502 */
1503 nss_pm_init();
1504
1505 /*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +05301506 * Register with Bus driver
1507 */
1508 pm_client = nss_pm_client_register(NSS_PM_CLIENT_NETAP);
1509 if (!pm_client) {
1510 nss_warning("Error registering with PM driver");
1511 }
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001512#endif
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +05301513
1514 /*
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +05301515 * Initialize mtu size needed as start
1516 */
1517 nss_top_main.prev_mtu_sz = NSS_GMAC_NORMAL_FRAME_MTU;
1518
1519 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301520 * Register platform_driver
1521 */
1522 return platform_driver_register(&nss_driver);
1523}
1524
1525/*
1526 * nss_cleanup()
1527 * Unregisters nss driver
1528 */
1529static void __exit nss_cleanup(void)
1530{
1531 nss_info("Exit NSS driver");
wthomas442c7972013-08-05 14:28:17 -07001532
1533 if (nss_dev_header)
1534 unregister_sysctl_table(nss_dev_header);
1535
Vijay Dewangan9db18752014-09-15 16:25:01 -07001536 /*
Vijay Dewangan488e5372014-12-29 21:40:11 -08001537 * Unregister n2h specific sysctl
1538 */
1539 nss_n2h_empty_pool_buf_unregister_sysctl();
1540
1541 /*
Vijay Dewangan9db18752014-09-15 16:25:01 -07001542 * Unregister ipv4/6 specific sysctl
1543 */
1544 nss_ipv4_unregister_sysctl();
1545 nss_ipv6_unregister_sysctl();
1546
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001547#if (NSS_DT_SUPPORT == 1)
1548 if(nss_top_main.nss_fpb_base) {
1549 iounmap(nss_top_main.nss_fpb_base);
1550 nss_top_main.nss_fpb_base = 0;
1551 }
1552#endif
1553
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301554 platform_driver_unregister(&nss_driver);
1555}
1556
1557module_init(nss_init);
1558module_exit(nss_cleanup);
1559
1560MODULE_DESCRIPTION("QCA NSS Driver");
1561MODULE_AUTHOR("Qualcomm Atheros Inc");
1562MODULE_LICENSE("Dual BSD/GPL");