static u_int32_t xlp_pcib_read_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, int width) { uint32_t data = 0; uint64_t cfgaddr; int regindex = reg/sizeof(uint32_t); cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f)); if ((width == 2) && (reg & 1)) return 0xFFFFFFFF; else if ((width == 4) && (reg & 3)) return 0xFFFFFFFF; /* * The intline and int pin of SoC devices are DOA, except * for bridges (slot %8 == 1). * use the values we stashed in a writable PCI scratch reg. */ if (b == 0 && regindex == 0xf && s % 8 > 1) regindex = XLP_PCI_DEVSCRATCH_REG0; data = nlm_read_pci_reg(cfgaddr, regindex); if (width == 1) return ((data >> ((reg & 3) << 3)) & 0xff); else if (width == 2)
static u_int32_t xlp_pcib_read_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, int width) { uint32_t data = 0; uint64_t cfgaddr; int regindex = reg/sizeof(uint32_t); cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f)); if ((width == 2) && (reg & 1)) return 0xFFFFFFFF; else if ((width == 4) && (reg & 3)) return 0xFFFFFFFF; data = nlm_read_pci_reg(cfgaddr, regindex); /* * Fix up read data in some SoC devices * to emulate complete PCIe header */ if (b == 0) { int dev = s % 8; /* Fake intpin on config read for UART/I2C, USB, SD/Flash */ if (regindex == 0xf && (dev == 6 || dev == 2 || dev == 7)) data |= 0x1 << 8; /* Fake int pin */ } if (width == 1) return ((data >> ((reg & 3) << 3)) & 0xff); else if (width == 2)
static void xlp_add_soc_child(device_t pcib, device_t dev, int b, int s, int f) { struct pci_devinfo *dinfo; struct xlp_devinfo *xlp_dinfo; struct soc_dev_desc *si; uint64_t pcibase; int domain, node, irt, irq, flags, devoffset, num; uint16_t devid; domain = pcib_get_domain(dev); node = s / 8; devoffset = XLP_HDR_OFFSET(node, 0, s % 8, f); if (!nlm_dev_exists(devoffset)) return; /* Find if there is a desc for the SoC device */ devid = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_DEVICE, 2); si = xlp_find_soc_desc(devid); /* update flags and irq from desc if available */ irq = 0; flags = 0; if (si != NULL) { if (si->irqbase != 0) irq = si->irqbase + si->ndevs; flags = si->flags; si->ndevs++; } /* skip internal devices */ if ((flags & INTERNAL_DEV) != 0) return; /* PCIe interfaces are special, bug in Ax */ if (devid == PCI_DEVICE_ID_NLM_PCIE) { xlp_add_irq(node, xlp_pcie_link_irt(f), PIC_PCIE_0_IRQ + f); } else { /* Stash intline and pin in shadow reg for devices */ pcibase = nlm_pcicfg_base(devoffset); irt = nlm_irtstart(pcibase); num = nlm_irtnum(pcibase); if (irq != 0 && num > 0) { xlp_add_irq(node, irt, irq); nlm_write_reg(pcibase, XLP_PCI_DEVSCRATCH_REG0, (1 << 8) | irq); } } dinfo = pci_read_device(pcib, domain, b, s, f, sizeof(*xlp_dinfo)); if (dinfo == NULL) return; xlp_dinfo = (struct xlp_devinfo *)dinfo; xlp_dinfo->irq = irq; xlp_dinfo->flags = flags; /* memory resource from ecfg space, if MEM_RES_EMUL is set */ if ((flags & MEM_RES_EMUL) != 0) xlp_dinfo->mem_res_start = XLP_DEFAULT_IO_BASE + devoffset + XLP_IO_PCI_HDRSZ; pci_add_child(dev, dinfo); }
int nlm_board_eeprom_read(int node, int bus, int addr, int offs, uint8_t *buf, int sz) { int rd, i; char *err = NULL; eeprom_i2c_base = nlm_pcicfg_base(XLP_IO_I2C_OFFSET(node, bus)) + XLP_IO_PCI_HDRSZ; if (oc_wait_on_status(OC_STATUS_BUSY) < 0) { err = "Not idle"; goto err_exit; } /* write start */ if (oc_wr_cmd(addr, OC_COMMAND_START)) { err = "I2C write start failed."; goto err_exit; } if (oc_read_reg(OC_I2C_STATUS_REG) & OC_STATUS_NACK) { err = "No ack after start"; goto err_exit_stop; } if (oc_read_reg(OC_I2C_STATUS_REG) & OC_STATUS_AL) { err = "I2C Bus Arbitration Lost"; goto err_exit_stop; } /* Write offset */ if (oc_wr_cmd(offs, OC_COMMAND_WRITE)) { err = "I2C write slave offset failed."; goto err_exit_stop; } if (oc_read_reg(OC_I2C_STATUS_REG) & OC_STATUS_NACK) { err = "No ack after write"; goto err_exit_stop; } /* read start */ if (oc_wr_cmd(addr | 1, OC_COMMAND_START)) { err = "I2C read start failed."; goto err_exit_stop; } if (oc_read_reg(OC_I2C_STATUS_REG) & OC_STATUS_NACK) { err = "No ack after read start"; goto err_exit_stop; } for (i = 0; i < sz - 1; i++) { if ((rd = oc_rd_cmd(OC_COMMAND_READ)) < 0) { err = "I2C read data byte failed."; goto err_exit_stop; } buf[i] = rd; } /* last byte */ if ((rd = oc_rd_cmd(OC_COMMAND_RDNACK)) < 0) { err = "I2C read last data byte failed."; goto err_exit_stop; } buf[sz - 1] = rd; err_exit_stop: oc_write_reg(OC_I2C_CMD_REG, OC_COMMAND_STOP); if (oc_wait_on_status(OC_STATUS_BUSY) < 0) printf("%s: stop failed", __func__); err_exit: if (err) { printf("%s: Failed (%s)\n", __func__, err); return (-1); } return (0); }