blob: b7c6bc29b8774d3c1690998e1fa9edf74241932f [file] [log] [blame]
Radhakrishna Jiguru1c9b2252013-08-27 23:57:48 +05301/*
2 **************************************************************************
Vijay Dewangan488e5372014-12-29 21:40:11 -08003 * Copyright (c) 2013 - 2015, The Linux Foundation. All rights reserved.
Radhakrishna Jiguru1c9b2252013-08-27 23:57:48 +05304 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 **************************************************************************
15 */
Abhishek Rastogibc74e432013-04-02 10:28:22 +053016
17/*
18 * nss_init.c
19 * NSS init APIs
20 *
21 */
Abhishek Rastogibc74e432013-04-02 10:28:22 +053022#include "nss_core.h"
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080023#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053024#include "nss_pm.h"
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080025#endif
Abhishek Rastogi9da47472014-03-18 19:46:15 +053026#include "nss_tx_rx_common.h"
Stephen Wang38e89bc2014-11-06 11:34:45 -080027#include "nss_data_plane.h"
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +053028
Abhishek Rastogibc74e432013-04-02 10:28:22 +053029#include <nss_hal.h>
Thomas Wufb6a6842013-10-23 13:14:27 -070030#include <nss_clocks.h>
Abhishek Rastogibc74e432013-04-02 10:28:22 +053031
32#include <linux/module.h>
33#include <linux/platform_device.h>
wthomas442c7972013-08-05 14:28:17 -070034#include <linux/proc_fs.h>
35#include <linux/device.h>
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080036
37#if (NSS_DT_SUPPORT == 1)
38#include <linux/of.h>
39#include <linux/of_net.h>
40#include <linux/of_irq.h>
41#include <linux/of_address.h>
42#include <linux/reset.h>
43#else
Abhishek Rastogibc74e432013-04-02 10:28:22 +053044#include <mach/msm_nss.h>
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080045#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +053046
wthomas442c7972013-08-05 14:28:17 -070047#include <linux/sysctl.h>
48#include <linux/regulator/consumer.h>
Thomas Wufb6a6842013-10-23 13:14:27 -070049#include <linux/clk.h>
Thomas Wu49008962014-04-02 14:50:47 -070050#include <linux/firmware.h>
51
Saurabh Misra09dddeb2014-09-30 16:38:07 -070052#include "nss_capwap.h"
53
Thomas Wu49008962014-04-02 14:50:47 -070054/*
55 * Macros
56 */
57#define MIN_IMG_SIZE 64*1024
Radha krishna Simha Jiguru6e74d572014-05-13 11:30:20 +053058#define NETAP0_IMAGE "qca-nss0.bin"
59#define NETAP1_IMAGE "qca-nss1.bin"
wthomas442c7972013-08-05 14:28:17 -070060
Abhishek Rastogibc74e432013-04-02 10:28:22 +053061/*
62 * Global declarations
63 */
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +053064int nss_ctl_redirect __read_mostly = 0;
Sakthi Vignesh Radhakrishnanaf39aad2014-03-31 11:31:03 -070065int nss_ctl_debug __read_mostly = 0;
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +053066int nss_rps_cfg __read_mostly = 0;
Saurabh Misra96998db2014-07-10 12:15:48 -070067int nss_ctl_logbuf __read_mostly = 0;
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -080068int nss_jumbo_mru __read_mostly = 0;
69int nss_paged_mode __read_mostly = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +053070
Sundarajan Srinivasan6e0366b2015-01-20 12:10:42 -080071#ifdef CONFIG_DEBUG_KMEMLEAK
72extern struct sk_buff_head nss_skb_list;
73#endif
74
Abhishek Rastogibc74e432013-04-02 10:28:22 +053075/*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053076 * PM client handle
77 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080078#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053079static void *pm_client;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -080080#endif
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +053081
82/*
wthomas626147f2013-09-18 13:12:40 -070083 * Handler to send NSS messages
84 */
85void *nss_freq_change_context;
Thomas Wufb6a6842013-10-23 13:14:27 -070086struct clk *nss_core0_clk;
wthomas626147f2013-09-18 13:12:40 -070087
88/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +053089 * Top level nss context structure
90 */
91struct nss_top_instance nss_top_main;
wthomas442c7972013-08-05 14:28:17 -070092struct nss_cmd_buffer nss_cmd_buf;
wthomas626147f2013-09-18 13:12:40 -070093struct nss_runtime_sampling nss_runtime_samples;
94struct workqueue_struct *nss_wq;
95
96/*
97 * Work Queue to handle messages to Kernel
98 */
99nss_work_t *nss_work;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530100
101/*
102 * File local/Static variables/functions
103 */
104
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530105static const struct net_device_ops nss_netdev_ops;
106static const struct ethtool_ops nss_ethtool_ops;
107
108/*
109 * nss_dummy_netdev_setup()
110 * Dummy setup for net_device handler
111 */
112static void nss_dummy_netdev_setup(struct net_device *ndev)
113{
wthomas626147f2013-09-18 13:12:40 -0700114
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530115}
116
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530117/*
118 * nss_handle_irq()
119 * HLOS interrupt handler for nss interrupts
120 */
121static irqreturn_t nss_handle_irq (int irq, void *ctx)
122{
123 struct int_ctx_instance *int_ctx = (struct int_ctx_instance *) ctx;
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530124 struct nss_ctx_instance *nss_ctx = int_ctx->nss_ctx;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530125
126 /*
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530127 * Mask interrupt until our bottom half re-enables it
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530128 */
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530129 nss_hal_disable_interrupt(nss_ctx->nmap, int_ctx->irq,
130 int_ctx->shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530131
132 /*
133 * Schedule tasklet to process interrupt cause
134 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530135 napi_schedule(&int_ctx->napi);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530136 return IRQ_HANDLED;
137}
138
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800139#if (NSS_DT_SUPPORT == 1)
140/*
141 * nss_drv_of_get_pdata()
142 * Retrieve platform data from device node.
143 */
144static struct nss_platform_data *nss_drv_of_get_pdata(struct device_node *np,
145 struct platform_device *pdev)
146{
147 struct nss_platform_data *npd = NULL;
148 struct nss_ctx_instance *nss_ctx = NULL;
149 struct nss_top_instance *nss_top = &nss_top_main;
150 uint32_t val;
151 struct resource res_nphys, res_vphys;
152 int32_t i;
153
154 npd = devm_kzalloc(&pdev->dev, sizeof(struct nss_platform_data), GFP_KERNEL);
155 if (!npd) {
156 return NULL;
157 }
158
159 if (of_property_read_u32(np, "qcom,id", &npd->id)
160 || of_property_read_u32(np, "qcom,rst_addr", &npd->rst_addr)
161 || of_property_read_u32(np, "qcom,load_addr", &npd->load_addr)
162 || of_property_read_u32(np, "qcom,turbo_frequency", &npd->turbo_frequency)
163 || of_property_read_u32(np, "qcom,gmac0_enabled", &npd->gmac_enabled[0])
164 || of_property_read_u32(np, "qcom,gmac1_enabled", &npd->gmac_enabled[1])
165 || of_property_read_u32(np, "qcom,gmac2_enabled", &npd->gmac_enabled[2])
166 || of_property_read_u32(np, "qcom,gmac3_enabled", &npd->gmac_enabled[3])
167 || of_property_read_u32(np, "qcom,num_irq", &npd->num_irq)) {
168 pr_err("%s: error reading critical device node properties\n", np->name);
169 goto out;
170 }
171
172 nss_ctx = &nss_top->nss[npd->id];
173 nss_ctx->id = npd->id;
174
175 if (of_address_to_resource(np, 0, &res_nphys) != 0) {
176 nss_info("%p: nss%d: of_address_to_resource() fail for nphys \n", nss_ctx, nss_ctx->id);
177 goto out;
178 }
179
180 if (of_address_to_resource(np, 1, &res_vphys) != 0) {
181 nss_info("%p: nss%d: of_address_to_resource() fail for vphys \n", nss_ctx, nss_ctx->id);
182 goto out;
183 }
184
185 /*
186 * Save physical addresses
187 */
188 npd->nphys = res_nphys.start;
189 npd->vphys = res_vphys.start;
190
191 npd->nmap = (uint32_t)ioremap_nocache(npd->nphys, resource_size(&res_nphys));
192 if (!npd->nmap) {
193 nss_info("%p: nss%d: ioremap() fail for nphys \n", nss_ctx, nss_ctx->id);
194 goto out;
195 }
196
197 npd->vmap = (uint32_t)ioremap_nocache(npd->vphys, resource_size(&res_vphys));
198 if (!npd->vmap) {
199 nss_info("%p: nss%d: ioremap() fail for vphys \n", nss_ctx, nss_ctx->id);
200 goto out;
201 }
202
203 /*
204 * Clear TCM memory used by this core
205 */
206 for (i = 0; i < resource_size(&res_vphys) ; i += 4) {
207 nss_write_32((uint32_t)npd->vmap, i, 0);
208 }
209
210 /*
211 * Get IRQ numbers
212 */
213 for (val = 0 ; val < npd->num_irq ; val++) {
214 npd->irq[val] = irq_of_parse_and_map(np, val);
215 if (!npd->irq[val]) {
216 nss_info("%p: nss%d: irq_of_parse_and_map() fail for irq %d\n",
217 nss_ctx, nss_ctx->id, val);
218 goto out;
219 }
220 }
221
222 if (of_property_read_u32(np, "qcom,ipv4_enabled", &npd->ipv4_enabled)
223 || of_property_read_u32(np, "qcom,ipv6_enabled", &npd->ipv6_enabled)
224 || of_property_read_u32(np, "qcom,l2switch_enabled", &npd->l2switch_enabled)
225 || of_property_read_u32(np, "qcom,crypto_enabled", &npd->crypto_enabled)
226 || of_property_read_u32(np, "qcom,ipsec_enabled", &npd->ipsec_enabled)
227 || of_property_read_u32(np, "qcom,wlan_enabled", &npd->wlan_enabled)
228 || of_property_read_u32(np, "qcom,tun6rd_enabled", &npd->tun6rd_enabled)
229 || of_property_read_u32(np, "qcom,tunipip6_enabled", &npd->tunipip6_enabled)
230 || of_property_read_u32(np, "qcom,shaping_enabled", &npd->shaping_enabled)) {
231 pr_warn("%s: error reading non-critical device node properties\n", np->name);
232 }
233
234 return npd;
235
236out:
237 if (npd->nmap) {
238 iounmap((void *)npd->nmap);
239 }
240
241 if (npd->vmap) {
242 iounmap((void *)npd->vmap);
243 }
244
245 devm_kfree(&pdev->dev, npd);
246
247 return NULL;
248}
249
250#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530251/*
252 * nss_probe()
253 * HLOS device probe callback
254 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800255#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530256static int __devinit nss_probe(struct platform_device *nss_dev)
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800257#else
258static int nss_probe(struct platform_device *nss_dev)
259#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530260{
261 struct nss_top_instance *nss_top = &nss_top_main;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800262 struct nss_ctx_instance *nss_ctx = NULL;
263 struct nss_platform_data *npd = NULL;
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530264 struct netdev_priv_instance *ndev_priv;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800265#if (NSS_DT_SUPPORT == 1)
266 struct reset_control *rstctl = NULL;
267#endif
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530268 int i, err = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530269
Thomas Wu49008962014-04-02 14:50:47 -0700270 const struct firmware *nss_fw = NULL;
271 int rc = -ENODEV;
272 void __iomem *load_mem;
273
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800274#if (NSS_DT_SUPPORT == 1)
275 struct device_node *np = NULL;
276
277 if (nss_top_main.nss_hal_common_init_done == false) {
278 /*
279 * Perform clock init common to all NSS cores
280 */
281 struct clk *nss_tcm_src = NULL;
282 struct clk *nss_tcm_clk = NULL;
283
284 /*
285 * Attach debug interface to TLMM
286 */
287 nss_write_32((uint32_t)nss_top_main.nss_fpb_base, NSS_REGS_FPB_CSR_CFG_OFFSET, 0x360);
288
289 /*
290 * NSS TCM CLOCK
291 */
292 nss_tcm_src = clk_get(&nss_dev->dev, NSS_TCM_SRC_CLK);
293 if (IS_ERR(nss_tcm_src)) {
294 pr_err("nss-driver: cannot get clock: " NSS_TCM_SRC_CLK);
295 return -EFAULT;
296 }
297
298 clk_set_rate(nss_tcm_src, NSSTCM_FREQ);
299 clk_prepare(nss_tcm_src);
300 clk_enable(nss_tcm_src);
301
302 nss_tcm_clk = clk_get(&nss_dev->dev, NSS_TCM_CLK);
303 if (IS_ERR(nss_tcm_clk)) {
304 pr_err("nss-driver: cannot get clock: " NSS_TCM_CLK);
305 return -EFAULT;
306 }
307
308 clk_prepare(nss_tcm_clk);
309 clk_enable(nss_tcm_clk);
310
311 nss_top_main.nss_hal_common_init_done = true;
312 nss_info("nss_hal_common_reset Done.\n");
313 }
314
315 if (nss_dev->dev.of_node) {
316 /*
317 * Device Tree based init
318 */
319
320 np = of_node_get(nss_dev->dev.of_node);
321 npd = nss_drv_of_get_pdata(np, nss_dev);
322
323 of_node_put(np);
324
325 if (!npd) {
326 return -EFAULT;
327 }
328
329 nss_ctx = &nss_top->nss[npd->id];
330 nss_ctx->id = npd->id;
331 nss_dev->id = nss_ctx->id;
332
333 } else {
334 /*
335 * Platform Device based init
336 */
337
338 npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
339 nss_ctx = &nss_top->nss[nss_dev->id];
340 nss_ctx->id = nss_dev->id;
341 }
342
343#else
344 npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
345 nss_ctx = &nss_top->nss[nss_dev->id];
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530346 nss_ctx->id = nss_dev->id;
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800347#endif
348 nss_ctx->nss_top = nss_top;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530349
wthomas442c7972013-08-05 14:28:17 -0700350 nss_info("%p: NSS_DEV_ID %s \n", nss_ctx, dev_name(&nss_dev->dev));
351
Stephen Wang38e89bc2014-11-06 11:34:45 -0800352 /*
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530353 * F/W load from NSS Driver
354 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800355 if (nss_ctx->id == 0) {
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530356 rc = request_firmware(&nss_fw, NETAP0_IMAGE, &(nss_dev->dev));
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800357 } else if (nss_ctx->id == 1) {
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530358 rc = request_firmware(&nss_fw, NETAP1_IMAGE, &(nss_dev->dev));
359 } else {
Samarjeet Banerjee7bce8c52014-05-02 15:32:13 +0530360 nss_warning("%p: Invalid nss dev: %d \n", nss_ctx, nss_dev->id);
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530361 }
362
363 /*
364 * Check if the file read is successful
365 */
366 if (rc) {
367 nss_warning("%p: request_firmware failed with err code: %d", nss_ctx, rc);
368 err = rc;
369 goto err_init_0;
Radha krishna Simha Jiguru27bff9a2014-03-18 16:31:34 +0530370 }
371
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530372 if (nss_fw->size < MIN_IMG_SIZE) {
373 nss_warning("%p: nss firmware is truncated, size:%d", nss_ctx, nss_fw->size);
Thomas Wu49008962014-04-02 14:50:47 -0700374 }
375
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530376 load_mem = ioremap_nocache(npd->load_addr, nss_fw->size);
377 if (load_mem == NULL) {
378 nss_warning("%p: ioremap_nocache failed: %x", nss_ctx, npd->load_addr);
379 release_firmware(nss_fw);
Thomas Wu49008962014-04-02 14:50:47 -0700380 goto err_init_0;
Thomas Wu49008962014-04-02 14:50:47 -0700381 }
382
Saurabh Misra96998db2014-07-10 12:15:48 -0700383 printk("nss_driver - fw of size %u bytes copied to load addr: %x, nss_id : %d\n", nss_fw->size, npd->load_addr, nss_dev->id);
Radha krishna Simha Jiguru9ed88c62014-04-11 12:12:33 +0530384 memcpy_toio(load_mem, nss_fw->data, nss_fw->size);
385 release_firmware(nss_fw);
386 iounmap(load_mem);
387
wthomas442c7972013-08-05 14:28:17 -0700388 /*
389 * Both NSS cores controlled by same regulator, Hook only Once
390 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800391 if (!nss_ctx->id) {
Thomas Wufb6a6842013-10-23 13:14:27 -0700392 nss_core0_clk = clk_get(&nss_dev->dev, "nss_core_clk");
393 if (IS_ERR(nss_core0_clk)) {
wthomas442c7972013-08-05 14:28:17 -0700394
Thomas Wufb6a6842013-10-23 13:14:27 -0700395 err = PTR_ERR(nss_core0_clk);
wthomas442c7972013-08-05 14:28:17 -0700396 nss_info("%p: Regulator %s get failed, err=%d\n", nss_ctx, dev_name(&nss_dev->dev), err);
397 return err;
398
wthomas442c7972013-08-05 14:28:17 -0700399 }
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800400
401 /*
402 * Check if turbo is supported
403 */
404 if (npd->turbo_frequency) {
405 /*
406 * Turbo is supported
407 */
408 printk("nss_driver - Turbo Support %d\n", npd->turbo_frequency);
Thomas Wu0d112192015-04-13 11:37:22 -0700409#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijayf9b5a272014-01-22 14:24:10 +0530410 nss_pm_set_turbo();
Thomas Wu0d112192015-04-13 11:37:22 -0700411#endif
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800412 } else {
413 printk("nss_driver - Turbo No Support %d\n", npd->turbo_frequency);
Thomas Wu0a0a9c92013-11-21 15:28:19 -0800414 }
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800415
Thomas Wu7132bd32015-05-07 15:03:06 -0700416 nss_runtime_samples.freq_scale[NSS_FREQ_LOW_SCALE].frequency = 0;
417 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].frequency = 0;
418 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].frequency = 0;
419
420 /*
421 * Load default scales, then query for higher.
422 * If basic set cannot be set, then go to error, and abort
423 * Two set of defaults, 110, 550, 733 or 110, 275 and 550
424 */
425 if (clk_set_rate(nss_core0_clk, NSS_FREQ_110) != 0) {
426 goto err_init_0;
427 }
428
429 nss_runtime_samples.freq_scale[NSS_FREQ_LOW_SCALE].frequency = NSS_FREQ_110;
430 nss_runtime_samples.freq_scale[NSS_FREQ_LOW_SCALE].minimum = NSS_FREQ_110_MIN;
431 nss_runtime_samples.freq_scale[NSS_FREQ_LOW_SCALE].maximum = NSS_FREQ_110_MAX;
432
433 if (npd->turbo_frequency) {
434 /*
435 * Figure out the middle scale
436 */
437 if (clk_set_rate(nss_core0_clk, NSS_FREQ_600) == 0) {
438 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].frequency = NSS_FREQ_600;
439 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].minimum = NSS_FREQ_600_MIN;
440 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].maximum = NSS_FREQ_600_MAX;
441 }else if (clk_set_rate(nss_core0_clk, NSS_FREQ_550) == 0) {
442 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].frequency = NSS_FREQ_550;
443 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].minimum = NSS_FREQ_550_MIN;
444 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].maximum = NSS_FREQ_550_MAX;
445 } else {
446 goto err_init_0;
447 }
448
449 /*
450 * Figure out the max scale
451 */
452 if (clk_set_rate(nss_core0_clk, NSS_FREQ_800) == 0) {
453 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].frequency = NSS_FREQ_800;
454 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].minimum = NSS_FREQ_800_MIN;
455 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].maximum = NSS_FREQ_800_MAX;
456 } else if (clk_set_rate(nss_core0_clk, NSS_FREQ_733) == 0) {
457 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].frequency = NSS_FREQ_733;
458 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].minimum = NSS_FREQ_733_MIN;
459 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].maximum = NSS_FREQ_733_MAX;
460 } else {
461 goto err_init_0;
462 }
463
464 } else {
465 if (clk_set_rate(nss_core0_clk, NSS_FREQ_275) != 0) {
466 goto err_init_0;
467 }
468 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].frequency = NSS_FREQ_275;
469 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].minimum = NSS_FREQ_275_MIN;
470 nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].maximum = NSS_FREQ_275_MAX;
471
472 if (clk_set_rate(nss_core0_clk, NSS_FREQ_550) != 0) {
473 goto err_init_0;
474 }
475 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].frequency = NSS_FREQ_550;
476 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].minimum = NSS_FREQ_550_MIN;
477 nss_runtime_samples.freq_scale[NSS_FREQ_HIGH_SCALE].maximum = NSS_FREQ_550_MAX;
478 }
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800479
480 printk("Supported Frequencies - ");
Thomas Wu7132bd32015-05-07 15:03:06 -0700481 for (i = 0; i < NSS_FREQ_MAX_SCALE; i++) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800482 if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_110) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800483 printk("110Mhz ");
484 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_275) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800485 printk("275Mhz ");
486 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_550) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800487 printk("550Mhz ");
488 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_600) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800489 printk("600Mhz ");
490 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_733) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800491 printk("733Mhz ");
492 } else if (nss_runtime_samples.freq_scale[i].frequency == NSS_FREQ_800) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800493 printk("800Mhz ");
494 } else {
Thomas Wu0d72eae2015-03-26 18:02:25 -0700495 printk("Error \nNo Table/Invalid Frequency Found - Loading Old Tables - ");
Thomas Wu7132bd32015-05-07 15:03:06 -0700496 goto err_init_0;
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800497 }
498 }
499 printk("\n");
Thomas Wu9380a7a2015-03-25 13:55:21 -0700500
Thomas Wu7132bd32015-05-07 15:03:06 -0700501 /*
502 * Set default frequency
503 */
504 clk_set_rate(nss_core0_clk, nss_runtime_samples.freq_scale[NSS_FREQ_MID_SCALE].frequency);
Thomas Wu9380a7a2015-03-25 13:55:21 -0700505 clk_prepare(nss_core0_clk);
506 clk_enable(nss_core0_clk);
wthomas442c7972013-08-05 14:28:17 -0700507 }
508
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530509 /*
Sakthi Vignesh Radhakrishnand923e342013-12-09 11:53:03 -0800510 * Get load address of NSS firmware
511 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800512 nss_info("%p: Setting NSS%d Firmware load address to %x\n", nss_ctx, nss_ctx->id, npd->load_addr);
513 nss_top->nss[nss_ctx->id].load = npd->load_addr;
Sakthi Vignesh Radhakrishnand923e342013-12-09 11:53:03 -0800514
515 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530516 * Get virtual and physical memory addresses for nss logical/hardware address maps
517 */
518
519 /*
520 * Virtual address of CSM space
521 */
522 nss_ctx->nmap = npd->nmap;
523 nss_assert(nss_ctx->nmap);
524
525 /*
526 * Physical address of CSM space
527 */
528 nss_ctx->nphys = npd->nphys;
529 nss_assert(nss_ctx->nphys);
530
531 /*
532 * Virtual address of logical registers space
533 */
534 nss_ctx->vmap = npd->vmap;
535 nss_assert(nss_ctx->vmap);
536
537 /*
538 * Physical address of logical registers space
539 */
540 nss_ctx->vphys = npd->vphys;
541 nss_assert(nss_ctx->vphys);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530542 nss_info("%d:ctx=%p, vphys=%x, vmap=%x, nphys=%x, nmap=%x",
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800543 nss_ctx->id, nss_ctx, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530544
545 /*
546 * Register netdevice handlers
547 */
548 nss_ctx->int_ctx[0].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
549 "qca-nss-dev%d", nss_dummy_netdev_setup);
550 if (nss_ctx->int_ctx[0].ndev == NULL) {
551 nss_warning("%p: Could not allocate net_device #0", nss_ctx);
552 err = -ENOMEM;
553 goto err_init_0;
554 }
555
556 nss_ctx->int_ctx[0].ndev->netdev_ops = &nss_netdev_ops;
557 nss_ctx->int_ctx[0].ndev->ethtool_ops = &nss_ethtool_ops;
558 err = register_netdev(nss_ctx->int_ctx[0].ndev);
559 if (err) {
560 nss_warning("%p: Could not register net_device #0", nss_ctx);
561 goto err_init_1;
562 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530563
564 /*
565 * request for IRQs
566 *
567 * WARNING: CPU affinities should be set using OS supported methods
568 */
569 nss_ctx->int_ctx[0].nss_ctx = nss_ctx;
570 nss_ctx->int_ctx[0].shift_factor = 0;
571 nss_ctx->int_ctx[0].irq = npd->irq[0];
572 err = request_irq(npd->irq[0], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[0]);
573 if (err) {
574 nss_warning("%d: IRQ0 request failed", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530575 goto err_init_2;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530576 }
577
578 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530579 * Register NAPI for NSS core interrupt #0
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530580 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530581 ndev_priv = netdev_priv(nss_ctx->int_ctx[0].ndev);
582 ndev_priv->int_ctx = &nss_ctx->int_ctx[0];
583 netif_napi_add(nss_ctx->int_ctx[0].ndev, &nss_ctx->int_ctx[0].napi, nss_core_handle_napi, 64);
584 napi_enable(&nss_ctx->int_ctx[0].napi);
585 nss_ctx->int_ctx[0].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530586
587 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530588 * Check if second interrupt is supported on this nss core
589 */
590 if (npd->num_irq > 1) {
591 nss_info("%d: This NSS core supports two interrupts", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530592
593 /*
594 * Register netdevice handlers
595 */
596 nss_ctx->int_ctx[1].ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
597 "qca-nss-dev%d", nss_dummy_netdev_setup);
598 if (nss_ctx->int_ctx[1].ndev == NULL) {
599 nss_warning("%p: Could not allocate net_device #1", nss_ctx);
600 err = -ENOMEM;
601 goto err_init_3;
602 }
603
604 nss_ctx->int_ctx[1].ndev->netdev_ops = &nss_netdev_ops;
605 nss_ctx->int_ctx[1].ndev->ethtool_ops = &nss_ethtool_ops;
606 err = register_netdev(nss_ctx->int_ctx[1].ndev);
607 if (err) {
608 nss_warning("%p: Could not register net_device #1", nss_ctx);
609 goto err_init_4;
610 }
611
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530612 nss_ctx->int_ctx[1].nss_ctx = nss_ctx;
613 nss_ctx->int_ctx[1].shift_factor = 15;
614 nss_ctx->int_ctx[1].irq = npd->irq[1];
615 err = request_irq(npd->irq[1], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[1]);
616 if (err) {
617 nss_warning("%d: IRQ1 request failed for nss", nss_dev->id);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530618 goto err_init_5;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530619 }
620
621 /*
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530622 * Register NAPI for NSS core interrupt #1
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530623 */
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530624 ndev_priv = netdev_priv(nss_ctx->int_ctx[1].ndev);
625 ndev_priv->int_ctx = &nss_ctx->int_ctx[1];
626 netif_napi_add(nss_ctx->int_ctx[1].ndev, &nss_ctx->int_ctx[1].napi, nss_core_handle_napi, 64);
627 napi_enable(&nss_ctx->int_ctx[1].napi);
628 nss_ctx->int_ctx[1].napi_active = true;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530629 }
630
631 spin_lock_bh(&(nss_top->lock));
632
633 /*
634 * Check functionalities are supported by this NSS core
635 */
Murat Sezgin7a705422014-01-30 16:09:22 -0800636 if (npd->shaping_enabled == NSS_FEATURE_ENABLED) {
637 nss_top->shaping_handler_id = nss_dev->id;
Sakthi Vignesh Radhakrishnanb042f472015-02-23 15:56:51 -0800638 nss_info("%d: NSS shaping is enabled", nss_dev->id);
Murat Sezgin7a705422014-01-30 16:09:22 -0800639 }
640
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530641 if (npd->ipv4_enabled == NSS_FEATURE_ENABLED) {
642 nss_top->ipv4_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530643 nss_ipv4_register_handler();
644 nss_pppoe_register_handler();
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530645 nss_eth_rx_register_handler();
646 nss_n2h_register_handler();
Sol Kavy2783c072014-04-05 12:53:13 -0700647 nss_virt_if_register_handler();
Tushar Mathura3e03052014-04-07 20:17:28 +0530648 nss_lag_register_handler();
Ankit Dhanuka9b430252014-08-12 13:53:41 +0530649 nss_dynamic_interface_register_handler();
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700650 nss_top->capwap_handler_id = nss_dev->id;
651 nss_capwap_init();
Ankit Dhanuka9b430252014-08-12 13:53:41 +0530652
Sol Kavy4013e282014-04-06 15:57:00 -0700653 for (i = 0; i < NSS_MAX_VIRTUAL_INTERFACES; i++) {
654 nss_top->virt_if_handler_id[i] = nss_dev->id;
655 }
Ankit Dhanuka65935322014-10-08 19:20:47 +0530656
657 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR] = nss_dev->id;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530658 }
659
Selin Dag6d9b0c12014-11-04 18:27:21 -0800660 if (npd->ipv4_reasm_enabled == NSS_FEATURE_ENABLED) {
661 nss_top->ipv4_reasm_handler_id = nss_dev->id;
662 nss_ipv4_reasm_register_handler();
663 }
664
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530665 if (npd->ipv6_enabled == NSS_FEATURE_ENABLED) {
666 nss_top->ipv6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530667 nss_ipv6_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530668 }
669
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530670 if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +0530671 nss_top->crypto_enabled = 1;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530672 nss_top->crypto_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530673 nss_crypto_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530674 }
675
676 if (npd->ipsec_enabled == NSS_FEATURE_ENABLED) {
677 nss_top->ipsec_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530678 nss_ipsec_register_handler();
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530679 }
680
681 if (npd->wlan_enabled == NSS_FEATURE_ENABLED) {
682 nss_top->wlan_handler_id = nss_dev->id;
683 }
684
Bharath M Kumar0d87e912013-08-12 18:32:57 +0530685 if (npd->tun6rd_enabled == NSS_FEATURE_ENABLED) {
686 nss_top->tun6rd_handler_id = nss_dev->id;
687 }
688
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530689 if (npd->tunipip6_enabled == NSS_FEATURE_ENABLED) {
690 nss_top->tunipip6_handler_id = nss_dev->id;
Abhishek Rastogi9da47472014-03-18 19:46:15 +0530691 nss_tunipip6_register_handler();
Bharath M Kumar614bbf82013-08-31 20:18:44 +0530692 }
693
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530694 if (npd->gre_redir_enabled == NSS_FEATURE_ENABLED) {
695 nss_top->gre_redir_handler_id = nss_dev->id;
696 nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR] = nss_dev->id;
697 nss_gre_redir_register_handler();
Ankit Dhanuka2ae20a82014-08-25 18:04:00 +0530698 nss_sjack_register_handler();
Ankit Dhanuka607508d2014-08-21 20:20:34 +0530699 }
700
Stephen Wang38e89bc2014-11-06 11:34:45 -0800701 /*
702 * Mark data plane enabled so when nss core init done we call register to nss-gmac
703 */
704 for (i = 0 ; i < NSS_MAX_PHYSICAL_INTERFACES ; i ++) {
705 if (npd->gmac_enabled[i] == NSS_FEATURE_ENABLED) {
706 nss_data_plane_set_enabled(i);
707 }
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530708 }
709
Sundarajan Srinivasandedd8e42014-10-06 11:59:34 -0700710 nss_freq_register_handler();
Thomas Wuc3e382c2014-10-29 15:35:13 -0700711 nss_lso_rx_register_handler();
712
wthomas626147f2013-09-18 13:12:40 -0700713 nss_top->frequency_handler_id = nss_dev->id;
714
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530715 spin_unlock_bh(&(nss_top->lock));
716
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530717 /*
718 * Initialize decongestion callbacks to NULL
719 */
720 for (i = 0; i< NSS_MAX_CLIENTS; i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530721 nss_ctx->queue_decongestion_callback[i] = 0;
722 nss_ctx->queue_decongestion_ctx[i] = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530723 }
724
725 spin_lock_init(&(nss_ctx->decongest_cb_lock));
726 nss_ctx->magic = NSS_CTX_MAGIC;
727
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530728 nss_info("%p: Reseting NSS core %d now", nss_ctx, nss_ctx->id);
729
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530730 /*
731 * Enable clocks and bring NSS core out of reset
732 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800733#if (NSS_DT_SUPPORT == 1)
734 /*
735 * Remove UBI32 reset clamp
736 */
Stephen Wang83e48752015-03-03 18:41:40 -0800737 rstctl = devm_reset_control_get(&nss_dev->dev, "clkrst_clamp");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800738 if (IS_ERR(rstctl)) {
739 nss_info("%p: Deassert UBI32 reset clamp failed", nss_ctx, nss_ctx->id);
740 err = -EFAULT;
741 goto err_init_5;
742 }
743 reset_control_deassert(rstctl);
744 mdelay(1);
745 reset_control_put(rstctl);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530746
747 /*
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800748 * Remove UBI32 core clamp
749 */
Stephen Wang83e48752015-03-03 18:41:40 -0800750 rstctl = devm_reset_control_get(&nss_dev->dev, "clamp");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800751 if (IS_ERR(rstctl)) {
752 nss_info("%p: Deassert UBI32 core clamp failed", nss_ctx, nss_ctx->id);
753 err = -EFAULT;
754 goto err_init_5;
755 }
756 reset_control_deassert(rstctl);
757 mdelay(1);
758 reset_control_put(rstctl);
759
760 /*
761 * Remove UBI32 AHB reset
762 */
Stephen Wang83e48752015-03-03 18:41:40 -0800763 rstctl = devm_reset_control_get(&nss_dev->dev, "ahb");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800764 if (IS_ERR(rstctl)) {
765 nss_info("%p: Deassert AHB reset failed", nss_ctx, nss_ctx->id);
766 err = -EFAULT;
767 goto err_init_5;
768 }
769 reset_control_deassert(rstctl);
770 mdelay(1);
771 reset_control_put(rstctl);
772
773 /*
774 * Remove UBI32 AXI reset
775 */
Stephen Wang83e48752015-03-03 18:41:40 -0800776 rstctl = devm_reset_control_get(&nss_dev->dev, "axi");
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800777 if (IS_ERR(rstctl)) {
778 nss_info("%p: Deassert AXI reset failed", nss_ctx, nss_ctx->id);
779 err = -EFAULT;
780 goto err_init_5;
781 }
782 reset_control_deassert(rstctl);
783 mdelay(1);
784 reset_control_put(rstctl);
785
786 nss_hal_core_reset(nss_ctx->nmap, nss_ctx->load);
787#else
788 nss_hal_core_reset(nss_dev->id, nss_ctx->nmap, nss_ctx->load, nss_top->clk_src);
789#endif
790 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530791 * Enable interrupts for NSS core
792 */
793 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
794 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
795
796 if (npd->num_irq > 1) {
797 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
798 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
799 }
800
Radhakrishna Jigurub7346cf2013-12-16 13:08:43 +0530801 /*
802 * Initialize max buffer size for NSS core
803 */
804 nss_ctx->max_buf_size = NSS_NBUF_PAYLOAD_SIZE;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530805 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 +0530806 goto err_init_0;
807
808err_init_5:
809 unregister_netdev(nss_ctx->int_ctx[1].ndev);
810err_init_4:
811 free_netdev(nss_ctx->int_ctx[1].ndev);
812err_init_3:
813 free_irq(npd->irq[0], &nss_ctx->int_ctx[0]);
814err_init_2:
815 unregister_netdev(nss_ctx->int_ctx[0].ndev);
816err_init_1:
817 free_netdev(nss_ctx->int_ctx[0].ndev);
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800818
819#if (NSS_DT_SUPPORT == 1)
820 if (nss_dev->dev.of_node) {
821 if (npd->nmap) {
822 iounmap((void *)npd->nmap);
823 }
824
825 if (npd->vmap) {
826 iounmap((void *)npd->vmap);
827 }
828 }
829#endif
830
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530831err_init_0:
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800832
833#if (NSS_DT_SUPPORT == 1)
834 if (nss_dev->dev.of_node) {
835 devm_kfree(&nss_dev->dev, npd);
836 }
837
838#endif
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530839 return err;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530840}
841
842/*
843 * nss_remove()
844 * HLOS device remove callback
845 */
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800846#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530847static int __devexit nss_remove(struct platform_device *nss_dev)
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800848#else
849static int nss_remove(struct platform_device *nss_dev)
850#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530851{
852 struct nss_top_instance *nss_top = &nss_top_main;
853 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
Stephen Wang38e89bc2014-11-06 11:34:45 -0800854 int i;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530855
856 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530857 * Clean-up debugfs
858 */
859 nss_stats_clean();
860
861 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530862 * Disable interrupts and bottom halves in HLOS
863 * Disable interrupts from NSS to HLOS
864 */
865 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
866 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530867
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530868 free_irq(nss_ctx->int_ctx[0].irq, &nss_ctx->int_ctx[0]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530869 unregister_netdev(nss_ctx->int_ctx[0].ndev);
870 free_netdev(nss_ctx->int_ctx[0].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530871
872 /*
873 * Check if second interrupt is supported
874 * If so then clear resources for second interrupt as well
875 */
876 if (nss_ctx->int_ctx[1].irq) {
877 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
878 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530879 free_irq(nss_ctx->int_ctx[1].irq, &nss_ctx->int_ctx[1]);
Abhishek Rastogi271eee72013-07-29 21:08:36 +0530880 unregister_netdev(nss_ctx->int_ctx[1].ndev);
881 free_netdev(nss_ctx->int_ctx[1].ndev);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530882 }
883
Stephen Wang38e89bc2014-11-06 11:34:45 -0800884 /*
885 * nss-drv is exiting, remove from nss-gmac
886 */
887 for (i = 0 ; i < NSS_MAX_PHYSICAL_INTERFACES ; i ++) {
Sundarajan Srinivasan70374842014-11-19 15:22:52 -0800888 if (nss_top->subsys_dp_register[i].ndev) {
Stephen Wang38e89bc2014-11-06 11:34:45 -0800889 nss_data_plane_unregister_from_nss_gmac(i);
890 }
891 }
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800892#if (NSS_DT_SUPPORT == 1)
893 if (nss_dev->dev.of_node) {
894 if (nss_ctx->nmap) {
895 iounmap((void *)nss_ctx->nmap);
896 nss_ctx->nmap = 0;
897 }
898
899 if (nss_ctx->vmap) {
900 iounmap((void *)nss_ctx->vmap);
901 nss_ctx->vmap = 0;
902 }
903 }
904#endif
Stephen Wang38e89bc2014-11-06 11:34:45 -0800905
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530906 nss_info("%p: All resources freed for nss core%d", nss_ctx, nss_dev->id);
907 return 0;
908}
909
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800910#if (NSS_DT_SUPPORT == 1)
911static struct of_device_id nss_dt_ids[] = {
912 { .compatible = "qcom,nss0" },
913 { .compatible = "qcom,nss1" },
914 {},
915};
916MODULE_DEVICE_TABLE(of, nss_dt_ids);
917#endif
918
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530919/*
920 * nss_driver
921 * Platform driver structure for NSS
922 */
923struct platform_driver nss_driver = {
924 .probe = nss_probe,
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800925#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,7,0))
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530926 .remove = __devexit_p(nss_remove),
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800927#else
928 .remove = nss_remove,
929#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530930 .driver = {
931 .name = "qca-nss",
932 .owner = THIS_MODULE,
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -0800933#if (NSS_DT_SUPPORT == 1)
934 .of_match_table = of_match_ptr(nss_dt_ids),
935#endif
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530936 },
937};
938
939/*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530940 * nss_reset_frequency_stats_samples()
941 * Reset all frequency sampling state when auto scaling is turned off.
942 */
943static void nss_reset_frequency_stats_samples (void)
944{
945 nss_runtime_samples.buffer_index = 0;
946 nss_runtime_samples.sum = 0;
947 nss_runtime_samples.average = 0;
948 nss_runtime_samples.sample_count = 0;
949 nss_runtime_samples.message_rate_limit = 0;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530950 nss_runtime_samples.freq_scale_rate_limit_down = 0;
951}
952
953/*
wthomas626147f2013-09-18 13:12:40 -0700954 ***************************************************************************************************
Thomas Wufb6a6842013-10-23 13:14:27 -0700955 * nss_wq_function() is used to queue up requests to change NSS frequencies.
956 * The function will take care of NSS notices and also control clock.
957 * The auto rate algorithmn will queue up requests or the procfs may also queue up these requests.
wthomas626147f2013-09-18 13:12:40 -0700958 ***************************************************************************************************
959 */
960
961/*
962 * nss_wq_function()
963 * Added to Handle BH requests to kernel
964 */
965void nss_wq_function (struct work_struct *work)
966{
967 nss_work_t *my_work = (nss_work_t *)work;
968
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530969 nss_freq_change(nss_freq_change_context, my_work->frequency, my_work->stats_enable, 0);
Thomas Wufb6a6842013-10-23 13:14:27 -0700970 clk_set_rate(nss_core0_clk, my_work->frequency);
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +0530971 nss_freq_change(nss_freq_change_context, my_work->frequency, my_work->stats_enable, 1);
wthomas626147f2013-09-18 13:12:40 -0700972
Thomas Wu0d112192015-04-13 11:37:22 -0700973#if (NSS_PM_SUPPORT == 1)
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530974 if(!pm_client) {
975 goto out;
976 }
977
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800978 if (my_work->frequency >= NSS_FREQ_733) {
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530979 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_TURBO);
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800980 } else if (my_work->frequency > NSS_FREQ_110) {
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530981 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_NOMINAL);
982 } else {
983 nss_pm_set_perf_level(pm_client, NSS_PM_PERF_LEVEL_IDLE);
984 }
Thomas Wu0d112192015-04-13 11:37:22 -0700985
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +0530986out:
Thomas Wu0d112192015-04-13 11:37:22 -0700987#endif
wthomas626147f2013-09-18 13:12:40 -0700988 kfree((void *)work);
989}
990
991/*
wthomas442c7972013-08-05 14:28:17 -0700992 * nss_current_freq_handler()
993 * Handle Userspace Frequency Change Requests
994 */
995static int nss_current_freq_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
996{
Thomas Wu0e2fc4f2015-03-04 15:39:14 -0800997 int ret, i;
wthomas626147f2013-09-18 13:12:40 -0700998
999 BUG_ON(!nss_wq);
wthomas442c7972013-08-05 14:28:17 -07001000
1001 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1002
wthomasd39fa822013-08-22 16:44:23 -07001003 if (!write) {
wthomas626147f2013-09-18 13:12:40 -07001004 printk("Frequency Set to %d\n", nss_cmd_buf.current_freq);
wthomasd39fa822013-08-22 16:44:23 -07001005 return ret;
wthomas442c7972013-08-05 14:28:17 -07001006 }
wthomasd39fa822013-08-22 16:44:23 -07001007
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001008 /*
1009 * Check if frequency exists in frequency Table
1010 */
1011 i = 0;
Thomas Wu7132bd32015-05-07 15:03:06 -07001012 while (i < NSS_FREQ_MAX_SCALE) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001013 if (nss_runtime_samples.freq_scale[i].frequency == nss_cmd_buf.current_freq) {
1014 break;
1015 }
1016 i++;
1017 }
Thomas Wu7132bd32015-05-07 15:03:06 -07001018 if (i == NSS_FREQ_MAX_SCALE) {
Thomas Wufb6a6842013-10-23 13:14:27 -07001019 printk("Frequency not found. Please check Frequency Table\n");
wthomas626147f2013-09-18 13:12:40 -07001020 return ret;
wthomasd39fa822013-08-22 16:44:23 -07001021 }
1022
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001023 /* Turn off Auto Scale */
1024 nss_cmd_buf.auto_scale = 0;
1025 nss_runtime_samples.freq_scale_ready = 0;
1026
Thomas Wu7409bce2014-05-21 10:56:07 -07001027 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
wthomas626147f2013-09-18 13:12:40 -07001028 if (!nss_work) {
1029 nss_info("NSS Freq WQ kmalloc fail");
1030 return ret;
1031 }
1032 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
1033 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301034 nss_work->stats_enable = 0;
1035
1036 /* Ensure we start with a fresh set of samples later */
1037 nss_reset_frequency_stats_samples();
1038
wthomas626147f2013-09-18 13:12:40 -07001039 queue_work(nss_wq, (struct work_struct *)nss_work);
1040
wthomas442c7972013-08-05 14:28:17 -07001041 return ret;
1042}
1043
1044/*
1045 * nss_auto_scale_handler()
1046 * Enables or Disable Auto Scaling
1047 */
1048static int nss_auto_scale_handler (ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1049{
1050 int ret;
1051
1052 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1053
wthomas626147f2013-09-18 13:12:40 -07001054 if (!write) {
1055 return ret;
1056 }
1057
Thomas Wufb6a6842013-10-23 13:14:27 -07001058 if (nss_cmd_buf.auto_scale != 1) {
wthomas626147f2013-09-18 13:12:40 -07001059 /*
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301060 * Is auto scaling currently enabled? If so, send the command to
1061 * disable stats reporting to NSS
wthomas626147f2013-09-18 13:12:40 -07001062 */
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301063 if (nss_runtime_samples.freq_scale_ready != 0) {
1064 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
Thomas Wu7409bce2014-05-21 10:56:07 -07001065 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301066 if (!nss_work) {
1067 nss_info("NSS Freq WQ kmalloc fail");
1068 return ret;
1069 }
1070 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
1071 nss_work->frequency = nss_cmd_buf.current_freq;
1072 nss_work->stats_enable = 0;
1073 queue_work(nss_wq, (struct work_struct *)nss_work);
1074 nss_runtime_samples.freq_scale_ready = 0;
1075
1076 /*
1077 * The current samples would be stale later when scaling is
1078 * enabled again, hence reset them
1079 */
1080 nss_reset_frequency_stats_samples();
1081 }
Thomas Wufb6a6842013-10-23 13:14:27 -07001082 return ret;
wthomas626147f2013-09-18 13:12:40 -07001083 }
wthomas442c7972013-08-05 14:28:17 -07001084
Thomas Wufb6a6842013-10-23 13:14:27 -07001085 /*
1086 * Auto Scaling is already being done
1087 */
1088 if (nss_runtime_samples.freq_scale_ready == 1) {
1089 return ret;
1090 }
1091
1092 /*
1093 * Setup default values - Middle of Freq Scale Band
1094 */
1095 nss_runtime_samples.freq_scale_index = 1;
1096 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
1097
Thomas Wu7409bce2014-05-21 10:56:07 -07001098 nss_work = (nss_work_t *)kmalloc(sizeof(nss_work_t), GFP_ATOMIC);
Thomas Wufb6a6842013-10-23 13:14:27 -07001099 if (!nss_work) {
1100 nss_info("NSS Freq WQ kmalloc fail");
1101 return ret;
1102 }
1103 INIT_WORK((struct work_struct *)nss_work, nss_wq_function);
1104 nss_work->frequency = nss_cmd_buf.current_freq;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301105 nss_work->stats_enable = 1;
Thomas Wufb6a6842013-10-23 13:14:27 -07001106 queue_work(nss_wq, (struct work_struct *)nss_work);
1107
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001108 nss_cmd_buf.auto_scale = 0;
Thomas Wufb6a6842013-10-23 13:14:27 -07001109 nss_runtime_samples.freq_scale_ready = 1;
1110
wthomas442c7972013-08-05 14:28:17 -07001111 return ret;
1112}
1113
1114/*
1115 * nss_get_freq_table_handler()
1116 * Display Support Freq and Ex how to Change.
1117 */
Thomas Wu05495be2013-12-19 14:24:24 -08001118static 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 -07001119{
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001120 int ret, i;
wthomas442c7972013-08-05 14:28:17 -07001121
1122 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1123
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001124 printk("Frequency Supported - ");
1125 i = 0;
Thomas Wu7132bd32015-05-07 15:03:06 -07001126 while (i < NSS_FREQ_MAX_SCALE) {
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001127 printk("%dMhz ", nss_runtime_samples.freq_scale[i].frequency/1000000);
1128 i++;
Thomas Wu0a0a9c92013-11-21 15:28:19 -08001129 }
Thomas Wu0e2fc4f2015-03-04 15:39:14 -08001130 printk("\n");
wthomas442c7972013-08-05 14:28:17 -07001131
1132 return ret;
1133}
1134
1135/*
Thomas Wu05495be2013-12-19 14:24:24 -08001136 * nss_get_average_inst_handler()
1137 * Display AVG Inst Per Ms.
1138 */
1139static int nss_get_average_inst_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
1145 if (!ret && !write) {
1146 printk("Current Inst Per Ms %x\n", nss_runtime_samples.average);
1147 }
1148
1149 return ret;
1150}
1151
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001152#if (NSS_FW_DBG_SUPPORT == 1)
Thomas Wu05495be2013-12-19 14:24:24 -08001153/*
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301154 * nss_debug_handler()
1155 * Enable NSS debug output
1156 */
1157static int nss_debug_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1158{
1159 int ret;
1160
1161 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1162 if (!ret) {
1163 if ((write) && (nss_ctl_debug != 0)) {
1164 printk("Enabling NSS SPI Debug\n");
1165 nss_hal_debug_enable();
1166 }
1167 }
1168
1169 return ret;
1170}
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001171#endif
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301172
1173/*
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301174 * nss_rps_handler()
1175 * Enable NSS RPS
1176 */
1177static int nss_rpscfg_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1178{
1179 struct nss_top_instance *nss_top = &nss_top_main;
1180 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0];
1181 int ret;
1182
1183 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1184 if (!ret) {
1185 if ((write) && (nss_rps_cfg == 1)) {
1186 printk("Enabling NSS RPS\n");
Vijay Dewangan634ce592015-01-07 17:21:09 -08001187
1188 return nss_n2h_rps_cfg(nss_ctx, 1);
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301189 }
1190
1191 if ((write) && (nss_rps_cfg == 0)) {
1192 printk("Runtime disabling of NSS RPS not supported \n");
1193 return ret;
1194 }
1195
1196 if (write) {
1197 printk("Invalid input value.Valid values are 0 and 1 \n");
1198 }
1199
1200 }
1201
1202 return ret;
1203}
1204
1205/*
Thomas Wu52075f42014-02-06 16:32:42 -08001206 * nss_coredump_handler()
1207 * Send Signal To Coredump NSS Cores
1208 */
1209static int nss_coredump_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1210{
1211 struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *) nss_freq_change_context;
1212 int ret;
1213
1214 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1215 if (!ret) {
1216 if ((write) && (nss_ctl_debug != 0)) {
1217 printk("Coredumping to DDR\n");
1218 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);
1219 }
1220 }
1221
1222 return ret;
1223}
1224
1225/*
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -08001226 * nss_jumbo_mru_handler()
1227 * Sysctl to modify nss_jumbo_mru
1228 */
1229static int nss_jumbo_mru_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1230{
1231 int ret;
1232
1233 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1234 if (ret) {
1235 return ret;
1236 }
1237
1238 if (write) {
1239 nss_core_set_jumbo_mru(nss_jumbo_mru);
1240 nss_info("jumbo_mru set to %d\n", nss_jumbo_mru);
1241 }
1242
1243 return ret;
1244}
1245
1246/* nss_paged_mode_handler()
1247 * Sysctl to modify nss_paged_mode.
1248 */
1249
1250static int nss_paged_mode_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
1251{
1252 int ret;
1253
1254 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
1255 if (ret) {
1256 return ret;
1257 }
1258
1259 if (write) {
1260 nss_core_set_paged_mode(nss_paged_mode);
1261 nss_info("paged_mode set to %d\n", nss_paged_mode);
1262 }
1263
1264 return ret;
1265}
1266
1267/*
wthomas442c7972013-08-05 14:28:17 -07001268 * sysctl-tuning infrastructure.
1269 */
1270static ctl_table nss_freq_table[] = {
1271 {
1272 .procname = "current_freq",
1273 .data = &nss_cmd_buf.current_freq,
1274 .maxlen = sizeof(int),
1275 .mode = 0644,
1276 .proc_handler = &nss_current_freq_handler,
1277 },
1278 {
1279 .procname = "freq_table",
1280 .data = &nss_cmd_buf.max_freq,
1281 .maxlen = sizeof(int),
1282 .mode = 0644,
1283 .proc_handler = &nss_get_freq_table_handler,
1284 },
1285 {
1286 .procname = "auto_scale",
1287 .data = &nss_cmd_buf.auto_scale,
1288 .maxlen = sizeof(int),
1289 .mode = 0644,
1290 .proc_handler = &nss_auto_scale_handler,
1291 },
Thomas Wu05495be2013-12-19 14:24:24 -08001292 {
1293 .procname = "inst_per_sec",
1294 .data = &nss_cmd_buf.average_inst,
1295 .maxlen = sizeof(int),
1296 .mode = 0644,
1297 .proc_handler = &nss_get_average_inst_handler,
1298 },
wthomas442c7972013-08-05 14:28:17 -07001299 { }
1300};
1301
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301302static ctl_table nss_general_table[] = {
1303 {
1304 .procname = "redirect",
1305 .data = &nss_ctl_redirect,
1306 .maxlen = sizeof(int),
1307 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001308 .proc_handler = proc_dointvec,
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301309 },
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001310#if (NSS_FW_DBG_SUPPORT == 1)
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301311 {
1312 .procname = "debug",
1313 .data = &nss_ctl_debug,
1314 .maxlen = sizeof(int),
1315 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001316 .proc_handler = &nss_debug_handler,
Abhishek Rastogi1626a902013-11-21 17:09:49 +05301317 },
Sundarajan Srinivasan758e8f42014-12-08 14:56:24 -08001318#endif
Thomas Wu52075f42014-02-06 16:32:42 -08001319 {
1320 .procname = "coredump",
1321 .data = &nss_cmd_buf.coredump,
1322 .maxlen = sizeof(int),
1323 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001324 .proc_handler = &nss_coredump_handler,
Thomas Wu52075f42014-02-06 16:32:42 -08001325 },
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301326 {
1327 .procname = "rps",
1328 .data = &nss_rps_cfg,
1329 .maxlen = sizeof(int),
1330 .mode = 0644,
Vijay Dewangan9db18752014-09-15 16:25:01 -07001331 .proc_handler = &nss_rpscfg_handler,
Pamidipati, Vijayefcc4692014-05-09 14:47:38 +05301332 },
Saurabh Misra96998db2014-07-10 12:15:48 -07001333 {
1334 .procname = "logbuf",
1335 .data = &nss_ctl_logbuf,
1336 .maxlen = sizeof(int),
1337 .mode = 0644,
1338 .proc_handler = &nss_logbuffer_handler,
1339 },
Sundarajan Srinivasanf9c4a232014-11-18 13:25:40 -08001340 {
1341 .procname = "jumbo_mru",
1342 .data = &nss_jumbo_mru,
1343 .maxlen = sizeof(int),
1344 .mode = 0644,
1345 .proc_handler = &nss_jumbo_mru_handler,
1346 },
1347 {
1348 .procname = "paged_mode",
1349 .data = &nss_paged_mode,
1350 .maxlen = sizeof(int),
1351 .mode = 0644,
1352 .proc_handler = &nss_paged_mode_handler,
1353 },
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301354 { }
1355};
1356
wthomas442c7972013-08-05 14:28:17 -07001357static ctl_table nss_clock_dir[] = {
1358 {
Abhishek Rastogi5cd2e4c2013-11-13 18:09:08 +05301359 .procname = "clock",
1360 .mode = 0555,
1361 .child = nss_freq_table,
1362 },
1363 {
1364 .procname = "general",
1365 .mode = 0555,
1366 .child = nss_general_table,
wthomas442c7972013-08-05 14:28:17 -07001367 },
1368 { }
1369};
1370
1371static ctl_table nss_root_dir[] = {
1372 {
1373 .procname = "nss",
1374 .mode = 0555,
1375 .child = nss_clock_dir,
1376 },
1377 { }
1378};
1379
1380static ctl_table nss_root[] = {
1381 {
1382 .procname = "dev",
1383 .mode = 0555,
1384 .child = nss_root_dir,
1385 },
1386 { }
1387};
1388
1389static struct ctl_table_header *nss_dev_header;
1390
1391/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301392 * nss_init()
1393 * Registers nss driver
1394 */
1395static int __init nss_init(void)
1396{
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001397#if (NSS_DT_SUPPORT == 1)
1398 struct device_node *cmn = NULL;
1399 struct resource res_nss_fpb_base;
1400#endif
1401
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301402 nss_info("Init NSS driver");
1403
Sundarajan Srinivasandedd8e42014-10-06 11:59:34 -07001404 nss_freq_change_context = nss_freq_get_mgr();
1405
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001406#if (NSS_DT_SUPPORT == 1)
1407 /*
1408 * Get reference to NSS common device node
1409 */
1410 cmn = of_find_node_by_name(NULL, "nss-common");
1411 if (!cmn) {
1412 nss_info("cannot find nss-common node\n");
1413 return -EFAULT;
1414 }
1415
1416 if (of_address_to_resource(cmn, 0, &res_nss_fpb_base) != 0) {
1417 nss_info("of_address_to_resource() return error for nss_fpb_base\n");
1418 of_node_put(cmn);
1419 return -EFAULT;
1420 }
1421
1422 nss_top_main.nss_fpb_base = ioremap_nocache(res_nss_fpb_base.start,
1423 resource_size(&res_nss_fpb_base));
1424 if (!nss_top_main.nss_fpb_base) {
1425 nss_info("ioremap fail for nss_fpb_base\n");
1426 of_node_put(cmn);
1427 return -EFAULT;
1428 }
1429
1430 nss_top_main.nss_hal_common_init_done = false;
1431
1432 /*
1433 * Release reference to NSS common device node
1434 */
1435 of_node_put(cmn);
1436 cmn = NULL;
1437#else
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301438 /*
1439 * Perform clock init common to all NSS cores
1440 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301441 nss_hal_common_reset(&(nss_top_main.clk_src));
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301442
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001443#endif /* NSS_DT_SUPPORT */
1444
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301445 /*
1446 * Enable spin locks
1447 */
1448 spin_lock_init(&(nss_top_main.lock));
1449 spin_lock_init(&(nss_top_main.stats_lock));
1450
1451 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301452 * Enable NSS statistics
1453 */
1454 nss_stats_init();
1455
1456 /*
wthomas442c7972013-08-05 14:28:17 -07001457 * Register sysctl table.
1458 */
1459 nss_dev_header = register_sysctl_table(nss_root);
1460
1461 /*
Vijay Dewangan9db18752014-09-15 16:25:01 -07001462 * Registering sysctl for ipv4/6 specific config.
1463 */
1464 nss_ipv4_register_sysctl();
1465 nss_ipv6_register_sysctl();
1466
Vijay Dewanganac7efc42015-02-09 16:04:53 -08001467 /*
1468 * Registering sysctl for n2h empty pool buffer.
1469 */
1470 nss_n2h_empty_pool_buf_register_sysctl();
1471
Sundarajan Srinivasan6e0366b2015-01-20 12:10:42 -08001472#ifdef CONFIG_DEBUG_KMEMLEAK
1473 /*
1474 * If the system is under kmemleak debugging, track our
1475 * skbs by putting them in a list.
1476 */
1477
1478 skb_queue_head_init(&nss_skb_list);
1479#endif
1480
Vijay Dewangan9db18752014-09-15 16:25:01 -07001481 /*
wthomas626147f2013-09-18 13:12:40 -07001482 * Setup Runtime Sample values
1483 */
wthomas626147f2013-09-18 13:12:40 -07001484 nss_runtime_samples.freq_scale_index = 1;
1485 nss_runtime_samples.freq_scale_ready = 0;
Thomas Wu9681f7e2013-11-06 13:12:57 -08001486 nss_runtime_samples.freq_scale_rate_limit_down = 0;
wthomas626147f2013-09-18 13:12:40 -07001487 nss_runtime_samples.buffer_index = 0;
1488 nss_runtime_samples.sum = 0;
1489 nss_runtime_samples.sample_count = 0;
1490 nss_runtime_samples.average = 0;
1491 nss_runtime_samples.message_rate_limit = 0;
Kiran Kumar C.S.K69fd5992014-01-06 20:58:14 +05301492 nss_runtime_samples.initialized = 0;
wthomas626147f2013-09-18 13:12:40 -07001493
Thomas Wu05495be2013-12-19 14:24:24 -08001494 nss_cmd_buf.current_freq = nss_runtime_samples.freq_scale[nss_runtime_samples.freq_scale_index].frequency;
1495
wthomas626147f2013-09-18 13:12:40 -07001496 /*
1497 * Initial Workqueue
1498 */
1499 nss_wq = create_workqueue("nss_freq_queue");
1500
Thomas Wu0d112192015-04-13 11:37:22 -07001501#if (NSS_PM_SUPPORT == 1)
wthomas626147f2013-09-18 13:12:40 -07001502 /*
Pamidipati, Vijay7f413b52013-09-24 19:07:12 +05301503 * Initialize NSS Bus PM module
1504 */
1505 nss_pm_init();
1506
1507 /*
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +05301508 * Register with Bus driver
1509 */
1510 pm_client = nss_pm_client_register(NSS_PM_CLIENT_NETAP);
1511 if (!pm_client) {
1512 nss_warning("Error registering with PM driver");
1513 }
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001514#endif
Pamidipati, Vijay5d27d812013-11-22 16:48:11 +05301515
1516 /*
Radha krishna Simha Jiguru7f424d52015-02-10 19:41:01 +05301517 * Initialize mtu size needed as start
1518 */
1519 nss_top_main.prev_mtu_sz = NSS_GMAC_NORMAL_FRAME_MTU;
1520
1521 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301522 * Register platform_driver
1523 */
1524 return platform_driver_register(&nss_driver);
1525}
1526
1527/*
1528 * nss_cleanup()
1529 * Unregisters nss driver
1530 */
1531static void __exit nss_cleanup(void)
1532{
1533 nss_info("Exit NSS driver");
wthomas442c7972013-08-05 14:28:17 -07001534
1535 if (nss_dev_header)
1536 unregister_sysctl_table(nss_dev_header);
1537
Vijay Dewangan9db18752014-09-15 16:25:01 -07001538 /*
Vijay Dewangan488e5372014-12-29 21:40:11 -08001539 * Unregister n2h specific sysctl
1540 */
1541 nss_n2h_empty_pool_buf_unregister_sysctl();
1542
1543 /*
Vijay Dewangan9db18752014-09-15 16:25:01 -07001544 * Unregister ipv4/6 specific sysctl
1545 */
1546 nss_ipv4_unregister_sysctl();
1547 nss_ipv6_unregister_sysctl();
1548
Sundarajan Srinivasan4691ba62014-11-07 11:24:07 -08001549#if (NSS_DT_SUPPORT == 1)
1550 if(nss_top_main.nss_fpb_base) {
1551 iounmap(nss_top_main.nss_fpb_base);
1552 nss_top_main.nss_fpb_base = 0;
1553 }
1554#endif
1555
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301556 platform_driver_unregister(&nss_driver);
1557}
1558
1559module_init(nss_init);
1560module_exit(nss_cleanup);
1561
1562MODULE_DESCRIPTION("QCA NSS Driver");
1563MODULE_AUTHOR("Qualcomm Atheros Inc");
1564MODULE_LICENSE("Dual BSD/GPL");