void fsp_epow_init(void) { struct dt_node *np; fsp_register_client(&fsp_epow_client, FSP_MCLASS_SERVICE); opal_register(OPAL_GET_EPOW_STATUS, fsp_opal_get_epow_status, 2); np = dt_new(opal_node, "epow"); dt_add_property_strings(np, "compatible", "ibm,opal-v3-epow"); dt_add_property_strings(np, "epow-classes", "power", "temperature", "cooling"); prlog(PR_TRACE, "FSP EPOW support initialized\n"); }
static struct dt_node *get_bus_node(struct dt_node *i2cm, int port, int freq) { struct dt_node *bus; bus = dt_find_by_name_addr(i2cm, "i2c-bus", port); if (!bus) { bus = dt_new_addr(i2cm, "i2c-bus", port); dt_add_property_cells(bus, "reg", port); dt_add_property_cells(bus, "#size-cells", 0); dt_add_property_cells(bus, "#address-cells", 1); /* The P9 I2C master is fully compatible with the P8 one */ dt_add_property_strings(bus, "compatible", "ibm,opal-i2c", "ibm,power8-i2c-port", "ibm,power9-i2c-port"); /* * use the clock frequency as the bus frequency until we * have actual devices on the bus. Adding a device will * reduce the frequency to something that all devices * can tolerate. */ dt_add_property_cells(bus, "bus-frequency", freq * 1000); } return bus; }
static struct dt_node *get_i2cm_node(struct dt_node *xscom, int engine) { uint64_t xscom_base = P9_I2CM_XSCOM_BASE + P9_I2CM_XSCOM_SIZE * (uint64_t)engine; struct dt_node *i2cm; uint64_t freq, clock; i2cm = dt_find_by_name_addr(xscom, "i2cm", xscom_base); if (!i2cm) { i2cm = dt_new_addr(xscom, "i2cm", xscom_base); dt_add_property_cells(i2cm, "reg", xscom_base, P9_I2CM_XSCOM_SIZE); dt_add_property_strings(i2cm, "compatible", "ibm,power8-i2cm", "ibm,power9-i2cm"); dt_add_property_cells(i2cm, "#size-cells", 0); dt_add_property_cells(i2cm, "#address-cells", 1); dt_add_property_cells(i2cm, "chip-engine#", engine); freq = dt_prop_get_u64_def(xscom, "bus-frequency", 0); clock = (u32)(freq / 4); if (clock) dt_add_property_cells(i2cm, "clock-frequency", clock); else dt_add_property_cells(i2cm, "clock-frequency", 150000000); } return i2cm; }
void ipmi_rtc_init(void) { struct dt_node *np = dt_new(opal_node, "rtc"); dt_add_property_strings(np, "compatible", "ibm,opal-rtc"); opal_register(OPAL_RTC_READ, ipmi_opal_rtc_read, 2); opal_register(OPAL_RTC_WRITE, ipmi_opal_rtc_write, 2); /* Initialise the rtc cache */ ipmi_get_sel_time(); }
void ipmi_opal_init(void) { struct dt_node *opal_ipmi; opal_ipmi = dt_new(opal_node, "ipmi"); dt_add_property_strings(opal_ipmi, "compatible", "ibm,opal-ipmi"); dt_add_property_cells(opal_ipmi, "ibm,ipmi-interface-id", IPMI_DEFAULT_INTERFACE); dt_add_property_cells(opal_ipmi, "interrupts", ilog2(ipmi_backend->opal_event_ipmi_recv)); opal_register(OPAL_IPMI_SEND, opal_ipmi_send, 3); opal_register(OPAL_IPMI_RECV, opal_ipmi_recv, 3); }
static struct dt_node *dt_create_i2c_bus(struct dt_node *i2cm, const char *port_name, uint32_t port_id) { static struct dt_node *port; port = dt_new_addr(i2cm, "i2c-bus", port_id); if (!port) return NULL; dt_add_property_strings(port, "compatible", "ibm,power8-i2c-port", "ibm,opal-i2c"); dt_add_property_string(port, "ibm,port-name", port_name); dt_add_property_cells(port, "reg", port_id); dt_add_property_cells(port, "bus-frequency", 400000); dt_add_property_cells(port, "#address-cells", 1); dt_add_property_cells(port, "#size-cells", 0); return port; }
static struct dt_node *flash_add_dt_node(struct flash *flash, int id) { int i; int rc; const char *name; bool ecc; struct ffs_handle *ffs; int ffs_part_num, ffs_part_start, ffs_part_size; struct dt_node *flash_node; struct dt_node *partition_container_node; struct dt_node *partition_node; flash_node = dt_new_addr(opal_node, "flash", id); dt_add_property_strings(flash_node, "compatible", "ibm,opal-flash"); dt_add_property_cells(flash_node, "ibm,opal-id", id); dt_add_property_u64(flash_node, "reg", flash->size); dt_add_property_cells(flash_node, "ibm,flash-block-size", flash->block_size); if (flash->no_erase) dt_add_property(flash_node, "no-erase", NULL, 0); /* we fix to 32-bits */ dt_add_property_cells(flash_node, "#address-cells", 1); dt_add_property_cells(flash_node, "#size-cells", 1); /* Add partition container node */ partition_container_node = dt_new(flash_node, "partitions"); dt_add_property_strings(partition_container_node, "compatible", "fixed-partitions"); /* we fix to 32-bits */ dt_add_property_cells(partition_container_node, "#address-cells", 1); dt_add_property_cells(partition_container_node, "#size-cells", 1); /* Add partitions */ for (i = 0, name = NULL; i < ARRAY_SIZE(part_name_map); i++) { name = part_name_map[i].name; rc = ffs_init(0, flash->size, flash->bl, &ffs, 1); if (rc) { prerror("FLASH: Can't open ffs handle\n"); continue; } rc = ffs_lookup_part(ffs, name, &ffs_part_num); if (rc) { /* This is not an error per-se, some partitions * are purposefully absent, don't spam the logs */ prlog(PR_DEBUG, "FLASH: No %s partition\n", name); continue; } rc = ffs_part_info(ffs, ffs_part_num, NULL, &ffs_part_start, NULL, &ffs_part_size, &ecc); if (rc) { prerror("FLASH: Failed to get %s partition info\n", name); continue; } partition_node = dt_new_addr(partition_container_node, "partition", ffs_part_start); dt_add_property_strings(partition_node, "label", name); dt_add_property_cells(partition_node, "reg", ffs_part_start, ffs_part_size); if (part_name_map[i].id != RESOURCE_ID_KERNEL_FW) { /* Mark all partitions other than the full PNOR and the boot kernel * firmware as read only. These two partitions are the only partitions * that are properly erase block aligned at this time. */ dt_add_property(partition_node, "read-only", NULL, 0); } } partition_node = dt_new_addr(partition_container_node, "partition", 0); dt_add_property_strings(partition_node, "label", "PNOR"); dt_add_property_cells(partition_node, "reg", 0, flash->size); return flash_node; }
static void firenze_dt_fixup_i2cm(void) { struct dt_node *master, *bus, *dev; struct proc_chip *c; const uint32_t *p; char name[32]; uint64_t lx; if (dt_find_compatible_node(dt_root, NULL, "ibm,power8-i2cm")) return; p = dt_prop_get_def(dt_root, "ibm,vpd-lx-info", NULL); if (!p) return; lx = ((uint64_t)p[1] << 32) | p[2]; switch (lx) { case LX_VPD_2S4U_BACKPLANE: case LX_VPD_2S2U_BACKPLANE: case LX_VPD_SHARK_BACKPLANE: /* XXX confirm ? */ /* i2c nodes on chip 0x10 */ c = get_chip(0x10); if (c) { /* Engine 1 */ master = dt_create_i2c_master(c->devnode, 1); assert(master); snprintf(name, sizeof(name), "p8_%08x_e%dp%d", c->id, 1, 0); bus = dt_create_i2c_bus(master, name, 0); assert(bus); dev = dt_create_i2c_device(bus, 0x39, "power-control", "maxim,5961", "pcie-hotplug"); assert(dev); dt_add_property_strings(dev, "target-list", "slot-C4", "slot-C5"); dev = dt_create_i2c_device(bus, 0x3a, "power-control", "maxim,5961", "pcie-hotplug"); assert(dev); dt_add_property_strings(dev, "target-list", "slot-C2", "slot-C3"); } else { prlog(PR_INFO, "PLAT: Chip not found for the id 0x10\n"); } /* Fall through */ case LX_VPD_1S4U_BACKPLANE: case LX_VPD_1S2U_BACKPLANE: /* i2c nodes on chip 0 */ c = get_chip(0); if (!c) { prlog(PR_INFO, "PLAT: Chip not found for the id 0x0\n"); break; } /* Engine 1*/ master = dt_create_i2c_master(c->devnode, 1); assert(master); snprintf(name, sizeof(name), "p8_%08x_e%dp%d", c->id, 1, 0); bus = dt_create_i2c_bus(master, name, 0); assert(bus); dev = dt_create_i2c_device(bus, 0x32, "power-control", "maxim,5961", "pcie-hotplug"); assert(dev); dt_add_property_strings(dev, "target-list", "slot-C10", "slot-C11"); dev = dt_create_i2c_device(bus, 0x35, "power-control", "maxim,5961", "pcie-hotplug"); assert(dev); dt_add_property_strings(dev, "target-list", "slot-C6", "slot-C7"); dev = dt_create_i2c_device(bus, 0x36, "power-control", "maxim,5961", "pcie-hotplug"); assert(dev); dt_add_property_strings(dev, "target-list", "slot-C8", "slot-C9"); dev = dt_create_i2c_device(bus, 0x39, "power-control", "maxim,5961", "pcie-hotplug"); assert(dev); dt_add_property_strings(dev, "target-list", "slot-C12"); break; default: break; } }