ath9k: merge a few bugfixes
[openwrt/openwrt.git] / package / lqtapi / src / mps / mps-irq.c
1 #include <linux/interrupt.h>
2 #include <linux/kernel_stat.h>
3 #include <ifxmips_irq.h>
4
5 #include "mps.h"
6 #include "mps-irq.h"
7
8 #define MPS_REG_AD0_IRQ_BASE 0x40
9 #define MPS_REG_AD1_IRQ_BASE 0x44
10
11 #define MPS_REG_AD_IRQ_STATUS 0x00
12 #define MPS_REG_AD_IRQ_SET 0x08
13 #define MPS_REG_AD_IRQ_CLEAR 0x10
14 #define MPS_REG_AD_IRQ_ENABLE 0x18
15
16 struct mps_irq_desc
17 {
18 void __iomem *base;
19 unsigned int irq_base;
20 };
21
22 static inline unsigned int mps_irq_bit(struct mps_irq_desc *mps_desc, int irq)
23 {
24 return BIT(irq - mps_desc->irq_base);
25 }
26
27 static void mps_irq_ack(unsigned int irq)
28 {
29 struct mps_irq_desc *mps_desc = get_irq_chip_data(irq);
30
31 __raw_writel(mps_irq_bit(mps_desc, irq),
32 mps_desc->base + MPS_REG_AD_IRQ_CLEAR);
33 }
34
35 static void mps_irq_mask(unsigned int irq)
36 {
37 struct mps_irq_desc *mps_desc = get_irq_chip_data(irq);
38 uint32_t mask;
39
40 mask = __raw_readl(mps_desc->base + MPS_REG_AD_IRQ_ENABLE);
41 mask &= ~mps_irq_bit(mps_desc, irq);
42 __raw_writel(mask, mps_desc->base + MPS_REG_AD_IRQ_ENABLE);
43 }
44
45 static void mps_irq_unmask(unsigned int irq)
46 {
47 struct mps_irq_desc *mps_desc = get_irq_chip_data(irq);
48 uint32_t mask;
49
50 mask = __raw_readl(mps_desc->base + MPS_REG_AD_IRQ_ENABLE);
51 mask |= mps_irq_bit(mps_desc, irq) | 0xffff;
52 __raw_writel(mask, mps_desc->base + MPS_REG_AD_IRQ_ENABLE);
53 }
54
55 static struct irq_chip mps_irq_chip = {
56 .name = "mps",
57 .ack = mps_irq_ack,
58 .mask = mps_irq_mask,
59 .unmask = mps_irq_unmask,
60 };
61
62 static void mps_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
63 {
64 struct mps_irq_desc *mps_desc = get_irq_data(irq);
65 uint32_t val;
66 int mps_irq;
67
68 desc->chip->mask(irq);
69
70 val = __raw_readl(mps_desc->base + MPS_REG_AD_IRQ_STATUS);
71 mps_irq = ffs(val);
72
73 /* printk("irq: %d %x\n", mps_irq, val);*/
74
75 if (mps_irq > 16)
76 printk("PANIC!\n");
77
78 if (mps_irq)
79 generic_handle_irq(mps_irq + mps_desc->irq_base - 1);
80
81 desc->chip->ack(irq);
82 desc->chip->unmask(irq);
83 }
84
85 #if 0
86
87 static const uint32_t ring_msg[] = {
88 0x01010004, 0x00030000,
89 };
90
91 static irqreturn_t mps_irq_ad0(int irq, void *devid)
92 {
93 struct mps *mps = devid;
94 uint32_t val;
95
96 val = __raw_readl(mps->base + MPS_REG_AD0_IRQ_STATUS);
97 printk("WOHO ein IRQ: %x\n", val);
98 __raw_writel(val, mps->base + MPS_REG_AD0_IRQ_CLEAR);
99
100 if (val & BIT(MPS_IRQ_DOWNLOAD_DONE))
101 complete(&mps->init_completion);
102
103 if (val & BIT(MPS_IRQ_EVENT))
104 mps_fifo_in(&mps->mbox_cmd.downstream, ring_msg, ARRAY_SIZE(ring_msg));
105
106 return IRQ_HANDLED;
107 }
108 #endif
109
110 #define MPS_NUM_AD_IRQS 32
111
112 struct mps_irq_desc mps_irq_descs[2];
113
114 int mps_irq_init(struct mps *mps)
115 {
116 int ret = 0;
117 int irq;
118
119 mps_irq_descs[0].base = mps->base + MPS_REG_AD0_IRQ_BASE;
120 mps_irq_descs[0].irq_base = mps->irq_base;
121 mps_irq_descs[1].base = mps->base + MPS_REG_AD1_IRQ_BASE;
122 mps_irq_descs[1].irq_base = mps->irq_base + 16;
123
124
125 set_irq_data(mps->irq_ad0, &mps_irq_descs[0]);
126 set_irq_chained_handler(mps->irq_ad0, mps_irq_demux_handler);
127 set_irq_data(mps->irq_ad1, &mps_irq_descs[1]);
128 set_irq_chained_handler(mps->irq_ad1, mps_irq_demux_handler);
129
130 /*
131 ret = request_irq(mps->irq_ad0, mps_irq_demux_handler, IRQF_DISABLED,
132 "mps ad0", &mps_irq_descs[0]);
133 ret = request_irq(mps->irq_ad1, mps_irq_demux_handler, IRQF_DISABLED,
134 "mps ad0", &mps_irq_descs[1]);
135 */
136 for (irq = 0; irq < MPS_NUM_AD_IRQS; ++irq) {
137 set_irq_chip_data(irq + mps->irq_base, &mps_irq_descs[irq / 16]);
138 set_irq_chip_and_handler(irq + mps->irq_base, &mps_irq_chip, handle_level_irq);
139 }
140
141
142 /*
143 res = request_irq(INT_NUM_IM4_IRL18, mps_irq_ad0, IRQF_DISABLED,
144 "mps ad0", mps);
145
146 irqs = BIT(MPS_IRQ_CMD_UPSTREAM) | BIT(MPS_IRQ_DATA_UPSTREAM)
147 | BIT(MPS_IRQ_DOWNLOAD_DONE) | BIT(MPS_IRQ_EVENT) | BIT(MPS_IRQ_CMD_ERROR);
148
149 __raw_writel(irqs, mps->base + MPS_REG_AD0_IRQ_ENA);
150 */
151 return ret;
152 }
153
154 void mps_irq_exit(struct mps *mps)
155 {
156 free_irq(INT_NUM_IM4_IRL18, mps);
157 }