1 /* 2 * Copyright (C) 2017 Marvell 3 * 4 * Hanna Hawa <hannah@marvell.com> 5 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> 6 * 7 * This file is licensed under the terms of the GNU General Public 8 * License version 2. This program is licensed "as is" without any 9 * warranty of any kind, whether express or implied. 10 */ 11 12 #include <linux/interrupt.h> 13 #include <linux/irq.h> 14 #include <linux/irqchip.h> 15 #include <linux/irqdomain.h> 16 #include <linux/kernel.h> 17 #include <linux/msi.h> 18 #include <linux/of_irq.h> 19 #include <linux/of_platform.h> 20 #include <linux/platform_device.h> 21 22 #include <dt-bindings/interrupt-controller/mvebu-icu.h> 23 24 #include "irq-mvebu-gicp.h" 25 26 /* ICU registers */ 27 #define ICU_SETSPI_NSR_AL 0x10 28 #define ICU_SETSPI_NSR_AH 0x14 29 #define ICU_CLRSPI_NSR_AL 0x18 30 #define ICU_CLRSPI_NSR_AH 0x1c 31 #define ICU_INT_CFG(x) (0x100 + 4 * (x)) 32 #define ICU_INT_ENABLE BIT(24) 33 #define ICU_IS_EDGE BIT(28) 34 #define ICU_GROUP_SHIFT 29 35 36 /* ICU definitions */ 37 #define ICU_MAX_IRQS 207 38 #define ICU_SATA0_ICU_ID 109 39 #define ICU_SATA1_ICU_ID 107 40 41 struct mvebu_icu { 42 struct irq_chip irq_chip; 43 void __iomem *base; 44 struct irq_domain *domain; 45 struct device *dev; 46 }; 47 48 struct mvebu_icu_irq_data { 49 struct mvebu_icu *icu; 50 unsigned int icu_group; 51 unsigned int type; 52 }; 53 54 static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg) 55 { 56 struct irq_data *d = irq_get_irq_data(desc->irq); 57 struct mvebu_icu_irq_data *icu_irqd = d->chip_data; 58 struct mvebu_icu *icu = icu_irqd->icu; 59 unsigned int icu_int; 60 61 if (msg->address_lo || msg->address_hi) { 62 /* Configure the ICU with irq number & type */ 63 icu_int = msg->data | ICU_INT_ENABLE; 64 if (icu_irqd->type & IRQ_TYPE_EDGE_RISING) 65 icu_int |= ICU_IS_EDGE; 66 icu_int |= icu_irqd->icu_group << ICU_GROUP_SHIFT; 67 } else { 68 /* De-configure the ICU */ 69 icu_int = 0; 70 } 71 72 writel_relaxed(icu_int, icu->base + ICU_INT_CFG(d->hwirq)); 73 74 /* 75 * The SATA unit has 2 ports, and a dedicated ICU entry per 76 * port. The ahci sata driver supports only one irq interrupt 77 * per SATA unit. To solve this conflict, we configure the 2 78 * SATA wired interrupts in the south bridge into 1 GIC 79 * interrupt in the north bridge. Even if only a single port 80 * is enabled, if sata node is enabled, both interrupts are 81 * configured (regardless of which port is actually in use). 82 */ 83 if (d->hwirq == ICU_SATA0_ICU_ID || d->hwirq == ICU_SATA1_ICU_ID) { 84 writel_relaxed(icu_int, 85 icu->base + ICU_INT_CFG(ICU_SATA0_ICU_ID)); 86 writel_relaxed(icu_int, 87 icu->base + ICU_INT_CFG(ICU_SATA1_ICU_ID)); 88 } 89 } 90 91 static int 92 mvebu_icu_irq_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec, 93 unsigned long *hwirq, unsigned int *type) 94 { 95 struct mvebu_icu *icu = d->host_data; 96 unsigned int icu_group; 97 98 /* Check the count of the parameters in dt */ 99 if (WARN_ON(fwspec->param_count < 3)) { 100 dev_err(icu->dev, "wrong ICU parameter count %d\n", 101 fwspec->param_count); 102 return -EINVAL; 103 } 104 105 /* Only ICU group type is handled */ 106 icu_group = fwspec->param[0]; 107 if (icu_group != ICU_GRP_NSR && icu_group != ICU_GRP_SR && 108 icu_group != ICU_GRP_SEI && icu_group != ICU_GRP_REI) { 109 dev_err(icu->dev, "wrong ICU group type %x\n", icu_group); 110 return -EINVAL; 111 } 112 113 *hwirq = fwspec->param[1]; 114 if (*hwirq >= ICU_MAX_IRQS) { 115 dev_err(icu->dev, "invalid interrupt number %ld\n", *hwirq); 116 return -EINVAL; 117 } 118 119 /* Mask the type to prevent wrong DT configuration */ 120 *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; 121 122 return 0; 123 } 124 125 static int 126 mvebu_icu_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, 127 unsigned int nr_irqs, void *args) 128 { 129 int err; 130 unsigned long hwirq; 131 struct irq_fwspec *fwspec = args; 132 struct mvebu_icu *icu = platform_msi_get_host_data(domain); 133 struct mvebu_icu_irq_data *icu_irqd; 134 135 icu_irqd = kmalloc(sizeof(*icu_irqd), GFP_KERNEL); 136 if (!icu_irqd) 137 return -ENOMEM; 138 139 err = mvebu_icu_irq_domain_translate(domain, fwspec, &hwirq, 140 &icu_irqd->type); 141 if (err) { 142 dev_err(icu->dev, "failed to translate ICU parameters\n"); 143 goto free_irqd; 144 } 145 146 icu_irqd->icu_group = fwspec->param[0]; 147 icu_irqd->icu = icu; 148 149 err = platform_msi_domain_alloc(domain, virq, nr_irqs); 150 if (err) { 151 dev_err(icu->dev, "failed to allocate ICU interrupt in parent domain\n"); 152 goto free_irqd; 153 } 154 155 /* Make sure there is no interrupt left pending by the firmware */ 156 err = irq_set_irqchip_state(virq, IRQCHIP_STATE_PENDING, false); 157 if (err) 158 goto free_msi; 159 160 err = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, 161 &icu->irq_chip, icu_irqd); 162 if (err) { 163 dev_err(icu->dev, "failed to set the data to IRQ domain\n"); 164 goto free_msi; 165 } 166 167 return 0; 168 169 free_msi: 170 platform_msi_domain_free(domain, virq, nr_irqs); 171 free_irqd: 172 kfree(icu_irqd); 173 return err; 174 } 175 176 static void 177 mvebu_icu_irq_domain_free(struct irq_domain *domain, unsigned int virq, 178 unsigned int nr_irqs) 179 { 180 struct irq_data *d = irq_get_irq_data(virq); 181 struct mvebu_icu_irq_data *icu_irqd = d->chip_data; 182 183 kfree(icu_irqd); 184 185 platform_msi_domain_free(domain, virq, nr_irqs); 186 } 187 188 static const struct irq_domain_ops mvebu_icu_domain_ops = { 189 .translate = mvebu_icu_irq_domain_translate, 190 .alloc = mvebu_icu_irq_domain_alloc, 191 .free = mvebu_icu_irq_domain_free, 192 }; 193 194 static int mvebu_icu_probe(struct platform_device *pdev) 195 { 196 struct mvebu_icu *icu; 197 struct device_node *node = pdev->dev.of_node; 198 struct device_node *gicp_dn; 199 struct resource *res; 200 phys_addr_t setspi, clrspi; 201 u32 i, icu_int; 202 int ret; 203 204 icu = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_icu), 205 GFP_KERNEL); 206 if (!icu) 207 return -ENOMEM; 208 209 icu->dev = &pdev->dev; 210 211 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 212 icu->base = devm_ioremap_resource(&pdev->dev, res); 213 if (IS_ERR(icu->base)) { 214 dev_err(&pdev->dev, "Failed to map icu base address.\n"); 215 return PTR_ERR(icu->base); 216 } 217 218 icu->irq_chip.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, 219 "ICU.%x", 220 (unsigned int)res->start); 221 if (!icu->irq_chip.name) 222 return -ENOMEM; 223 224 icu->irq_chip.irq_mask = irq_chip_mask_parent; 225 icu->irq_chip.irq_unmask = irq_chip_unmask_parent; 226 icu->irq_chip.irq_eoi = irq_chip_eoi_parent; 227 icu->irq_chip.irq_set_type = irq_chip_set_type_parent; 228 #ifdef CONFIG_SMP 229 icu->irq_chip.irq_set_affinity = irq_chip_set_affinity_parent; 230 #endif 231 232 /* 233 * We're probed after MSI domains have been resolved, so force 234 * resolution here. 235 */ 236 pdev->dev.msi_domain = of_msi_get_domain(&pdev->dev, node, 237 DOMAIN_BUS_PLATFORM_MSI); 238 if (!pdev->dev.msi_domain) 239 return -EPROBE_DEFER; 240 241 gicp_dn = irq_domain_get_of_node(pdev->dev.msi_domain); 242 if (!gicp_dn) 243 return -ENODEV; 244 245 ret = mvebu_gicp_get_doorbells(gicp_dn, &setspi, &clrspi); 246 if (ret) 247 return ret; 248 249 /* Set Clear/Set ICU SPI message address in AP */ 250 writel_relaxed(upper_32_bits(setspi), icu->base + ICU_SETSPI_NSR_AH); 251 writel_relaxed(lower_32_bits(setspi), icu->base + ICU_SETSPI_NSR_AL); 252 writel_relaxed(upper_32_bits(clrspi), icu->base + ICU_CLRSPI_NSR_AH); 253 writel_relaxed(lower_32_bits(clrspi), icu->base + ICU_CLRSPI_NSR_AL); 254 255 /* 256 * Clean all ICU interrupts with type SPI_NSR, required to 257 * avoid unpredictable SPI assignments done by firmware. 258 */ 259 for (i = 0 ; i < ICU_MAX_IRQS ; i++) { 260 icu_int = readl(icu->base + ICU_INT_CFG(i)); 261 if ((icu_int >> ICU_GROUP_SHIFT) == ICU_GRP_NSR) 262 writel_relaxed(0x0, icu->base + ICU_INT_CFG(i)); 263 } 264 265 icu->domain = 266 platform_msi_create_device_domain(&pdev->dev, ICU_MAX_IRQS, 267 mvebu_icu_write_msg, 268 &mvebu_icu_domain_ops, icu); 269 if (!icu->domain) { 270 dev_err(&pdev->dev, "Failed to create ICU domain\n"); 271 return -ENOMEM; 272 } 273 274 return 0; 275 } 276 277 static const struct of_device_id mvebu_icu_of_match[] = { 278 { .compatible = "marvell,cp110-icu", }, 279 {}, 280 }; 281 282 static struct platform_driver mvebu_icu_driver = { 283 .probe = mvebu_icu_probe, 284 .driver = { 285 .name = "mvebu-icu", 286 .of_match_table = mvebu_icu_of_match, 287 }, 288 }; 289 builtin_platform_driver(mvebu_icu_driver); 290