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