blob: cde04bebe96357f86ecdca35703d2a0c5691b357 [file] [log] [blame]
Kory Maincent6c2c7e92021-05-04 19:31:27 +02001// 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
32struct 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
44int 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}