]>
git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - arch/arm/mach-ux500/modem-irq-db5500.c
2 * Copyright (C) ST-Ericsson SA 2010
3 * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
4 * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
5 * License terms: GNU General Public License (GPL), version 2.
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/irq.h>
11 #include <linux/interrupt.h>
13 #include <linux/slab.h>
17 #define MODEM_INTCON_BASE_ADDR 0xBFFD3000
18 #define MODEM_INTCON_SIZE 0xFFF
20 #define DEST_IRQ41_OFFSET 0x2A4
21 #define DEST_IRQ43_OFFSET 0x2AC
22 #define DEST_IRQ45_OFFSET 0x2B4
24 #define PRIO_IRQ41_OFFSET 0x6A4
25 #define PRIO_IRQ43_OFFSET 0x6AC
26 #define PRIO_IRQ45_OFFSET 0x6B4
28 #define ALLOW_IRQ_OFFSET 0x104
30 #define MODEM_INTCON_CPU_NBR 0x1
31 #define MODEM_INTCON_PRIO_HIGH 0x0
33 #define MODEM_INTCON_ALLOW_IRQ41 0x0200
34 #define MODEM_INTCON_ALLOW_IRQ43 0x0800
35 #define MODEM_INTCON_ALLOW_IRQ45 0x2000
37 #define MODEM_IRQ_REG_OFFSET 0x4
40 void __iomem
*modem_intcon_base
;
44 static void setup_modem_intcon(void __iomem
*modem_intcon_base
)
46 /* IC_DESTINATION_BASE_ARRAY - Which CPU to receive the IRQ */
47 writel(MODEM_INTCON_CPU_NBR
, modem_intcon_base
+ DEST_IRQ41_OFFSET
);
48 writel(MODEM_INTCON_CPU_NBR
, modem_intcon_base
+ DEST_IRQ43_OFFSET
);
49 writel(MODEM_INTCON_CPU_NBR
, modem_intcon_base
+ DEST_IRQ45_OFFSET
);
51 /* IC_PRIORITY_BASE_ARRAY - IRQ priority in modem IRQ controller */
52 writel(MODEM_INTCON_PRIO_HIGH
, modem_intcon_base
+ PRIO_IRQ41_OFFSET
);
53 writel(MODEM_INTCON_PRIO_HIGH
, modem_intcon_base
+ PRIO_IRQ43_OFFSET
);
54 writel(MODEM_INTCON_PRIO_HIGH
, modem_intcon_base
+ PRIO_IRQ45_OFFSET
);
56 /* IC_ALLOW_ARRAY - IRQ enable */
57 writel(MODEM_INTCON_ALLOW_IRQ41
|
58 MODEM_INTCON_ALLOW_IRQ43
|
59 MODEM_INTCON_ALLOW_IRQ45
,
60 modem_intcon_base
+ ALLOW_IRQ_OFFSET
);
63 static irqreturn_t
modem_cpu_irq_handler(int irq
, void *data
)
67 struct modem_irq
*mi
= (struct modem_irq
*)data
;
69 /* Read modem side IRQ number from modem IRQ controller */
70 real_irq
= readl(mi
->modem_intcon_base
+ MODEM_IRQ_REG_OFFSET
) & 0xFF;
71 virt_irq
= IRQ_MODEM_EVENTS_BASE
+ real_irq
;
73 pr_debug("modem_irq: Worker read addr 0x%X and got value 0x%X "
74 "which will be 0x%X (%d) which translates to "
75 "virtual IRQ 0x%X (%d)!\n",
76 (u32
)mi
->modem_intcon_base
+ MODEM_IRQ_REG_OFFSET
,
84 generic_handle_irq(virt_irq
);
86 pr_debug("modem_irq: Done handling virtual IRQ %d!\n", virt_irq
);
91 static void create_virtual_irq(int irq
, struct irq_chip
*modem_irq_chip
)
93 set_irq_chip(irq
, modem_irq_chip
);
94 set_irq_handler(irq
, handle_simple_irq
);
95 set_irq_flags(irq
, IRQF_VALID
);
97 pr_debug("modem_irq: Created virtual IRQ %d\n", irq
);
100 static int modem_irq_init(void)
103 static struct irq_chip modem_irq_chip
;
104 struct modem_irq
*mi
;
109 pr_info("modem_irq: Set up IRQ handler for incoming modem IRQ %d\n",
112 mi
= kmalloc(sizeof(struct modem_irq
), GFP_KERNEL
);
114 pr_err("modem_irq: Could not allocate device\n");
118 mi
->modem_intcon_base
=
119 ioremap(MODEM_INTCON_BASE_ADDR
, MODEM_INTCON_SIZE
);
120 pr_debug("modem_irq: ioremapped modem_intcon_base from "
121 "phy 0x%x to virt 0x%x\n", MODEM_INTCON_BASE_ADDR
,
122 (u32
)mi
->modem_intcon_base
);
124 setup_modem_intcon(mi
->modem_intcon_base
);
126 modem_irq_chip
= dummy_irq_chip
;
127 modem_irq_chip
.name
= "modem_irq";
129 /* Create the virtual IRQ:s needed */
130 create_virtual_irq(MBOX_PAIR0_VIRT_IRQ
, &modem_irq_chip
);
131 create_virtual_irq(MBOX_PAIR1_VIRT_IRQ
, &modem_irq_chip
);
132 create_virtual_irq(MBOX_PAIR2_VIRT_IRQ
, &modem_irq_chip
);
134 err
= request_threaded_irq(IRQ_DB5500_MODEM
, NULL
,
135 modem_cpu_irq_handler
, IRQF_ONESHOT
,
138 pr_err("modem_irq: Could not register IRQ %d\n",
144 arch_initcall(modem_irq_init
);