diff options
author | Kory Maincent | 2021-05-04 19:31:27 +0200 |
---|---|---|
committer | Tom Rini | 2021-05-13 13:09:09 -0400 |
commit | 6c2c7e9cb95e92cc792ade46a44fc3801dab2de5 (patch) | |
tree | b904a66eab924e0adacedef241e0155eab08bdc4 /board | |
parent | c9dffc971957e5fd18d64aa17a95e8d82a59d273 (diff) |
arm: sunxi: add support for DIP detection to CHIP board
Add the extension_board_scan specific function to scan the information
of the EEPROM on one-wire and fill the extension struct.
Add the Kconfig symbol to enable the needs to detect DIPs.
Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
Reviewed-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Andre Przywara <andre.przywara@arm.com>
Diffstat (limited to 'board')
-rw-r--r-- | board/sunxi/Makefile | 1 | ||||
-rw-r--r-- | board/sunxi/chip.c | 100 |
2 files changed, 101 insertions, 0 deletions
diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile index c4e13f8c38d..d96b7897b6c 100644 --- a/board/sunxi/Makefile +++ b/board/sunxi/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_SUN7I_GMAC) += gmac.o obj-$(CONFIG_MACH_SUN4I) += dram_sun4i_auto.o obj-$(CONFIG_MACH_SUN5I) += dram_sun5i_auto.o obj-$(CONFIG_MACH_SUN7I) += dram_sun5i_auto.o +obj-$(CONFIG_CHIP_DIP_SCAN) += chip.o diff --git a/board/sunxi/chip.c b/board/sunxi/chip.c new file mode 100644 index 00000000000..cde04bebe96 --- /dev/null +++ b/board/sunxi/chip.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2021 + * Köry Maincent, Bootlin, <kory.maincent@bootlin.com> + * Based on initial code from Maxime Ripard + */ + +#include <common.h> +#include <malloc.h> +#include <dm.h> +#include <w1.h> +#include <w1-eeprom.h> +#include <dm/device-internal.h> + +#include <asm/arch/gpio.h> + +#include <extension_board.h> + +#define for_each_w1_device(b, d) \ + for (device_find_first_child(b, d); *d; device_find_next_child(d)) + +#define dip_convert(field) \ + ( \ + (sizeof(field) == 1) ? field : \ + (sizeof(field) == 2) ? be16_to_cpu(field) : \ + (sizeof(field) == 4) ? be32_to_cpu(field) : \ + -1 \ + ) + +#define DIP_MAGIC 0x50494843 /* CHIP */ + +struct dip_w1_header { + u32 magic; /* CHIP */ + u8 version; /* spec version */ + u32 vendor_id; + u16 product_id; + u8 product_version; + char vendor_name[32]; + char product_name[32]; + u8 rsvd[36]; /* rsvd for future spec versions */ + u8 data[16]; /* user data, per-dip specific */ +} __packed; + +int extension_board_scan(struct list_head *extension_list) +{ + struct extension *dip; + struct dip_w1_header w1_header; + struct udevice *bus, *dev; + u32 vid; + u16 pid; + int ret; + + int num_dip = 0; + + sunxi_gpio_set_pull(SUNXI_GPD(2), SUNXI_GPIO_PULL_UP); + + ret = w1_get_bus(0, &bus); + if (ret) { + printf("one wire interface not found\n"); + return 0; + } + + for_each_w1_device(bus, &dev) { + if (w1_get_device_family(dev) != W1_FAMILY_DS2431) + continue; + + ret = device_probe(dev); + if (ret) { + printf("Couldn't probe device %s: error %d", + dev->name, ret); + continue; + } + + w1_eeprom_read_buf(dev, 0, (u8 *)&w1_header, sizeof(w1_header)); + + if (w1_header.magic != DIP_MAGIC) + continue; + + vid = dip_convert(w1_header.vendor_id); + pid = dip_convert(w1_header.product_id); + + printf("DIP: %s (0x%x) from %s (0x%x)\n", + w1_header.product_name, pid, + w1_header.vendor_name, vid); + + dip = calloc(1, sizeof(struct extension)); + if (!dip) { + printf("Error in memory allocation\n"); + return num_dip; + } + + snprintf(dip->overlay, sizeof(dip->overlay), "dip-%x-%x.dtbo", + vid, pid); + strncpy(dip->name, w1_header.product_name, 32); + strncpy(dip->owner, w1_header.vendor_name, 32); + list_add_tail(&dip->list, extension_list); + num_dip++; + } + return num_dip; +} |