From: Marek Vasut Date: Sat, 3 Jul 2021 18:38:26 +0000 (+0200) Subject: sysinfo: rcar3: Add Renesas R-Car Gen3 sysinfo driver X-Git-Url: http://git.dujemihanovic.xyz/html/%7B%7B%20.Permalink%20%7D%7D?a=commitdiff_plain;h=85cd345dc8a979b7d67c69030e081711e68bb2be;p=u-boot.git sysinfo: rcar3: Add Renesas R-Car Gen3 sysinfo driver The Renesas R-Car Gen3 development kits contain board ID EEPROM. This driver parses out the board ID and revision out of that EEPROM and exports it e.g. for the board-info print on boot. Signed-off-by: Marek Vasut Cc: Sean Anderson Cc: Simon Glass --- diff --git a/drivers/sysinfo/Kconfig b/drivers/sysinfo/Kconfig index 381dcd8844..e35f7cb179 100644 --- a/drivers/sysinfo/Kconfig +++ b/drivers/sysinfo/Kconfig @@ -17,6 +17,13 @@ config SYSINFO_GAZERBEAM help Support querying device information for the gdsys Gazerbeam board. +config SYSINFO_RCAR3 + bool "Enable sysinfo driver for the Renesas R-Car Gen3" + depends on RCAR_GEN3 && I2C_EEPROM + default y if RCAR_GEN3 + help + Support querying SoC version information for Renesas R-Car Gen3. + config SYSINFO_SANDBOX bool "Enable sysinfo driver for the Sandbox board" help diff --git a/drivers/sysinfo/Makefile b/drivers/sysinfo/Makefile index d9f708b7ea..680dde77fe 100644 --- a/drivers/sysinfo/Makefile +++ b/drivers/sysinfo/Makefile @@ -5,5 +5,6 @@ obj-y += sysinfo-uclass.o obj-$(CONFIG_SYSINFO_GAZERBEAM) += gazerbeam.o obj-$(CONFIG_SYSINFO_GPIO) += gpio.o +obj-$(CONFIG_SYSINFO_RCAR3) += rcar3.o obj-$(CONFIG_SYSINFO_SANDBOX) += sandbox.o obj-$(CONFIG_SYSINFO_SMBIOS) += smbios.o diff --git a/drivers/sysinfo/rcar3.c b/drivers/sysinfo/rcar3.c new file mode 100644 index 0000000000..c2f4ddfbbe --- /dev/null +++ b/drivers/sysinfo/rcar3.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Marek Vasut + */ + +#include +#include +#include +#include +#include + +#define BOARD_CODE_MASK 0xF8 +#define BOARD_REV_MASK 0x07 +#define BOARD_CODE_SHIFT 0x03 + +#define BOARD_SALVATOR_X 0x0 +#define BOARD_KRIEK 0x1 +#define BOARD_STARTER_KIT 0x2 +#define BOARD_SALVATOR_XS 0x4 +#define BOARD_EBISU 0x8 +#define BOARD_STARTER_KIT_PRE 0xB +#define BOARD_EBISU_4D 0xD +#define BOARD_DRAAK 0xE +#define BOARD_EAGLE 0xF + +/** + * struct sysinfo_rcar_priv - sysinfo private data + * @boardname: board model and revision + * @val: board ID value from eeprom + */ +struct sysinfo_rcar_priv { + char boardmodel[64]; + u8 val; +}; + +static int sysinfo_rcar_detect(struct udevice *dev) +{ + struct sysinfo_rcar_priv *priv = dev_get_priv(dev); + + return priv->val == 0xff; +} + +static int sysinfo_rcar_get_str(struct udevice *dev, int id, size_t size, char *val) +{ + struct sysinfo_rcar_priv *priv = dev_get_priv(dev); + + switch (id) { + case SYSINFO_ID_BOARD_MODEL: + strncpy(val, priv->boardmodel, size); + val[size - 1] = '\0'; + return 0; + default: + return -EINVAL; + }; +} + +static const struct sysinfo_ops sysinfo_rcar_ops = { + .detect = sysinfo_rcar_detect, + .get_str = sysinfo_rcar_get_str, +}; + +static void sysinfo_rcar_parse(struct sysinfo_rcar_priv *priv) +{ + const u8 board_id = (priv->val & BOARD_CODE_MASK) >> BOARD_CODE_SHIFT; + const u8 board_rev = priv->val & BOARD_REV_MASK; + bool salvator_xs = false; + bool ebisu_4d = false; + char rev_major = '?'; + char rev_minor = '?'; + + switch (board_id) { + case BOARD_SALVATOR_XS: + salvator_xs = true; + fallthrough; + case BOARD_SALVATOR_X: + if (!(board_rev & ~1)) { /* Only rev 0 and 1 is valid */ + rev_major = '1'; + rev_minor = '0' + (board_rev & BIT(0)); + } + snprintf(priv->boardmodel, sizeof(priv->boardmodel), + "Renesas Salvator-X%s board rev %c.%c", + salvator_xs ? "S" : "", rev_major, rev_minor); + return; + case BOARD_STARTER_KIT: + if (!(board_rev & ~1)) { /* Only rev 0 and 1 is valid */ + rev_major = (board_rev & BIT(0)) ? '3' : '1'; + rev_minor = '0'; + } + snprintf(priv->boardmodel, sizeof(priv->boardmodel), + "Renesas Starter Kit board rev %c.%c", + rev_major, rev_minor); + return; + case BOARD_STARTER_KIT_PRE: + if (!(board_rev & ~3)) { /* Only rev 0..3 is valid */ + rev_major = (board_rev & BIT(1)) ? '2' : '1'; + rev_minor = (board_rev == 3) ? '1' : '0'; + } + snprintf(priv->boardmodel, sizeof(priv->boardmodel), + "Renesas Starter Kit Premier board rev %c.%c", + rev_major, rev_minor); + return; + case BOARD_EAGLE: + if (!board_rev) { /* Only rev 0 is valid */ + rev_major = '1'; + rev_minor = '0'; + } + snprintf(priv->boardmodel, sizeof(priv->boardmodel), + "Renesas Eagle board rev %c.%c", + rev_major, rev_minor); + return; + case BOARD_EBISU_4D: + ebisu_4d = true; + fallthrough; + case BOARD_EBISU: + if (!board_rev) { /* Only rev 0 is valid */ + rev_major = '1'; + rev_minor = '0'; + } + snprintf(priv->boardmodel, sizeof(priv->boardmodel), + "Renesas Ebisu%s board rev %c.%c", + ebisu_4d ? "-4D" : "", rev_major, rev_minor); + return; + case BOARD_DRAAK: + if (!board_rev) { /* Only rev 0 is valid */ + rev_major = '1'; + rev_minor = '0'; + } + snprintf(priv->boardmodel, sizeof(priv->boardmodel), + "Renesas Draak board rev %c.%c", + rev_major, rev_minor); + return; + case BOARD_KRIEK: + if (!board_rev) { /* Only rev 0 is valid */ + rev_major = '1'; + rev_minor = '0'; + } + snprintf(priv->boardmodel, sizeof(priv->boardmodel), + "Renesas Kriek board rev %c.%c", + rev_major, rev_minor); + return; + default: + snprintf(priv->boardmodel, sizeof(priv->boardmodel), + "Renesas -Unknown- board rev ?.?"); + priv->val = 0xff; + return; + } +} + +static int sysinfo_rcar_probe(struct udevice *dev) +{ + struct sysinfo_rcar_priv *priv = dev_get_priv(dev); + struct ofnode_phandle_args phandle_args; + struct udevice *i2c_eeprom; + u32 offset; + int ret; + + offset = dev_read_u32_default(dev, "offset", 0x70); + + ret = dev_read_phandle_with_args(dev, "i2c-eeprom", NULL, + 0, 0, &phandle_args); + if (ret) { + debug("%s: i2c-eeprom backing device not specified\n", + dev->name); + return ret; + } + + ret = uclass_get_device_by_ofnode(UCLASS_I2C_EEPROM, phandle_args.node, + &i2c_eeprom); + if (ret) { + debug("%s: could not get backing device\n", dev->name); + return ret; + } + + ret = i2c_eeprom_read(i2c_eeprom, offset, &priv->val, 1); + if (ret < 0) { + debug("%s: read failed\n", __func__); + return -EIO; + } + + sysinfo_rcar_parse(priv); + + return 0; +} + +static const struct udevice_id sysinfo_rcar_ids[] = { + { .compatible = "renesas,rcar-sysinfo" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(sysinfo_rcar) = { + .name = "sysinfo_rcar", + .id = UCLASS_SYSINFO, + .of_match = sysinfo_rcar_ids, + .ops = &sysinfo_rcar_ops, + .priv_auto = sizeof(struct sysinfo_rcar_priv), + .probe = sysinfo_rcar_probe, +};