blob: 37c44326ecdcc3c8443bd1425890588c66e47548 [file] [log] [blame]
Abhishek Rastogibc74e432013-04-02 10:28:22 +05301/* * Copyright (c) 2013 Qualcomm Atheros, Inc. * */
2
3/*
4 * nss_init.c
5 * NSS init APIs
6 *
7 */
8
9#include "nss_core.h"
10#include <nss_hal.h>
11
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <mach/msm_nss.h>
15
16/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +053017 * Declare module parameters
18 */
19static int load0 = 0x40000000;
20module_param(load0, int, S_IRUSR | S_IWUSR);
21MODULE_PARM_DESC(load0, "NSS Core 0 load address");
22
23static int entry0 = 0x40000000;
24module_param(entry0, int, S_IRUSR | S_IWUSR);
25MODULE_PARM_DESC(load0, "NSS Core 0 entry address");
26
27static char *string0 = "nss0";
28module_param(string0, charp, 0);
29MODULE_PARM_DESC(string0, "NSS Core 0 identification string");
30
31static int load1 = 0x40100000;
32module_param(load1, int, S_IRUSR | S_IWUSR);
33MODULE_PARM_DESC(load0, "NSS Core 1 load address");
34
35static int entry1 = 0x40100000;
36module_param(entry1, int, S_IRUSR | S_IWUSR);
37MODULE_PARM_DESC(load0, "NSS Core 1 entry address");
38
39static char *string1 = "nss1";
40module_param(string1, charp, 0);
41MODULE_PARM_DESC(string1, "NSS Core 1 identification string");
42
43
44/*
Abhishek Rastogibc74e432013-04-02 10:28:22 +053045 * Global declarations
46 */
47
48/*
49 * Top level nss context structure
50 */
51struct nss_top_instance nss_top_main;
52
53/*
54 * File local/Static variables/functions
55 */
56
57/*
58 * nss_handle_irq()
59 * HLOS interrupt handler for nss interrupts
60 */
61static irqreturn_t nss_handle_irq (int irq, void *ctx)
62{
63 struct int_ctx_instance *int_ctx = (struct int_ctx_instance *) ctx;
64
65 /*
66 * Disable IRQ until our bottom half re-enables it
67 */
68 disable_irq_nosync(irq);
69
70 /*
71 * Schedule tasklet to process interrupt cause
72 */
73 tasklet_schedule(&int_ctx->bh);
74 return IRQ_HANDLED;
75}
76
77/*
78 * nss_probe()
79 * HLOS device probe callback
80 */
81static int __devinit nss_probe (struct platform_device *nss_dev)
82{
83 struct nss_top_instance *nss_top = &nss_top_main;
84 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
85 struct nss_platform_data *npd = (struct nss_platform_data *) nss_dev->dev.platform_data;
86 int err, i;
87
88 nss_ctx->nss_top = nss_top;
89 nss_ctx->id = nss_dev->id;
90
91 /*
92 * Get virtual and physical memory addresses for nss logical/hardware address maps
93 */
94
95 /*
96 * Virtual address of CSM space
97 */
98 nss_ctx->nmap = npd->nmap;
99 nss_assert(nss_ctx->nmap);
100
101 /*
102 * Physical address of CSM space
103 */
104 nss_ctx->nphys = npd->nphys;
105 nss_assert(nss_ctx->nphys);
106
107 /*
108 * Virtual address of logical registers space
109 */
110 nss_ctx->vmap = npd->vmap;
111 nss_assert(nss_ctx->vmap);
112
113 /*
114 * Physical address of logical registers space
115 */
116 nss_ctx->vphys = npd->vphys;
117 nss_assert(nss_ctx->vphys);
118 nss_info("nss:%d:vphys =%x, vmap =%x, nphys=%x, nmap =%x", nss_dev->id, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
119
120 /*
121 * request for IRQs
122 *
123 * WARNING: CPU affinities should be set using OS supported methods
124 */
125 nss_ctx->int_ctx[0].nss_ctx = nss_ctx;
126 nss_ctx->int_ctx[0].shift_factor = 0;
127 nss_ctx->int_ctx[0].irq = npd->irq[0];
128 err = request_irq(npd->irq[0], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[0]);
129 if (err) {
130 nss_warning("%d: IRQ0 request failed", nss_dev->id);
131 return err;
132 }
133
134 /*
135 * Register bottom halves for NSS core interrupt
136 */
137 tasklet_init(&nss_ctx->int_ctx[0].bh, nss_core_handle_bh, (unsigned long)&nss_ctx->int_ctx[0]);
138
139 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530140 * Check if second interrupt is supported on this nss core
141 */
142 if (npd->num_irq > 1) {
143 nss_info("%d: This NSS core supports two interrupts", nss_dev->id);
144 nss_ctx->int_ctx[1].nss_ctx = nss_ctx;
145 nss_ctx->int_ctx[1].shift_factor = 15;
146 nss_ctx->int_ctx[1].irq = npd->irq[1];
147 err = request_irq(npd->irq[1], nss_handle_irq, IRQF_DISABLED, "nss", &nss_ctx->int_ctx[1]);
148 if (err) {
149 nss_warning("%d: IRQ1 request failed for nss", nss_dev->id);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530150 tasklet_kill(&nss_ctx->int_ctx[0].bh);
151 free_irq(nss_ctx->int_ctx[0].irq, &nss_ctx->int_ctx[0]);
152 return err;
153 }
154
155 /*
156 * Register bottom halves for NSS0 interrupts
157 */
158 tasklet_init(&nss_ctx->int_ctx[1].bh, nss_core_handle_bh, (unsigned long)&nss_ctx->int_ctx[1]);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530159 }
160
161 spin_lock_bh(&(nss_top->lock));
162
163 /*
164 * Check functionalities are supported by this NSS core
165 */
166 if (npd->ipv4_enabled == NSS_FEATURE_ENABLED) {
167 nss_top->ipv4_handler_id = nss_dev->id;
168 }
169
170 if (npd->ipv6_enabled == NSS_FEATURE_ENABLED) {
171 nss_top->ipv6_handler_id = nss_dev->id;
172 }
173
174 if (npd->l2switch_enabled == NSS_FEATURE_ENABLED) {
175 nss_top->l2switch_handler_id = nss_dev->id;
176 }
177
178 if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
179 nss_top->crypto_handler_id = nss_dev->id;
180 }
181
182 if (npd->ipsec_enabled == NSS_FEATURE_ENABLED) {
183 nss_top->ipsec_handler_id = nss_dev->id;
184 }
185
186 if (npd->wlan_enabled == NSS_FEATURE_ENABLED) {
187 nss_top->wlan_handler_id = nss_dev->id;
188 }
189
190 if (npd->gmac_enabled[0] == NSS_FEATURE_ENABLED) {
191 nss_top->phys_if_handler_id[0] = nss_dev->id;
192 }
193
194 if (npd->gmac_enabled[1] == NSS_FEATURE_ENABLED) {
195 nss_top->phys_if_handler_id[1] = nss_dev->id;
196 }
197
198 if (npd->gmac_enabled[2] == NSS_FEATURE_ENABLED) {
199 nss_top->phys_if_handler_id[2] = nss_dev->id;
200 }
201
202 if (npd->gmac_enabled[3] == NSS_FEATURE_ENABLED) {
203 nss_top->phys_if_handler_id[3] = nss_dev->id;
204 }
205
206 spin_unlock_bh(&(nss_top->lock));
207
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530208 /*
209 * Initialize decongestion callbacks to NULL
210 */
211 for (i = 0; i< NSS_MAX_CLIENTS; i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530212 nss_ctx->queue_decongestion_callback[i] = 0;
213 nss_ctx->queue_decongestion_ctx[i] = 0;
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530214 }
215
216 spin_lock_init(&(nss_ctx->decongest_cb_lock));
217 nss_ctx->magic = NSS_CTX_MAGIC;
218
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530219 nss_info("%p: Reseting NSS core %d now", nss_ctx, nss_ctx->id);
220
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530221 /*
222 * Enable clocks and bring NSS core out of reset
223 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530224 nss_hal_core_reset(nss_dev->id, nss_ctx->nmap, nss_ctx->load, nss_top->clk_src);
225
226 /*
227 * Enable interrupts for NSS core
228 */
229 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
230 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
231
232 if (npd->num_irq > 1) {
233 nss_hal_enable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
234 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
235 }
236
237
238 nss_info("%p: All resources initialized and nss core%d has been brought out of reset", nss_ctx, nss_dev->id);
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530239 return 0;
240}
241
242/*
243 * nss_remove()
244 * HLOS device remove callback
245 */
246static int __devexit nss_remove (struct platform_device *nss_dev)
247{
248 struct nss_top_instance *nss_top = &nss_top_main;
249 struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_dev->id];
250
251 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530252 * Clean-up debugfs
253 */
254 nss_stats_clean();
255
256 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530257 * Disable interrupts and bottom halves in HLOS
258 * Disable interrupts from NSS to HLOS
259 */
260 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[0].irq,
261 nss_ctx->int_ctx[0].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
262 tasklet_kill(&nss_ctx->int_ctx[0].bh);
263 free_irq(nss_ctx->int_ctx[0].irq, &nss_ctx->int_ctx[0]);
264
265 /*
266 * Check if second interrupt is supported
267 * If so then clear resources for second interrupt as well
268 */
269 if (nss_ctx->int_ctx[1].irq) {
270 nss_hal_disable_interrupt(nss_ctx->nmap, nss_ctx->int_ctx[1].irq,
271 nss_ctx->int_ctx[1].shift_factor, NSS_HAL_SUPPORTED_INTERRUPTS);
272 tasklet_kill(&nss_ctx->int_ctx[1].bh);
273 free_irq(nss_ctx->int_ctx[1].irq, &nss_ctx->int_ctx[1]);
274 }
275
276 nss_info("%p: All resources freed for nss core%d", nss_ctx, nss_dev->id);
277 return 0;
278}
279
280/*
281 * nss_driver
282 * Platform driver structure for NSS
283 */
284struct platform_driver nss_driver = {
285 .probe = nss_probe,
286 .remove = __devexit_p(nss_remove),
287 .driver = {
288 .name = "qca-nss",
289 .owner = THIS_MODULE,
290 },
291};
292
293/*
294 * nss_init()
295 * Registers nss driver
296 */
297static int __init nss_init(void)
298{
299 nss_info("Init NSS driver");
300
301 /*
302 * Perform clock init common to all NSS cores
303 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530304 nss_hal_common_reset(&(nss_top_main.clk_src));
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530305
306 /*
307 * Enable spin locks
308 */
309 spin_lock_init(&(nss_top_main.lock));
310 spin_lock_init(&(nss_top_main.stats_lock));
311
312 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530313 * Enable NSS statistics
314 */
315 nss_stats_init();
316
317 /*
318 * Store load addresses
319 */
320 nss_top_main.nss[0].load = (uint32_t)load0;
321 nss_top_main.nss[1].load = (uint32_t)load1;
322
323 /*
Abhishek Rastogibc74e432013-04-02 10:28:22 +0530324 * Register platform_driver
325 */
326 return platform_driver_register(&nss_driver);
327}
328
329/*
330 * nss_cleanup()
331 * Unregisters nss driver
332 */
333static void __exit nss_cleanup(void)
334{
335 nss_info("Exit NSS driver");
336 platform_driver_unregister(&nss_driver);
337}
338
339module_init(nss_init);
340module_exit(nss_cleanup);
341
342MODULE_DESCRIPTION("QCA NSS Driver");
343MODULE_AUTHOR("Qualcomm Atheros Inc");
344MODULE_LICENSE("Dual BSD/GPL");