diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/skiboot/platforms/ibm-fsp/firenze.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/skiboot/platforms/ibm-fsp/firenze.c')
-rw-r--r-- | roms/skiboot/platforms/ibm-fsp/firenze.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/roms/skiboot/platforms/ibm-fsp/firenze.c b/roms/skiboot/platforms/ibm-fsp/firenze.c new file mode 100644 index 000000000..887a9c0ac --- /dev/null +++ b/roms/skiboot/platforms/ibm-fsp/firenze.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* Copyright 2013-2019 IBM Corp. */ + +#include <skiboot.h> +#include <device.h> +#include <fsp.h> +#include <pci.h> +#include <pci-cfg.h> +#include <chip.h> +#include <i2c.h> +#include <timebase.h> +#include <hostservices.h> + +#include "ibm-fsp.h" +#include "lxvpd.h" + +static struct dt_node *dt_create_i2c_master(struct dt_node *n, uint32_t eng_id) +{ + struct dt_node *i2cm; + uint64_t freq; + uint32_t clock; + + /* Each master registers set is of length 0x20 */ + i2cm = dt_new_addr(n, "i2cm", 0xa0000 + eng_id * 0x20); + if (!i2cm) + return NULL; + + dt_add_property_string(i2cm, "compatible", + "ibm,power8-i2cm"); + dt_add_property_cells(i2cm, "reg", 0xa0000 + eng_id * 0x20, + 0x20); + dt_add_property_cells(i2cm, "chip-engine#", eng_id); + dt_add_property_cells(i2cm, "#address-cells", 1); + dt_add_property_cells(i2cm, "#size-cells", 0); + + /* Derive the clock source frequency */ + freq = dt_prop_get_u64_def(n, "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", 125000000); + return i2cm; +} + +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 *dt_create_i2c_device(struct dt_node *bus, uint8_t addr, + const char *name, const char *compat, + const char *label) +{ + struct dt_node *dev; + + dev = dt_new_addr(bus, name, addr); + if (!dev) + return NULL; + + dt_add_property_string(dev, "compatible", compat); + dt_add_property_string(dev, "label", label); + dt_add_property_cells(dev, "reg", addr); + dt_add_property_string(dev, "status", "reserved"); + + return dev; +} + +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; + } +} + +static bool firenze_probe(void) +{ + if (!dt_node_is_compatible(dt_root, "ibm,firenze")) + return false; + + firenze_dt_fixup_i2cm(); + + return true; +} + +static uint32_t ibm_fsp_occ_timeout(void) +{ + /* Use a fixed 60s value for now */ + return 60; +} + +static void firenze_init(void) +{ + /* We call hservices_init to relocate the hbrt image now, as the FSP + * may request an OCC load any time after ibm_fsp_init. + */ + hservices_init(); + + ibm_fsp_init(); +} + +DECLARE_PLATFORM(firenze) = { + .name = "Firenze", + .psi = &fsp_platform_psi, + .prd = &fsp_platform_prd, + .probe = firenze_probe, + .init = firenze_init, + .fast_reboot_init = fsp_console_reset, + .finalise_dt = ibm_fsp_finalise_dt, + .exit = ibm_fsp_exit, + .cec_power_down = ibm_fsp_cec_power_down, + .cec_reboot = ibm_fsp_cec_reboot, + .pci_setup_phb = firenze_pci_setup_phb, + .pci_get_slot_info = firenze_pci_get_slot_info, + .pci_add_loc_code = firenze_pci_add_loc_code, + .pci_probe_complete = firenze_pci_send_inventory, + .nvram_info = fsp_nvram_info, + .nvram_start_read = fsp_nvram_start_read, + .nvram_write = fsp_nvram_write, + .occ_timeout = ibm_fsp_occ_timeout, + .elog_commit = elog_fsp_commit, + .start_preload_resource = fsp_start_preload_resource, + .resource_loaded = fsp_resource_loaded, + .sensor_read = ibm_fsp_sensor_read, + .terminate = ibm_fsp_terminate, + .op_display = fsp_op_display, + .vpd_iohub_load = vpd_iohub_load, + .heartbeat_time = fsp_heartbeat_time, +}; |