diff options
| -rw-r--r-- | drivers/irqchip/spear-shirq.c | 97 |
1 files changed, 45 insertions, 52 deletions
diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c index 8765aa7f7a15..169ef9a385d0 100644 --- a/drivers/irqchip/spear-shirq.c +++ b/drivers/irqchip/spear-shirq.c | |||
| @@ -49,7 +49,8 @@ struct shirq_regs { | |||
| 49 | * virq_base: Base virtual interrupt number | 49 | * virq_base: Base virtual interrupt number |
| 50 | * nr_irqs: Number of interrupts handled by this block | 50 | * nr_irqs: Number of interrupts handled by this block |
| 51 | * offset: Bit offset of the first interrupt | 51 | * offset: Bit offset of the first interrupt |
| 52 | * disabled: Group is disabled, but accounted | 52 | * irq_chip: Interrupt controller chip used for this instance, |
| 53 | * if NULL group is disabled, but accounted | ||
| 53 | */ | 54 | */ |
| 54 | struct spear_shirq { | 55 | struct spear_shirq { |
| 55 | void __iomem *base; | 56 | void __iomem *base; |
| @@ -58,19 +59,50 @@ struct spear_shirq { | |||
| 58 | u32 virq_base; | 59 | u32 virq_base; |
| 59 | u32 nr_irqs; | 60 | u32 nr_irqs; |
| 60 | u32 offset; | 61 | u32 offset; |
| 61 | bool disabled; | 62 | struct irq_chip *irq_chip; |
| 62 | }; | 63 | }; |
| 63 | 64 | ||
| 64 | static DEFINE_SPINLOCK(lock); | ||
| 65 | |||
| 66 | /* spear300 shared irq registers offsets and masks */ | 65 | /* spear300 shared irq registers offsets and masks */ |
| 67 | #define SPEAR300_INT_ENB_MASK_REG 0x54 | 66 | #define SPEAR300_INT_ENB_MASK_REG 0x54 |
| 68 | #define SPEAR300_INT_STS_MASK_REG 0x58 | 67 | #define SPEAR300_INT_STS_MASK_REG 0x58 |
| 69 | 68 | ||
| 69 | static DEFINE_RAW_SPINLOCK(shirq_lock); | ||
| 70 | |||
| 71 | static void shirq_irq_mask(struct irq_data *d) | ||
| 72 | { | ||
| 73 | struct spear_shirq *shirq = irq_data_get_irq_chip_data(d); | ||
| 74 | u32 val, shift = d->irq - shirq->virq_base + shirq->offset; | ||
| 75 | u32 __iomem *reg = shirq->base + shirq->regs.enb_reg; | ||
| 76 | |||
| 77 | raw_spin_lock(&shirq_lock); | ||
| 78 | val = readl(reg) & ~(0x1 << shift); | ||
| 79 | writel(val, reg); | ||
| 80 | raw_spin_unlock(&shirq_lock); | ||
| 81 | } | ||
| 82 | |||
| 83 | static void shirq_irq_unmask(struct irq_data *d) | ||
| 84 | { | ||
| 85 | struct spear_shirq *shirq = irq_data_get_irq_chip_data(d); | ||
| 86 | u32 val, shift = d->irq - shirq->virq_base + shirq->offset; | ||
| 87 | u32 __iomem *reg = shirq->base + shirq->regs.enb_reg; | ||
| 88 | |||
| 89 | raw_spin_lock(&shirq_lock); | ||
| 90 | val = readl(reg) | (0x1 << shift); | ||
| 91 | writel(val, reg); | ||
| 92 | raw_spin_unlock(&shirq_lock); | ||
| 93 | } | ||
| 94 | |||
| 95 | static struct irq_chip shirq_chip = { | ||
| 96 | .name = "spear-shirq", | ||
| 97 | .irq_mask = shirq_irq_mask, | ||
| 98 | .irq_unmask = shirq_irq_unmask, | ||
| 99 | }; | ||
| 100 | |||
| 70 | static struct spear_shirq spear300_shirq_ras1 = { | 101 | static struct spear_shirq spear300_shirq_ras1 = { |
| 71 | .offset = 0, | 102 | .offset = 0, |
| 72 | .nr_irqs = 9, | 103 | .nr_irqs = 9, |
| 73 | .mask = ((0x1 << 9) - 1) << 0, | 104 | .mask = ((0x1 << 9) - 1) << 0, |
| 105 | .irq_chip = &shirq_chip, | ||
| 74 | .regs = { | 106 | .regs = { |
| 75 | .enb_reg = SPEAR300_INT_ENB_MASK_REG, | 107 | .enb_reg = SPEAR300_INT_ENB_MASK_REG, |
| 76 | .status_reg = SPEAR300_INT_STS_MASK_REG, | 108 | .status_reg = SPEAR300_INT_STS_MASK_REG, |
| @@ -88,8 +120,8 @@ static struct spear_shirq spear310_shirq_ras1 = { | |||
| 88 | .offset = 0, | 120 | .offset = 0, |
| 89 | .nr_irqs = 8, | 121 | .nr_irqs = 8, |
| 90 | .mask = ((0x1 << 8) - 1) << 0, | 122 | .mask = ((0x1 << 8) - 1) << 0, |
| 123 | .irq_chip = &dummy_irq_chip, | ||
| 91 | .regs = { | 124 | .regs = { |
| 92 | .enb_reg = -1, | ||
| 93 | .status_reg = SPEAR310_INT_STS_MASK_REG, | 125 | .status_reg = SPEAR310_INT_STS_MASK_REG, |
| 94 | }, | 126 | }, |
| 95 | }; | 127 | }; |
| @@ -98,6 +130,7 @@ static struct spear_shirq spear310_shirq_ras2 = { | |||
| 98 | .offset = 8, | 130 | .offset = 8, |
| 99 | .nr_irqs = 5, | 131 | .nr_irqs = 5, |
| 100 | .mask = ((0x1 << 5) - 1) << 8, | 132 | .mask = ((0x1 << 5) - 1) << 8, |
| 133 | .irq_chip = &dummy_irq_chip, | ||
| 101 | .regs = { | 134 | .regs = { |
| 102 | .enb_reg = -1, | 135 | .enb_reg = -1, |
| 103 | .status_reg = SPEAR310_INT_STS_MASK_REG, | 136 | .status_reg = SPEAR310_INT_STS_MASK_REG, |
| @@ -108,8 +141,8 @@ static struct spear_shirq spear310_shirq_ras3 = { | |||
| 108 | .offset = 13, | 141 | .offset = 13, |
| 109 | .nr_irqs = 1, | 142 | .nr_irqs = 1, |
| 110 | .mask = ((0x1 << 1) - 1) << 13, | 143 | .mask = ((0x1 << 1) - 1) << 13, |
| 144 | .irq_chip = &dummy_irq_chip, | ||
| 111 | .regs = { | 145 | .regs = { |
| 112 | .enb_reg = -1, | ||
| 113 | .status_reg = SPEAR310_INT_STS_MASK_REG, | 146 | .status_reg = SPEAR310_INT_STS_MASK_REG, |
| 114 | }, | 147 | }, |
| 115 | }; | 148 | }; |
| @@ -118,8 +151,8 @@ static struct spear_shirq spear310_shirq_intrcomm_ras = { | |||
| 118 | .offset = 14, | 151 | .offset = 14, |
| 119 | .nr_irqs = 3, | 152 | .nr_irqs = 3, |
| 120 | .mask = ((0x1 << 3) - 1) << 14, | 153 | .mask = ((0x1 << 3) - 1) << 14, |
| 154 | .irq_chip = &dummy_irq_chip, | ||
| 121 | .regs = { | 155 | .regs = { |
| 122 | .enb_reg = -1, | ||
| 123 | .status_reg = SPEAR310_INT_STS_MASK_REG, | 156 | .status_reg = SPEAR310_INT_STS_MASK_REG, |
| 124 | }, | 157 | }, |
| 125 | }; | 158 | }; |
| @@ -140,15 +173,14 @@ static struct spear_shirq spear320_shirq_ras3 = { | |||
| 140 | .offset = 0, | 173 | .offset = 0, |
| 141 | .nr_irqs = 7, | 174 | .nr_irqs = 7, |
| 142 | .mask = ((0x1 << 7) - 1) << 0, | 175 | .mask = ((0x1 << 7) - 1) << 0, |
| 143 | .disabled = 1, | ||
| 144 | }; | 176 | }; |
| 145 | 177 | ||
| 146 | static struct spear_shirq spear320_shirq_ras1 = { | 178 | static struct spear_shirq spear320_shirq_ras1 = { |
| 147 | .offset = 7, | 179 | .offset = 7, |
| 148 | .nr_irqs = 3, | 180 | .nr_irqs = 3, |
| 149 | .mask = ((0x1 << 3) - 1) << 7, | 181 | .mask = ((0x1 << 3) - 1) << 7, |
| 182 | .irq_chip = &dummy_irq_chip, | ||
| 150 | .regs = { | 183 | .regs = { |
| 151 | .enb_reg = -1, | ||
| 152 | .status_reg = SPEAR320_INT_STS_MASK_REG, | 184 | .status_reg = SPEAR320_INT_STS_MASK_REG, |
| 153 | }, | 185 | }, |
| 154 | }; | 186 | }; |
| @@ -157,8 +189,8 @@ static struct spear_shirq spear320_shirq_ras2 = { | |||
| 157 | .offset = 10, | 189 | .offset = 10, |
| 158 | .nr_irqs = 1, | 190 | .nr_irqs = 1, |
| 159 | .mask = ((0x1 << 1) - 1) << 10, | 191 | .mask = ((0x1 << 1) - 1) << 10, |
| 192 | .irq_chip = &dummy_irq_chip, | ||
| 160 | .regs = { | 193 | .regs = { |
| 161 | .enb_reg = -1, | ||
| 162 | .status_reg = SPEAR320_INT_STS_MASK_REG, | 194 | .status_reg = SPEAR320_INT_STS_MASK_REG, |
| 163 | }, | 195 | }, |
| 164 | }; | 196 | }; |
| @@ -167,8 +199,8 @@ static struct spear_shirq spear320_shirq_intrcomm_ras = { | |||
| 167 | .offset = 11, | 199 | .offset = 11, |
| 168 | .nr_irqs = 11, | 200 | .nr_irqs = 11, |
| 169 | .mask = ((0x1 << 11) - 1) << 11, | 201 | .mask = ((0x1 << 11) - 1) << 11, |
| 202 | .irq_chip = &dummy_irq_chip, | ||
| 170 | .regs = { | 203 | .regs = { |
| 171 | .enb_reg = -1, | ||
| 172 | .status_reg = SPEAR320_INT_STS_MASK_REG, | 204 | .status_reg = SPEAR320_INT_STS_MASK_REG, |
| 173 | }, | 205 | }, |
| 174 | }; | 206 | }; |
| @@ -180,45 +212,6 @@ static struct spear_shirq *spear320_shirq_blocks[] = { | |||
| 180 | &spear320_shirq_intrcomm_ras, | 212 | &spear320_shirq_intrcomm_ras, |
| 181 | }; | 213 | }; |
| 182 | 214 | ||
| 183 | static void shirq_irq_mask_unmask(struct irq_data *d, bool mask) | ||
| 184 | { | ||
| 185 | struct spear_shirq *shirq = irq_data_get_irq_chip_data(d); | ||
| 186 | u32 val, offset = d->irq - shirq->virq_base; | ||
| 187 | unsigned long flags; | ||
| 188 | |||
| 189 | if (shirq->regs.enb_reg == -1) | ||
| 190 | return; | ||
| 191 | |||
| 192 | spin_lock_irqsave(&lock, flags); | ||
| 193 | val = readl(shirq->base + shirq->regs.enb_reg); | ||
| 194 | |||
| 195 | if (mask ^ shirq->regs.reset_to_enb) | ||
| 196 | val &= ~(0x1 << shirq->offset << offset); | ||
| 197 | else | ||
| 198 | val |= 0x1 << shirq->offset << offset; | ||
| 199 | |||
| 200 | writel(val, shirq->base + shirq->regs.enb_reg); | ||
| 201 | spin_unlock_irqrestore(&lock, flags); | ||
