1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2021
4  * Köry Maincent, Bootlin, <kory.maincent@bootlin.com>
5  * Based on initial code from Maxime Ripard
6  */
7 
8 #include <common.h>
9 #include <malloc.h>
10 #include <dm.h>
11 #include <w1.h>
12 #include <w1-eeprom.h>
13 #include <dm/device-internal.h>
14 
15 #include <asm/arch/gpio.h>
16 
17 #include <extension_board.h>
18 
19 #define for_each_w1_device(b, d) \
20 	for (device_find_first_child(b, d); *d; device_find_next_child(d))
21 
22 #define dip_convert(field)						\
23 	(								\
24 		(sizeof(field) == 1) ? field :				\
25 		(sizeof(field) == 2) ? be16_to_cpu(field) :		\
26 		(sizeof(field) == 4) ? be32_to_cpu(field) :		\
27 		-1							\
28 	)
29 
30 #define DIP_MAGIC	0x50494843	/* CHIP */
31 
32 struct dip_w1_header {
33 	u32     magic;                  /* CHIP */
34 	u8      version;                /* spec version */
35 	u32     vendor_id;
36 	u16     product_id;
37 	u8      product_version;
38 	char    vendor_name[32];
39 	char    product_name[32];
40 	u8      rsvd[36];               /* rsvd for future spec versions */
41 	u8      data[16];               /* user data, per-dip specific */
42 } __packed;
43 
extension_board_scan(struct list_head * extension_list)44 int extension_board_scan(struct list_head *extension_list)
45 {
46 	struct extension *dip;
47 	struct dip_w1_header w1_header;
48 	struct udevice *bus, *dev;
49 	u32 vid;
50 	u16 pid;
51 	int ret;
52 
53 	int num_dip = 0;
54 
55 	sunxi_gpio_set_pull(SUNXI_GPD(2), SUNXI_GPIO_PULL_UP);
56 
57 	ret = w1_get_bus(0, &bus);
58 	if (ret) {
59 		printf("one wire interface not found\n");
60 		return 0;
61 	}
62 
63 	for_each_w1_device(bus, &dev) {
64 		if (w1_get_device_family(dev) != W1_FAMILY_DS2431)
65 			continue;
66 
67 		ret = device_probe(dev);
68 		if (ret) {
69 			printf("Couldn't probe device %s: error %d",
70 			       dev->name, ret);
71 			continue;
72 		}
73 
74 		w1_eeprom_read_buf(dev, 0, (u8 *)&w1_header, sizeof(w1_header));
75 
76 		if (w1_header.magic != DIP_MAGIC)
77 			continue;
78 
79 		vid = dip_convert(w1_header.vendor_id);
80 		pid = dip_convert(w1_header.product_id);
81 
82 		printf("DIP: %s (0x%x) from %s (0x%x)\n",
83 		       w1_header.product_name, pid,
84 		       w1_header.vendor_name, vid);
85 
86 		dip = calloc(1, sizeof(struct extension));
87 		if (!dip) {
88 			printf("Error in memory allocation\n");
89 			return num_dip;
90 		}
91 
92 		snprintf(dip->overlay, sizeof(dip->overlay), "dip-%x-%x.dtbo",
93 			 vid, pid);
94 		strncpy(dip->name, w1_header.product_name, 32);
95 		strncpy(dip->owner, w1_header.vendor_name, 32);
96 		list_add_tail(&dip->list, extension_list);
97 		num_dip++;
98 	}
99 	return num_dip;
100 }
101