blob: c58b150a5856cb91c4d39ce9dd230a28890810bc [file] [log] [blame]
Arun Kumar Neelakantam804f5162013-07-25 17:58:05 +05301/* arch/arm/mach-msm/smd_init_plat.c
2 *
3 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15#ifndef CONFIG_OF
16#include <linux/platform_device.h>
17#include <linux/module.h>
18#include <linux/interrupt.h>
19#include <linux/io.h>
20#include <linux/slab.h>
21
22#include <mach/msm_iomap.h>
23#include <mach/msm_ipc_logging.h>
24#include <smd_private.h>
25
26#define MODULE_NAME "msm_smd"
27#define IPC_LOG(level, x...) do { \
28 if (smd_log_ctx) \
29 ipc_log_string(smd_log_ctx, x); \
30 else \
31 printk(level x); \
32 } while (0)
33
34#if defined(CONFIG_MSM_SMD_DEBUG)
35#define SMD_DBG(x...) do { \
36 if (msm_smd_debug_mask & MSM_SMD_DEBUG) \
37 IPC_LOG(KERN_DEBUG, x); \
38 } while (0)
39
40#define SMD_INFO(x...) do { \
41 if (msm_smd_debug_mask & MSM_SMD_INFO) \
42 IPC_LOG(KERN_INFO, x); \
43 } while (0)
44#else
45#define SMD_DBG(x...) do { } while (0)
46#define SMD_INFO(x...) do { } while (0)
47#endif
48
49#if defined(CONFIG_ARCH_QSD8X50) || defined(CONFIG_ARCH_MSM8X60) \
50 || defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_FSM9XXX) \
51 || defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_APQ8064)
52#define CONFIG_QDSP6 1
53#endif
54
55#if defined(CONFIG_ARCH_MSM8X60) || defined(CONFIG_ARCH_MSM8960) \
56 || defined(CONFIG_ARCH_APQ8064)
57#define CONFIG_DSPS 1
58#endif
59
60#if defined(CONFIG_ARCH_MSM8960) \
61 || defined(CONFIG_ARCH_APQ8064)
62#define CONFIG_WCNSS 1
63#define CONFIG_DSPS_SMSM 1
64#endif
65
66#if defined(CONFIG_ARCH_MSM7X30)
67#define MSM_CFG_A2M_SMD_INT \
68 (smd_cfg_smd_intr(SMD_MODEM, 1 << 0, MSM_APCS_GCC_BASE + 0x8))
69#define MSM_CFG_A2Q6_SMD_INT \
70 (smd_cfg_smd_intr(SMD_Q6, 1 << 8, MSM_APCS_GCC_BASE + 0x8))
71#define MSM_CFG_A2M_SMSM_INT \
72 (smd_cfg_smsm_intr(SMD_MODEM, 1 << 5, MSM_APCS_GCC_BASE + 0x8))
73#define MSM_CFG_A2Q6_SMSM_INT \
74 (smd_cfg_smsm_intr(SMD_Q6, 1 << 8, MSM_APCS_GCC_BASE + 0x8))
75#define MSM_CFG_A2DSPS_SMD_INT
76#define MSM_CFG_A2DSPS_SMSM_INT
77#define MSM_CFG_A2WCNSS_SMD_INT
78#define MSM_CFG_A2WCNSS_SMSM_INT
79#elif defined(CONFIG_ARCH_MSM8X60)
80#define MSM_CFG_A2M_SMD_INT \
81 (smd_cfg_smd_intr(SMD_MODEM, 1 << 3, MSM_GCC_BASE + 0x8))
82#define MSM_CFG_A2Q6_SMD_INT \
83 (smd_cfg_smd_intr(SMD_Q6, 1 << 15, MSM_GCC_BASE + 0x8))
84#define MSM_CFG_A2M_SMSM_INT \
85 (smd_cfg_smsm_intr(SMD_MODEM, 1 << 4, MSM_GCC_BASE + 0x8))
86#define MSM_CFG_A2Q6_SMSM_INT \
87 (smd_cfg_smsm_intr(SMD_Q6, 1 << 14, MSM_GCC_BASE + 0x8))
88#define MSM_CFG_A2DSPS_SMD_INT \
89 (smd_cfg_smd_intr(SMD_DSPS, 1, \
90 MSM_SIC_NON_SECURE_BASE + 0x4080))
91#define MSM_CFG_A2DSPS_SMSM_INT
92#define MSM_CFG_A2WCNSS_SMD_INT
93#define MSM_CFG_A2WCNSS_SMSM_INT
94#elif defined(CONFIG_ARCH_MSM9615)
95#define MSM_CFG_A2M_SMD_INT \
96 (smd_cfg_smd_intr(SMD_MODEM, 1 << 3, MSM_APCS_GCC_BASE + 0x8))
97#define MSM_CFG_A2Q6_SMD_INT \
98 (smd_cfg_smd_intr(SMD_Q6, 1 << 15, MSM_APCS_GCC_BASE + 0x8))
99#define MSM_CFG_A2M_SMSM_INT \
100 (smd_cfg_smsm_intr(SMD_MODEM, 1 << 4, MSM_APCS_GCC_BASE + 0x8))
101#define MSM_CFG_A2Q6_SMSM_INT \
102 (smd_cfg_smsm_intr(SMD_Q6, 1 << 14, MSM_APCS_GCC_BASE + 0x8))
103#define MSM_CFG_A2DSPS_SMD_INT
104#define MSM_CFG_A2DSPS_SMSM_INT
105#define MSM_CFG_A2WCNSS_SMD_INT
106#define MSM_CFG_A2WCNSS_SMSM_INT
107#elif defined(CONFIG_ARCH_FSM9XXX)
108#define MSM_CFG_A2Q6_SMD_INT \
109 (smd_cfg_smd_intr(SMD_Q6, 1 << 10, MSM_GCC_BASE + 0x8))
110#define MSM_CFG_A2Q6_SMSM_INT \
111 (smd_cfg_smsm_intr(SMD_Q6, 1 << 10, MSM_GCC_BASE + 0x8))
112#define MSM_CFG_A2M_SMD_INT \
113 (smd_cfg_smd_intr(SMD_MODEM, 1 << 0, MSM_GCC_BASE + 0x8))
114#define MSM_CFG_A2M_SMSM_INT \
115 (smd_cfg_smsm_intr(SMD_MODEM, 1 << 5, MSM_GCC_BASE + 0x8))
116#define MSM_CFG_A2DSPS_SMD_INT
117#define MSM_CFG_A2DSPS_SMSM_INT
118#define MSM_CFG_A2WCNSS_SMD_INT
119#define MSM_CFG_A2WCNSS_SMSM_INT
120#elif defined(CONFIG_ARCH_MSM7X01A) || defined(CONFIG_ARCH_MSM7x25)
121#define MSM_CFG_A2M_SMD_INT \
122 (smd_cfg_smd_intr(SMD_MODEM, 1, MSM_CSR_BASE + 0x400 + (0) * 4))
123#define MSM_CFG_A2Q6_SMD_INT
124#define MSM_CFG_A2M_SMSM_INT \
125 (smd_cfg_smsm_intr(SMD_MODEM, 1, \
126 MSM_CSR_BASE + 0x400 + (5) * 4))
127#define MSM_CFG_A2Q6_SMSM_INT
128#define MSM_CFG_A2DSPS_SMD_INT
129#define MSM_CFG_A2DSPS_SMSM_INT
130#define MSM_CFG_A2WCNSS_SMD_INT
131#define MSM_CFG_A2WCNSS_SMSM_INT
132#elif defined(CONFIG_ARCH_MSM7X27) || defined(CONFIG_ARCH_MSM7X27A)
133#define MSM_CFG_A2M_SMD_INT \
134 (smd_cfg_smd_intr(SMD_MODEM, 1, MSM_CSR_BASE + 0x400 + (0) * 4))
135#define MSM_CFG_A2Q6_SMD_INT
136#define MSM_CFG_A2M_SMSM_INT \
137 (smd_cfg_smsm_intr(SMD_MODEM, 1, \
138 MSM_CSR_BASE + 0x400 + (5) * 4))
139#define MSM_CFG_A2Q6_SMSM_INT
140#define MSM_CFG_A2DSPS_SMD_INT
141#define MSM_CFG_A2DSPS_SMSM_INT
142#define MSM_CFG_A2WCNSS_SMD_INT
143#define MSM_CFG_A2WCNSS_SMSM_INT
144#else /* use platform device / device tree configuration */
145#define MSM_CFG_A2M_SMD_INT
146#define MSM_CFG_A2Q6_SMD_INT
147#define MSM_CFG_A2M_SMSM_INT
148#define MSM_CFG_A2Q6_SMSM_INT
149#define MSM_CFG_A2DSPS_SMD_INT
150#define MSM_CFG_A2DSPS_SMSM_INT
151#define MSM_CFG_A2WCNSS_SMD_INT
152#define MSM_CFG_A2WCNSS_SMSM_INT
153#endif
154
155/*
156 * stub out legacy macros if they are not being used so that the legacy
157 * code compiles even though it is not used
158 *
159 * these definitions should not be used in active code and will cause
160 * an early failure
161 */
162#ifndef INT_A9_M2A_0
163#define INT_A9_M2A_0 -1
164#endif
165#ifndef INT_A9_M2A_5
166#define INT_A9_M2A_5 -1
167#endif
168#ifndef INT_ADSP_A11
169#define INT_ADSP_A11 -1
170#endif
171#ifndef INT_ADSP_A11_SMSM
172#define INT_ADSP_A11_SMSM -1
173#endif
174#ifndef INT_DSPS_A11
175#define INT_DSPS_A11 -1
176#endif
177#ifndef INT_DSPS_A11_SMSM
178#define INT_DSPS_A11_SMSM -1
179#endif
180#ifndef INT_WCNSS_A11
181#define INT_WCNSS_A11 -1
182#endif
183#ifndef INT_WCNSS_A11_SMSM
184#define INT_WCNSS_A11_SMSM -1
185#endif
186
187static int intr_init(struct interrupt_config_item *private_irq,
188 struct smd_irq_config *platform_irq,
189 struct platform_device *pdev
190 )
191{
192 int irq_id;
193 int ret;
194 int ret_wake;
195
196 private_irq->out_bit_pos = platform_irq->out_bit_pos;
197 private_irq->out_offset = platform_irq->out_offset;
198 private_irq->out_base = platform_irq->out_base;
199
200 irq_id = platform_get_irq_byname(
201 pdev,
202 platform_irq->irq_name
203 );
204 SMD_DBG("smd: %s: register irq: %s id: %d\n", __func__,
205 platform_irq->irq_name, irq_id);
206 ret = request_irq(irq_id,
207 private_irq->irq_handler,
208 platform_irq->flags,
209 platform_irq->device_name,
210 (void *)platform_irq->dev_id
211 );
212 if (ret < 0) {
213 platform_irq->irq_id = ret;
214 private_irq->irq_id = ret;
215 } else {
216 platform_irq->irq_id = irq_id;
217 private_irq->irq_id = irq_id;
218 ret_wake = enable_irq_wake(irq_id);
219 if (ret_wake < 0) {
220 pr_err("smd: enable_irq_wake failed on %s",
221 platform_irq->irq_name);
222 }
223 }
224
225 return ret;
226}
227
228int smd_core_init(void)
229{
230 int r;
231 unsigned long flags = IRQF_TRIGGER_RISING;
232 SMD_INFO("smd_core_init()\n");
233
234 MSM_CFG_A2M_SMD_INT;
235 MSM_CFG_A2Q6_SMD_INT;
236 MSM_CFG_A2M_SMSM_INT;
237 MSM_CFG_A2Q6_SMSM_INT;
238 MSM_CFG_A2DSPS_SMD_INT;
239 MSM_CFG_A2DSPS_SMSM_INT;
240 MSM_CFG_A2WCNSS_SMD_INT;
241 MSM_CFG_A2WCNSS_SMSM_INT;
242
243 r = request_irq(INT_A9_M2A_0, smd_modem_irq_handler,
244 flags, "smd_dev", 0);
245 if (r < 0)
246 return r;
247 interrupt_stats[SMD_MODEM].smd_interrupt_id = INT_A9_M2A_0;
248 r = enable_irq_wake(INT_A9_M2A_0);
249 if (r < 0)
250 pr_err("%s: enable_irq_wake failed for INT_A9_M2A_0\n",
251 __func__);
252
253 r = request_irq(INT_A9_M2A_5, smsm_modem_irq_handler,
254 flags, "smsm_dev", 0);
255 if (r < 0) {
256 free_irq(INT_A9_M2A_0, 0);
257 return r;
258 }
259 interrupt_stats[SMD_MODEM].smsm_interrupt_id = INT_A9_M2A_5;
260 r = enable_irq_wake(INT_A9_M2A_5);
261 if (r < 0)
262 pr_err("%s: enable_irq_wake failed for INT_A9_M2A_5\n",
263 __func__);
264
265#if defined(CONFIG_QDSP6)
266#if (INT_ADSP_A11 == INT_ADSP_A11_SMSM)
267 flags |= IRQF_SHARED;
268#endif
269 r = request_irq(INT_ADSP_A11, smd_dsp_irq_handler,
270 flags, "smd_dev", smd_dsp_irq_handler);
271 if (r < 0) {
272 free_irq(INT_A9_M2A_0, 0);
273 free_irq(INT_A9_M2A_5, 0);
274 return r;
275 }
276
277 interrupt_stats[SMD_Q6].smd_interrupt_id = INT_ADSP_A11;
278 r = request_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler,
279 flags, "smsm_dev", smsm_dsp_irq_handler);
280 if (r < 0) {
281 free_irq(INT_A9_M2A_0, 0);
282 free_irq(INT_A9_M2A_5, 0);
283 free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
284 return r;
285 }
286
287 interrupt_stats[SMD_Q6].smsm_interrupt_id = INT_ADSP_A11_SMSM;
288 r = enable_irq_wake(INT_ADSP_A11);
289 if (r < 0)
290 pr_err("%s: enable_irq_wake failed for INT_ADSP_A11\n",
291 __func__);
292
293#if (INT_ADSP_A11 != INT_ADSP_A11_SMSM)
294 r = enable_irq_wake(INT_ADSP_A11_SMSM);
295 if (r < 0)
296 pr_err("%s: enable_irq_wake failed for INT_ADSP_A11_SMSM\n",
297 __func__);
298#endif
299 flags &= ~IRQF_SHARED;
300#endif
301
302#if defined(CONFIG_DSPS)
303 r = request_irq(INT_DSPS_A11, smd_dsps_irq_handler,
304 flags, "smd_dev", smd_dsps_irq_handler);
305 if (r < 0) {
306 free_irq(INT_A9_M2A_0, 0);
307 free_irq(INT_A9_M2A_5, 0);
308 free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
309 free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
310 return r;
311 }
312
313 interrupt_stats[SMD_DSPS].smd_interrupt_id = INT_DSPS_A11;
314 r = enable_irq_wake(INT_DSPS_A11);
315 if (r < 0)
316 pr_err("%s: enable_irq_wake failed for INT_ADSP_A11\n",
317 __func__);
318#endif
319
320#if defined(CONFIG_WCNSS)
321 r = request_irq(INT_WCNSS_A11, smd_wcnss_irq_handler,
322 flags, "smd_dev", smd_wcnss_irq_handler);
323 if (r < 0) {
324 free_irq(INT_A9_M2A_0, 0);
325 free_irq(INT_A9_M2A_5, 0);
326 free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
327 free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
328 free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
329 return r;
330 }
331
332 interrupt_stats[SMD_WCNSS].smd_interrupt_id = INT_WCNSS_A11;
333 r = enable_irq_wake(INT_WCNSS_A11);
334 if (r < 0)
335 pr_err("%s: enable_irq_wake failed for INT_WCNSS_A11\n",
336 __func__);
337
338 r = request_irq(INT_WCNSS_A11_SMSM, smsm_wcnss_irq_handler,
339 flags, "smsm_dev", smsm_wcnss_irq_handler);
340 if (r < 0) {
341 free_irq(INT_A9_M2A_0, 0);
342 free_irq(INT_A9_M2A_5, 0);
343 free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
344 free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
345 free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
346 free_irq(INT_WCNSS_A11, smd_wcnss_irq_handler);
347 return r;
348 }
349
350 interrupt_stats[SMD_WCNSS].smsm_interrupt_id = INT_WCNSS_A11_SMSM;
351 r = enable_irq_wake(INT_WCNSS_A11_SMSM);
352 if (r < 0)
353 pr_err("%s: enable_irq_wake failed for INT_WCNSS_A11_SMSM\n",
354 __func__);
355#endif
356
357#if defined(CONFIG_DSPS_SMSM)
358 r = request_irq(INT_DSPS_A11_SMSM, smsm_dsps_irq_handler,
359 flags, "smsm_dev", smsm_dsps_irq_handler);
360 if (r < 0) {
361 free_irq(INT_A9_M2A_0, 0);
362 free_irq(INT_A9_M2A_5, 0);
363 free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
364 free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
365 free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
366 free_irq(INT_WCNSS_A11, smd_wcnss_irq_handler);
367 free_irq(INT_WCNSS_A11_SMSM, smsm_wcnss_irq_handler);
368 return r;
369 }
370
371 interrupt_stats[SMD_DSPS].smsm_interrupt_id = INT_DSPS_A11_SMSM;
372 r = enable_irq_wake(INT_DSPS_A11_SMSM);
373 if (r < 0)
374 pr_err("%s: enable_irq_wake failed for INT_DSPS_A11_SMSM\n",
375 __func__);
376#endif
377 SMD_INFO("smd_core_init() done\n");
378
379 return 0;
380}
381
382int smd_core_platform_init(struct platform_device *pdev)
383{
384 int i;
385 int ret;
386 uint32_t num_ss;
387 struct smd_platform *smd_platform_data;
388 struct smd_subsystem_config *smd_ss_config_list;
389 struct smd_subsystem_config *cfg;
390 struct interrupt_config *private_intr_config;
391 int err_ret = 0;
392
393 smd_platform_data = pdev->dev.platform_data;
394 num_ss = smd_platform_data->num_ss_configs;
395 smd_ss_config_list = smd_platform_data->smd_ss_configs;
396
397 if (smd_platform_data->smd_ssr_config)
398 disable_smsm_reset_handshake = smd_platform_data->
399 smd_ssr_config->disable_smsm_reset_handshake;
400
401 for (i = 0; i < num_ss; i++) {
402 cfg = &smd_ss_config_list[i];
403 private_intr_config = smd_get_intr_config(cfg->edge);
404 if (!private_intr_config) {
405 pr_err("%s: invalid edge\n", __func__);
406 goto intr_failed;
407 }
408
409 ret = intr_init(
410 &private_intr_config->smd,
411 &cfg->smd_int,
412 pdev
413 );
414
415 if (ret < 0) {
416 err_ret = ret;
417 pr_err("smd: register irq failed on %s\n",
418 cfg->smd_int.irq_name);
419 goto intr_failed;
420 }
421
422 interrupt_stats[cfg->irq_config_id].smd_interrupt_id
423 = cfg->smd_int.irq_id;
424 /* only init smsm structs if this edge supports smsm */
425 if (cfg->smsm_int.irq_id)
426 ret = intr_init(
427 &private_intr_config->smsm,
428 &cfg->smsm_int,
429 pdev
430 );
431
432 if (ret < 0) {
433 err_ret = ret;
434 pr_err("smd: register irq failed on %s\n",
435 cfg->smsm_int.irq_name);
436 goto intr_failed;
437 }
438
439 if (cfg->smsm_int.irq_id)
440 interrupt_stats[cfg->irq_config_id].smsm_interrupt_id
441 = cfg->smsm_int.irq_id;
442 if (cfg->subsys_name)
443 smd_set_edge_subsys_name(cfg->edge, cfg->subsys_name);
444
445 smd_set_edge_initialized(cfg->edge);
446 }
447
448 SMD_INFO("smd_core_platform_init() done\n");
449
450 return 0;
451
452intr_failed:
453 pr_err("smd: deregistering IRQs\n");
454 for (i = 0; i < num_ss; ++i) {
455 cfg = &smd_ss_config_list[i];
456
457 if (cfg->smd_int.irq_id >= 0)
458 free_irq(cfg->smd_int.irq_id,
459 (void *)cfg->smd_int.dev_id
460 );
461 if (cfg->smsm_int.irq_id >= 0)
462 free_irq(cfg->smsm_int.irq_id,
463 (void *)cfg->smsm_int.dev_id
464 );
465 }
466 return err_ret;
467}
468
469static int msm_smd_probe_legacy(struct platform_device *pdev)
470{
471 int ret;
472
473 if (!smem_initialized_check())
474 return -ENODEV;
475
476 SMD_INFO("smd probe\n");
477 if (pdev) {
478 if (pdev->dev.of_node) {
479 pr_err("%s: invalid device tree init\n", __func__);
480 return -ENODEV;
481 } else if (pdev->dev.platform_data) {
482 ret = smd_core_platform_init(pdev);
483 if (ret) {
484 pr_err(
485 "SMD: smd_core_platform_init() failed\n");
486 return -ENODEV;
487 }
488 } else {
489 ret = smd_core_init();
490 if (ret) {
491 pr_err("smd_core_init() failed\n");
492 return -ENODEV;
493 }
494 }
495 } else {
496 pr_err("SMD: PDEV not found\n");
497 return -ENODEV;
498 }
499
500 ret = smsm_post_init();
501 if (ret) {
502 pr_err("smd_post_init() failed ret = %d\n", ret);
503 return ret;
504 }
Jeff Hugof4df2ff2013-08-28 17:45:50 -0600505 smd_post_init(1, 0);
Arun Kumar Neelakantam804f5162013-07-25 17:58:05 +0530506
507 return 0;
508}
509
510static struct platform_driver msm_smd_driver_legacy = {
511 .probe = msm_smd_probe_legacy,
512 .driver = {
513 .name = MODULE_NAME,
514 .owner = THIS_MODULE,
515 },
516};
517
518int msm_smd_driver_register(void)
519{
520
521 int rc;
522
523 rc = platform_driver_register(&msm_smd_driver_legacy);
524 if (rc) {
525 pr_err("%s: smd_driver register failed %d\n",
526 __func__, rc);
527 return rc;
528 }
529 return 0;
530}
531EXPORT_SYMBOL(msm_smd_driver_register);
532
533MODULE_DESCRIPTION("MSM SMD Legacy/Platform Device Init");
534MODULE_LICENSE("GPL v2");
535#endif