1 /* 2 * Copyright (C) 2015 Freescale Semiconductor, Inc. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9 #include <linux/of_address.h> 10 #include <linux/of_irq.h> 11 #include <linux/slab.h> 12 #include <linux/irqchip.h> 13 #include <linux/syscore_ops.h> 14 15 #define IMR_NUM 4 16 #define GPC_MAX_IRQS (IMR_NUM * 32) 17 18 #define GPC_IMR1_CORE0 0x30 19 #define GPC_IMR1_CORE1 0x40 20 #define GPC_IMR1_CORE2 0x1c0 21 #define GPC_IMR1_CORE3 0x1d0 22 23 24 struct gpcv2_irqchip_data { 25 struct raw_spinlock rlock; 26 void __iomem *gpc_base; 27 u32 wakeup_sources[IMR_NUM]; 28 u32 saved_irq_mask[IMR_NUM]; 29 u32 cpu2wakeup; 30 }; 31 32 static struct gpcv2_irqchip_data *imx_gpcv2_instance; 33 34 static void __iomem *gpcv2_idx_to_reg(struct gpcv2_irqchip_data *cd, int i) 35 { 36 return cd->gpc_base + cd->cpu2wakeup + i * 4; 37 } 38 39 static int gpcv2_wakeup_source_save(void) 40 { 41 struct gpcv2_irqchip_data *cd; 42 void __iomem *reg; 43 int i; 44 45 cd = imx_gpcv2_instance; 46 if (!cd) 47 return 0; 48 49 for (i = 0; i < IMR_NUM; i++) { 50 reg = gpcv2_idx_to_reg(cd, i); 51 cd->saved_irq_mask[i] = readl_relaxed(reg); 52 writel_relaxed(cd->wakeup_sources[i], reg); 53 } 54 55 return 0; 56 } 57 58 static void gpcv2_wakeup_source_restore(void) 59 { 60 struct gpcv2_irqchip_data *cd; 61 int i; 62 63 cd = imx_gpcv2_instance; 64 if (!cd) 65 return; 66 67 for (i = 0; i < IMR_NUM; i++) 68 writel_relaxed(cd->saved_irq_mask[i], gpcv2_idx_to_reg(cd, i)); 69 } 70 71 static struct syscore_ops imx_gpcv2_syscore_ops = { 72 .suspend = gpcv2_wakeup_source_save, 73 .resume = gpcv2_wakeup_source_restore, 74 }; 75 76 static int imx_gpcv2_irq_set_wake(struct irq_data *d, unsigned int on) 77 { 78 struct gpcv2_irqchip_data *cd = d->chip_data; 79 unsigned int idx = d->hwirq / 32; 80 unsigned long flags; 81 u32 mask, val; 82 83 raw_spin_lock_irqsave(&cd->rlock, flags); 84 mask = BIT(d->hwirq % 32); 85 val = cd->wakeup_sources[idx]; 86 87 cd->wakeup_sources[idx] = on ? (val & ~mask) : (val | mask); 88 raw_spin_unlock_irqrestore(&cd->rlock, flags); 89 90 /* 91 * Do *not* call into the parent, as the GIC doesn't have any 92 * wake-up facility... 93 */ 94 95 return 0; 96 } 97 98 static void imx_gpcv2_irq_unmask(struct irq_data *d) 99 { 100 struct gpcv2_irqchip_data *cd = d->chip_data; 101 void __iomem *reg; 102 u32 val; 103 104 raw_spin_lock(&cd->rlock); 105 reg = gpcv2_idx_to_reg(cd, d->hwirq / 32); 106 val = readl_relaxed(reg); 107 val &= ~BIT(d->hwirq % 32); 108 writel_relaxed(val, reg); 109 raw_spin_unlock(&cd->rlock); 110 111 irq_chip_unmask_parent(d); 112 } 113 114 static void imx_gpcv2_irq_mask(struct irq_data *d) 115 { 116 struct gpcv2_irqchip_data *cd = d->chip_data; 117 void __iomem *reg; 118 u32 val; 119 120 raw_spin_lock(&cd->rlock); 121 reg = gpcv2_idx_to_reg(cd, d->hwirq / 32); 122 val = readl_relaxed(reg); 123 val |= BIT(d->hwirq % 32); 124 writel_relaxed(val, reg); 125 raw_spin_unlock(&cd->rlock); 126 127 irq_chip_mask_parent(d); 128 } 129 130 static struct irq_chip gpcv2_irqchip_data_chip = { 131 .name = "GPCv2", 132 .irq_eoi = irq_chip_eoi_parent, 133 .irq_mask = imx_gpcv2_irq_mask, 134 .irq_unmask = imx_gpcv2_irq_unmask, 135 .irq_set_wake = imx_gpcv2_irq_set_wake, 136 .irq_retrigger = irq_chip_retrigger_hierarchy, 137 #ifdef CONFIG_SMP 138 .irq_set_affinity = irq_chip_set_affinity_parent, 139 #endif 140 }; 141 142 static int imx_gpcv2_domain_translate(struct irq_domain *d, 143 struct irq_fwspec *fwspec, 144 unsigned long *hwirq, 145 unsigned int *type) 146 { 147 if (is_of_node(fwspec->fwnode)) { 148 if (fwspec->param_count != 3) 149 return -EINVAL; 150 151 /* No PPI should point to this domain */ 152 if (fwspec->param[0] != 0) 153 return -EINVAL; 154 155 *hwirq = fwspec->param[1]; 156 *type = fwspec->param[2]; 157 return 0; 158 } 159 160 return -EINVAL; 161 } 162 163 static int imx_gpcv2_domain_alloc(struct irq_domain *domain, 164 unsigned int irq, unsigned int nr_irqs, 165 void *data) 166 { 167 struct irq_fwspec *fwspec = data; 168 struct irq_fwspec parent_fwspec; 169 irq_hw_number_t hwirq; 170 unsigned int type; 171 int err; 172 int i; 173 174 err = imx_gpcv2_domain_translate(domain, fwspec, &hwirq, &type); 175 if (err) 176 return err; 177 178 if (hwirq >= GPC_MAX_IRQS) 179 return -EINVAL; 180 181 for (i = 0; i < nr_irqs; i++) { 182 irq_domain_set_hwirq_and_chip(domain, irq + i, hwirq + i, 183 &gpcv2_irqchip_data_chip, domain->host_data); 184 } 185 186 parent_fwspec = *fwspec; 187 parent_fwspec.fwnode = domain->parent->fwnode; 188 return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, 189 &parent_fwspec); 190 } 191 192 static const struct irq_domain_ops gpcv2_irqchip_data_domain_ops = { 193 .translate = imx_gpcv2_domain_translate, 194 .alloc = imx_gpcv2_domain_alloc, 195 .free = irq_domain_free_irqs_common, 196 }; 197 198 static const struct of_device_id gpcv2_of_match[] = { 199 { .compatible = "fsl,imx7d-gpc", .data = (const void *) 2 }, 200 { .compatible = "fsl,imx8mq-gpc", .data = (const void *) 4 }, 201 { /* END */ } 202 }; 203 204 static int __init imx_gpcv2_irqchip_init(struct device_node *node, 205 struct device_node *parent) 206 { 207 struct irq_domain *parent_domain, *domain; 208 struct gpcv2_irqchip_data *cd; 209 const struct of_device_id *id; 210 unsigned long core_num; 211 int i; 212 213 if (!parent) { 214 pr_err("%pOF: no parent, giving up\n", node); 215 return -ENODEV; 216 } 217 218 id = of_match_node(gpcv2_of_match, node); 219 if (!id) { 220 pr_err("%pOF: unknown compatibility string\n", node); 221 return -ENODEV; 222 } 223 224 core_num = (unsigned long)id->data; 225 226 parent_domain = irq_find_host(parent); 227 if (!parent_domain) { 228 pr_err("%pOF: unable to get parent domain\n", node); 229 return -ENXIO; 230 } 231 232 cd = kzalloc(sizeof(struct gpcv2_irqchip_data), GFP_KERNEL); 233 if (!cd) { 234 pr_err("%pOF: kzalloc failed!\n", node); 235 return -ENOMEM; 236 } 237 238 raw_spin_lock_init(&cd->rlock); 239 240 cd->gpc_base = of_iomap(node, 0); 241 if (!cd->gpc_base) { 242 pr_err("%pOF: unable to map gpc registers\n", node); 243 kfree(cd); 244 return -ENOMEM; 245 } 246 247 domain = irq_domain_add_hierarchy(parent_domain, 0, GPC_MAX_IRQS, 248 node, &gpcv2_irqchip_data_domain_ops, cd); 249 if (!domain) { 250 iounmap(cd->gpc_base); 251 kfree(cd); 252 return -ENOMEM; 253 } 254 irq_set_default_host(domain); 255 256 /* Initially mask all interrupts */ 257 for (i = 0; i < IMR_NUM; i++) { 258 void __iomem *reg = cd->gpc_base + i * 4; 259 260 switch (core_num) { 261 case 4: 262 writel_relaxed(~0, reg + GPC_IMR1_CORE2); 263 writel_relaxed(~0, reg + GPC_IMR1_CORE3); 264 /* fall through */ 265 case 2: 266 writel_relaxed(~0, reg + GPC_IMR1_CORE0); 267 writel_relaxed(~0, reg + GPC_IMR1_CORE1); 268 } 269 cd->wakeup_sources[i] = ~0; 270 } 271 272 /* Let CORE0 as the default CPU to wake up by GPC */ 273 cd->cpu2wakeup = GPC_IMR1_CORE0; 274 275 /* 276 * Due to hardware design failure, need to make sure GPR 277 * interrupt(#32) is unmasked during RUN mode to avoid entering 278 * DSM by mistake. 279 */ 280 writel_relaxed(~0x1, cd->gpc_base + cd->cpu2wakeup); 281 282 imx_gpcv2_instance = cd; 283 register_syscore_ops(&imx_gpcv2_syscore_ops); 284 285 /* 286 * Clear the OF_POPULATED flag set in of_irq_init so that 287 * later the GPC power domain driver will not be skipped. 288 */ 289 of_node_clear_flag(node, OF_POPULATED); 290 return 0; 291 } 292 293 IRQCHIP_DECLARE(imx_gpcv2_imx7d, "fsl,imx7d-gpc", imx_gpcv2_irqchip_init); 294 IRQCHIP_DECLARE(imx_gpcv2_imx8mq, "fsl,imx8mq-gpc", imx_gpcv2_irqchip_init); 295