aboutsummaryrefslogtreecommitdiff
path: root/platforms
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-11-07 16:19:05 +1100
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-11-07 16:19:05 +1100
commitfb20d3cd5129d5dc8964a1638e5150cc28c4b410 (patch)
tree940720cf3a822cbb39d695b3a9e4870ab9c1dfa2 /platforms
parent2b6b701f1dd15a4f0e39d51d048b90ea729ecc75 (diff)
downloadskiboot-fb20d3cd5129d5dc8964a1638e5150cc28c4b410.zip
skiboot-fb20d3cd5129d5dc8964a1638e5150cc28c4b410.tar.gz
skiboot-fb20d3cd5129d5dc8964a1638e5150cc28c4b410.tar.bz2
PLAT: Add i2c busses on palmetto/habanero
We add engine 1 only for now. Eventually, HostBoot will provide the device nodes and we'll filter what Linux can access. We expose the VPD eeprom so that the Linux AT24 driver can pick it up Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'platforms')
-rw-r--r--platforms/astbmc/common.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/platforms/astbmc/common.c b/platforms/astbmc/common.c
index 69fa8af..f79a5c5 100644
--- a/platforms/astbmc/common.c
+++ b/platforms/astbmc/common.c
@@ -149,6 +149,94 @@ static void astbmc_fixup_dt_uart(struct dt_node *lpc)
dt_add_property_cells(uart, "ibm,irq-chip-id", dt_get_chip_id(lpc));
}
+static struct dt_node *dt_create_i2c_master(struct dt_node *n, uint32_t eng_id)
+{
+ struct dt_node *i2cm;
+
+ /* 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, "bus-speed-khz", 400);
+ dt_add_property_cells(i2cm, "local-bus-freq-mhz", 50);
+ dt_add_property_cells(i2cm, "#address-cells", 1);
+ dt_add_property_cells(i2cm, "#size-cells", 0);
+
+ 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;
+ static uint32_t bus_id = 0;
+
+ port = dt_new_addr(i2cm, "i2c-bus", port_id);
+ if (!port)
+ return NULL;
+
+ dt_add_property_string(port, "compatible", "ibm,power8-i2c-port");
+ dt_add_property_string(port, "port-name", port_name);
+ dt_add_property_cells(port, "reg", port_id);
+ dt_add_property_cells(port, "ibm,opal-id", ++bus_id);
+ 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", "ok");
+
+ return dev;
+}
+
+static void astbmc_fixup_dt_i2cm(void)
+{
+ struct proc_chip *c;
+ struct dt_node *master, *bus;
+ char name[32];
+
+ /*
+ * Look if any i2c is in the device-tree, in which
+ * case we assume HB did the job
+ */
+ if (dt_find_compatible_node(dt_root, NULL, "ibm,power8-i2cm"))
+ return;
+
+ /* Create nodes for i2cm1 of chip 0 */
+ c = get_chip(0);
+ assert(c);
+
+ master = dt_create_i2c_master(c->devnode, 1);
+ assert(master);
+ sprintf(name,"p8_%08x_e%dp%d\n", c->id, 1, 0);
+ bus = dt_create_i2c_bus(master, name, 0);
+ assert(bus);
+ sprintf(name,"p8_%08x_e%dp%d\n", c->id, 1, 2);
+ bus = dt_create_i2c_bus(master, name, 2);
+ assert(bus);
+ dt_create_i2c_device(bus, 0x50, "eeprom", "atmel,24c64", "system-vpd");
+ assert(bus);
+}
+
static void astbmc_fixup_dt(void)
{
struct dt_node *n, *primary_lpc = NULL;
@@ -167,7 +255,11 @@ static void astbmc_fixup_dt(void)
/* Fixup the UART, that might be missing from HB */
astbmc_fixup_dt_uart(primary_lpc);
+ /* BT is not in HB either */
astbmc_fixup_dt_bt(primary_lpc);
+
+ /* Add i2c masters if needed */
+ astbmc_fixup_dt_i2cm();
}
static void astbmc_fixup_psi_bar(void)