From: Clement Leger <clement.leger@xxxxxxxxxxx> This driver uses various source (sfr, nvmem) to determine the mppa_id and the architecture revision. These are then exported using global variables which are: - global.kvx.arch_rev: Architecture revision (kv3-1 for instance) - global.kvx.mppa_id: Unique chip id, composed of lot and wafer id Signed-off-by: Clement Leger <clement.leger@xxxxxxxxxxx> Co-developed-by: Jules Maselbas <jmaselbas@xxxxxxxxx> Signed-off-by: Jules Maselbas <jmaselbas@xxxxxxxxx> --- drivers/soc/Kconfig | 1 + drivers/soc/Makefile | 1 + drivers/soc/kvx/Kconfig | 10 +++ drivers/soc/kvx/Makefile | 1 + drivers/soc/kvx/kvx_socinfo.c | 141 ++++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 drivers/soc/kvx/Kconfig create mode 100644 drivers/soc/kvx/Makefile create mode 100644 drivers/soc/kvx/kvx_socinfo.c diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index d78f13f3f8..54b69cc42e 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig @@ -1,5 +1,6 @@ menu "SoC drivers" source "drivers/soc/imx/Kconfig" +source "drivers/soc/kvx/Kconfig" endmenu diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index c4efb8f02f..e5b319e6da 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -3,3 +3,4 @@ obj-y += imx/ obj-$(CONFIG_CPU_SIFIVE) += sifive/ obj-$(CONFIG_SOC_STARFIVE) += starfive/ +obj-$(CONFIG_KVX) += kvx/ diff --git a/drivers/soc/kvx/Kconfig b/drivers/soc/kvx/Kconfig new file mode 100644 index 0000000000..18dcb8ba14 --- /dev/null +++ b/drivers/soc/kvx/Kconfig @@ -0,0 +1,10 @@ +menu "KVX SoC drivers" + +config KVX_SOCINFO + bool "KVX SoC Info driver" + depends on KVX + select NVMEM + select KVX_OTP_NV + default y + +endmenu diff --git a/drivers/soc/kvx/Makefile b/drivers/soc/kvx/Makefile new file mode 100644 index 0000000000..cacfef21a1 --- /dev/null +++ b/drivers/soc/kvx/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_KVX_SOCINFO) += kvx_socinfo.o diff --git a/drivers/soc/kvx/kvx_socinfo.c b/drivers/soc/kvx/kvx_socinfo.c new file mode 100644 index 0000000000..100faae766 --- /dev/null +++ b/drivers/soc/kvx/kvx_socinfo.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Kalray Inc., Clément Léger + */ + +#define pr_fmt(fmt) "kvx_socinfo: " fmt + +#include <init.h> +#include <driver.h> +#include <globalvar.h> +#include <magicvar.h> +#include <command.h> +#include <libfile.h> +#include <getopt.h> +#include <common.h> +#include <fs.h> + +#include <asm/sfr.h> + +#include <linux/kernel.h> +#include <linux/nvmem-consumer.h> + +#define LOT_ID_STR_LEN 8 + +#define EWS_LOT_ID_MASK 0x1ffffffffffULL +#define EWS_WAFER_ID_SHIFT 42 +#define EWS_WAFER_ID_MASK 0x1fULL + +#define FT_COM_AP_SHIFT 16 +#define FT_COM_AP_MASK 0x3f +#define FT_DEVICE_ID_SHIFT 22 +#define FT_DEVICE_ID_MASK 0x1ff + +static char *kvx_mppa_id; +static char *kvx_arch_rev; + +BAREBOX_MAGICVAR(kvx.arch_rev, "KVX architecture revision"); +BAREBOX_MAGICVAR(kvx.mppa_id, "KVX MPPA chip id"); + +static void kvx_soc_info_read_revision(void) +{ + u64 pcr = kvx_sfr_get(PCR); + u8 sv = kvx_sfr_field_val(pcr, PCR, SV); + u8 car = kvx_sfr_field_val(pcr, PCR, CAR); + const char *car_str = "", *ver_str = ""; + + switch (car) { + case 0: + car_str = "kv3"; + break; + } + + switch (sv) { + case 0: + ver_str = "1"; + break; + case 1: + ver_str = "2"; + break; + } + + kvx_arch_rev = basprintf("%s-%s", car_str, ver_str); + + globalvar_add_simple_string("kvx.arch_rev", &kvx_arch_rev); +} + +static int base38_decode(char *s, u64 val, int nb_char) +{ + int i; + const char *alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_?"; + const int base = strlen(alphabet); + + if (s == NULL) + return -1; + + for (i = 0; i < nb_char; i++) { + s[i] = alphabet[val % base]; + val /= base; + } + + return 0; +} + +static int kvx_read_serial(struct device_node *socinfo) +{ + char lot_id[LOT_ID_STR_LEN + 1] = ""; + char com_ap; + u64 *cell_val64; + u64 ews_val; + u32 *cell_val32; + u32 ft_val; + u8 wafer_id; + u16 device_id; + + cell_val64 = (u64 *) nvmem_cell_get_and_read(socinfo, "ews_fuse", 8); + if (IS_ERR(cell_val64)) { + pr_debug("Fail to read ews_fuse\n"); + return PTR_ERR(cell_val64); + } + + ews_val = *cell_val64; + ews_val = (ews_val >> 32) | (ews_val << 32); + wafer_id = (ews_val >> EWS_WAFER_ID_SHIFT) & EWS_WAFER_ID_MASK; + base38_decode(lot_id, ews_val & EWS_LOT_ID_MASK, LOT_ID_STR_LEN); + + cell_val32 = (u32 *) nvmem_cell_get_and_read(socinfo, "ft_fuse", 4); + if (IS_ERR(cell_val32)) { + pr_debug("Fail to read ft_fuse\n"); + return PTR_ERR(cell_val32); + } + + ft_val = *cell_val32; + device_id = (ft_val >> FT_DEVICE_ID_SHIFT) & FT_DEVICE_ID_MASK; + base38_decode(&com_ap, (ft_val >> FT_COM_AP_SHIFT) & FT_COM_AP_MASK, 1); + + kvx_mppa_id = basprintf("%sA-%d%c-%03d", lot_id, wafer_id, com_ap, + device_id); + + globalvar_add_simple_string("kvx.mppa_id", &kvx_mppa_id); + + return 0; +} + +static int kvx_socinfo_probe(struct device_d *dev) +{ + kvx_soc_info_read_revision(); + + return kvx_read_serial(dev->device_node); +} + +static const struct of_device_id kvx_socinfo_dt_ids[] = { + { .compatible = "kalray,kvx-socinfo" }, + { } +}; + +static struct driver_d kvx_socinfo_driver = { + .name = "kvx-socinfo", + .probe = kvx_socinfo_probe, + .of_compatible = DRV_OF_COMPAT(kvx_socinfo_dt_ids), +}; +coredevice_platform_driver(kvx_socinfo_driver); -- 2.17.1 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox