1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> 4 */ 5 6#include <common.h> 7#include <dm.h> 8#include <errno.h> 9#include <fdtdec.h> 10#include <irq.h> 11#include <log.h> 12#include <malloc.h> 13#include <asm/global_data.h> 14#include <asm/io.h> 15#include <asm/irq.h> 16#include <asm/pci.h> 17#include <asm/pirq_routing.h> 18#include <asm/tables.h> 19 20DECLARE_GLOBAL_DATA_PTR; 21 22/** 23 * pirq_reg_to_linkno() - Convert a PIRQ routing register offset to link number 24 * 25 * @priv: IRQ router driver's priv data 26 * @reg: PIRQ routing register offset from the base address 27 * @return: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc) 28 */ 29static inline int pirq_reg_to_linkno(struct irq_router *priv, int reg) 30{ 31 int linkno = 0; 32 33 if (priv->has_regmap) { 34 struct pirq_regmap *map = priv->regmap; 35 int i; 36 37 for (i = 0; i < priv->link_num; i++) { 38 if (reg - priv->link_base == map->offset) { 39 linkno = map->link; 40 break; 41 } 42 map++; 43 } 44 } else { 45 linkno = reg - priv->link_base; 46 } 47 48 return linkno; 49} 50 51/** 52 * pirq_linkno_to_reg() - Convert a PIRQ link number to routing register offset 53 * 54 * @priv: IRQ router driver's priv data 55 * @linkno: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc) 56 * @return: PIRQ routing register offset from the base address 57 */ 58static inline int pirq_linkno_to_reg(struct irq_router *priv, int linkno) 59{ 60 int reg = 0; 61 62 if (priv->has_regmap) { 63 struct pirq_regmap *map = priv->regmap; 64 int i; 65 66 for (i = 0; i < priv->link_num; i++) { 67 if (linkno == map->link) { 68 reg = map->offset + priv->link_base; 69 break; 70 } 71 map++; 72 } 73 } else { 74 reg = linkno + priv->link_base; 75 } 76 77 return reg; 78} 79 80bool pirq_check_irq_routed(struct udevice *dev, int link, u8 irq) 81{ 82 struct irq_router *priv = dev_get_priv(dev); 83 u8 pirq; 84 85 if (priv->config == PIRQ_VIA_PCI) 86 dm_pci_read_config8(dev->parent, 87 pirq_linkno_to_reg(priv, link), &pirq); 88 else 89 pirq = readb((uintptr_t)priv->ibase + 90 pirq_linkno_to_reg(priv, link)); 91 92 pirq &= 0xf; 93 94 /* IRQ# 0/1/2/8/13 are reserved */ 95 if (pirq < 3 || pirq == 8 || pirq == 13) 96 return false; 97 98 return pirq == irq ? true : false; 99} 100 101int pirq_translate_link(struct udevice *dev, int link) 102{ 103 struct irq_router *priv = dev_get_priv(dev); 104 105 return pirq_reg_to_linkno(priv, link); 106} 107 108void pirq_assign_irq(struct udevice *dev, int link, u8 irq) 109{ 110 struct irq_router *priv = dev_get_priv(dev); 111 112 /* IRQ# 0/1/2/8/13 are reserved */ 113 if (irq < 3 || irq == 8 || irq == 13) 114 return; 115 116 if (priv->config == PIRQ_VIA_PCI) 117 dm_pci_write_config8(dev->parent, 118 pirq_linkno_to_reg(priv, link), irq); 119 else 120 writeb(irq, (uintptr_t)priv->ibase + 121 pirq_linkno_to_reg(priv, link)); 122} 123 124static struct irq_info *check_dup_entry(struct irq_info *slot_base, 125 int entry_num, int bus, int device) 126{ 127 struct irq_info *slot = slot_base; 128 int i; 129 130 for (i = 0; i < entry_num; i++) { 131 if (slot->bus == bus && slot->devfn == (device << 3)) 132 break; 133 slot++; 134 } 135 136 return (i == entry_num) ? NULL : slot; 137} 138 139static inline void fill_irq_info(struct irq_router *priv, struct irq_info *slot, 140 int bus, int device, int pin, int pirq) 141{ 142 slot->bus = bus; 143 slot->devfn = (device << 3) | 0; 144 slot->irq[pin - 1].link = pirq_linkno_to_reg(priv, pirq); 145 slot->irq[pin - 1].bitmap = priv->irq_mask; 146} 147 148static int create_pirq_routing_table(struct udevice *dev) 149{ 150 struct irq_router *priv = dev_get_priv(dev); 151 const void *blob = gd->fdt_blob; 152 int node; 153 int len, count; 154 const u32 *cell; 155 struct pirq_regmap *map; 156 struct irq_routing_table *rt; 157 struct irq_info *slot, *slot_base; 158 int irq_entries = 0; 159 int i; 160 int ret; 161 162 node = dev_of_offset(dev); 163 164 /* extract the bdf from fdt_pci_addr */ 165 priv->bdf = dm_pci_get_bdf(dev->parent); 166 167 ret = fdt_stringlist_search(blob, node, "intel,pirq-config", "pci"); 168 if (!ret) { 169 priv->config = PIRQ_VIA_PCI; 170 } else { 171 ret = fdt_stringlist_search(blob, node, "intel,pirq-config", 172 "ibase"); 173 if (!ret) 174 priv->config = PIRQ_VIA_IBASE; 175 else 176 return -EINVAL; 177 } 178 179 cell = fdt_getprop(blob, node, "intel,pirq-link", &len); 180 if (!cell || len != 8) 181 return -EINVAL; 182 priv->link_base = fdt_addr_to_cpu(cell[0]); 183 priv->link_num = fdt_addr_to_cpu(cell[1]); 184 if (priv->link_num > CONFIG_MAX_PIRQ_LINKS) { 185 debug("Limiting supported PIRQ link number from %d to %d\n", 186 priv->link_num, CONFIG_MAX_PIRQ_LINKS); 187 priv->link_num = CONFIG_MAX_PIRQ_LINKS; 188 } 189 190 cell = fdt_getprop(blob, node, "intel,pirq-regmap", &len); 191 if (cell) { 192 if (len % sizeof(struct pirq_regmap)) 193 return -EINVAL; 194 195 count = len / sizeof(struct pirq_regmap); 196 if (count < priv->link_num) { 197 printf("Number of pirq-regmap entires is wrong\n"); 198 return -EINVAL; 199 } 200 201 count = priv->link_num; 202 priv->regmap = calloc(count, sizeof(struct pirq_regmap)); 203 if (!priv->regmap) 204 return -ENOMEM; 205 206 priv->has_regmap = true; 207 map = priv->regmap; 208 for (i = 0; i < count; i++) { 209 map->link = fdt_addr_to_cpu(cell[0]); 210 map->offset = fdt_addr_to_cpu(cell[1]); 211 212 cell += sizeof(struct pirq_regmap) / sizeof(u32); 213 map++; 214 } 215 } 216 217 priv->irq_mask = fdtdec_get_int(blob, node, 218 "intel,pirq-mask", PIRQ_BITMAP); 219 220 if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) { 221 /* Reserve IRQ9 for SCI */ 222 priv->irq_mask &= ~(1 << 9); 223 } 224 225 if (priv->config == PIRQ_VIA_IBASE) { 226 int ibase_off; 227 228 ibase_off = fdtdec_get_int(blob, node, "intel,ibase-offset", 0); 229 if (!ibase_off) 230 return -EINVAL; 231 232 /* 233 * Here we assume that the IBASE register has already been 234 * properly configured by U-Boot before. 235 * 236 * By 'valid' we mean: 237 * 1) a valid memory space carved within system memory space 238 * assigned to IBASE register block. 239 * 2) memory range decoding is enabled. 240 * Hence we don't do any santify test here. 241 */ 242 dm_pci_read_config32(dev->parent, ibase_off, &priv->ibase); 243 priv->ibase &= ~0xf; 244 } 245 246 priv->actl_8bit = fdtdec_get_bool(blob, node, "intel,actl-8bit"); 247 priv->actl_addr = fdtdec_get_int(blob, node, "intel,actl-addr", 0); 248 249 cell = fdt_getprop(blob, node, "intel,pirq-routing", &len); 250 if (!cell || len % sizeof(struct pirq_routing)) 251 return -EINVAL; 252 count = len / sizeof(struct pirq_routing); 253 254 rt = calloc(1, sizeof(struct irq_routing_table)); 255 if (!rt) 256 return -ENOMEM; 257 258 /* Populate the PIRQ table fields */ 259 rt->signature = PIRQ_SIGNATURE; 260 rt->version = PIRQ_VERSION; 261 rt->rtr_bus = PCI_BUS(priv->bdf); 262 rt->rtr_devfn = (PCI_DEV(priv->bdf) << 3) | PCI_FUNC(priv->bdf); 263 rt->rtr_vendor = PCI_VENDOR_ID_INTEL; 264 rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31; 265 266 slot_base = rt->slots; 267 268 /* Now fill in the irq_info entries in the PIRQ table */ 269 for (i = 0; i < count; 270 i++, cell += sizeof(struct pirq_routing) / sizeof(u32)) { 271 struct pirq_routing pr; 272 273 pr.bdf = fdt_addr_to_cpu(cell[0]); 274 pr.pin = fdt_addr_to_cpu(cell[1]); 275 pr.pirq = fdt_addr_to_cpu(cell[2]); 276 277 debug("irq_info %d: b.d.f %x.%x.%x INT%c PIRQ%c\n", 278 i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), 279 PCI_FUNC(pr.bdf), 'A' + pr.pin - 1, 280 'A' + pr.pirq); 281 282 slot = check_dup_entry(slot_base, irq_entries, 283 PCI_BUS(pr.bdf), PCI_DEV(pr.bdf)); 284 if (slot) { 285 debug("found entry for bus %d device %d, ", 286 PCI_BUS(pr.bdf), PCI_DEV(pr.bdf)); 287 288 if (slot->irq[pr.pin - 1].link) { 289 debug("skipping\n"); 290 291 /* 292 * Sanity test on the routed PIRQ pin 293 * 294 * If they don't match, show a warning to tell 295 * there might be something wrong with the PIRQ 296 * routing information in the device tree. 297 */ 298 if (slot->irq[pr.pin - 1].link != 299 pirq_linkno_to_reg(priv, pr.pirq)) 300 debug("WARNING: Inconsistent PIRQ routing information\n"); 301 continue; 302 } 303 } else { 304 slot = slot_base + irq_entries++; 305 } 306 debug("writing INT%c\n", 'A' + pr.pin - 1); 307 fill_irq_info(priv, slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), 308 pr.pin, pr.pirq); 309 } 310 311 rt->size = irq_entries * sizeof(struct irq_info) + 32; 312 313 /* Fix up the table checksum */ 314 rt->checksum = table_compute_checksum(rt, rt->size); 315 316 gd->arch.pirq_routing_table = rt; 317 318 return 0; 319} 320 321static void irq_enable_sci(struct udevice *dev) 322{ 323 struct irq_router *priv = dev_get_priv(dev); 324 325 if (priv->actl_8bit) { 326 /* Bit7 must be turned on to enable ACPI */ 327 dm_pci_write_config8(dev->parent, priv->actl_addr, 0x80); 328 } else { 329 /* Write 0 to enable SCI on IRQ9 */ 330 if (priv->config == PIRQ_VIA_PCI) 331 dm_pci_write_config32(dev->parent, priv->actl_addr, 0); 332 else 333 writel(0, (uintptr_t)priv->ibase + priv->actl_addr); 334 } 335} 336 337int irq_router_probe(struct udevice *dev) 338{ 339 int ret; 340 341 ret = create_pirq_routing_table(dev); 342 if (ret) { 343 debug("Failed to create pirq routing table\n"); 344 return ret; 345 } 346 /* Route PIRQ */ 347 pirq_route_irqs(dev, gd->arch.pirq_routing_table->slots, 348 get_irq_slot_count(gd->arch.pirq_routing_table)); 349 350 if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) 351 irq_enable_sci(dev); 352 353 return 0; 354} 355 356static const struct udevice_id irq_router_ids[] = { 357 { .compatible = "intel,irq-router", .data = X86_IRQT_BASE }, 358 { } 359}; 360 361U_BOOT_DRIVER(irq_router_drv) = { 362 .name = "intel_irq", 363 .id = UCLASS_IRQ, 364 .of_match = irq_router_ids, 365 .probe = irq_router_probe, 366 .priv_auto = sizeof(struct irq_router), 367}; 368