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