1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2021
4 * K��ry Maincent, Bootlin, <kory.maincent@bootlin.com>
5 */
6
7#include <common.h>
8#include <malloc.h>
9#include <i2c.h>
10#include <extension_board.h>
11
12#include "cape_detect.h"
13
14static void sanitize_field(char *text, size_t size)
15{
16	char *c = NULL;
17
18	for (c = text; c < text + (int)size; c++) {
19		if (*c == 0xFF)
20			*c = 0;
21	}
22}
23
24int extension_board_scan(struct list_head *extension_list)
25{
26	struct extension *cape;
27	struct am335x_cape_eeprom_id eeprom_header;
28
29	int num_capes = 0;
30	int ret, i;
31	struct udevice *dev;
32	unsigned char addr;
33
34	char process_cape_part_number[17] = {'0'};
35	char process_cape_version[5] = {'0'};
36	uint8_t cursor = 0;
37
38	for (addr = CAPE_EEPROM_FIRST_ADDR; addr <= CAPE_EEPROM_LAST_ADDR; addr++) {
39		ret = i2c_get_chip_for_busnum(CONFIG_CAPE_EEPROM_BUS_NUM, addr, 1, &dev);
40		if (ret)
41			continue;
42
43		/* Move the read cursor to the beginning of the EEPROM */
44		dm_i2c_write(dev, 0, &cursor, 1);
45		ret = dm_i2c_read(dev, 0, (uint8_t *)&eeprom_header,
46				  sizeof(struct am335x_cape_eeprom_id));
47		if (ret) {
48			printf("Cannot read i2c EEPROM\n");
49			continue;
50		}
51
52		if (eeprom_header.header != CAPE_MAGIC)
53			continue;
54
55		sanitize_field(eeprom_header.board_name, sizeof(eeprom_header.board_name));
56		sanitize_field(eeprom_header.version, sizeof(eeprom_header.version));
57		sanitize_field(eeprom_header.manufacturer, sizeof(eeprom_header.manufacturer));
58		sanitize_field(eeprom_header.part_number, sizeof(eeprom_header.part_number));
59
60		/* Process cape part_number */
61		memset(process_cape_part_number, 0, sizeof(process_cape_part_number));
62		strncpy(process_cape_part_number, eeprom_header.part_number, 16);
63		/* Some capes end with '.' */
64		for (i = 15; i >= 0; i--) {
65			if (process_cape_part_number[i] == '.')
66				process_cape_part_number[i] = '\0';
67			else
68				break;
69		}
70
71		/* Process cape version */
72		memset(process_cape_version, 0, sizeof(process_cape_version));
73		strncpy(process_cape_version, eeprom_header.version, 4);
74		for (i = 0; i < 4; i++) {
75			if (process_cape_version[i] == 0)
76				process_cape_version[i] = '0';
77		}
78
79		printf("BeagleBone Cape: %s (0x%x)\n", eeprom_header.board_name, addr);
80
81		cape = calloc(1, sizeof(struct extension));
82		if (!cape) {
83			printf("Error in memory allocation\n");
84			return num_capes;
85		}
86
87		snprintf(cape->overlay, sizeof(cape->overlay), "%s-%s.dtbo",
88			 process_cape_part_number, process_cape_version);
89		strncpy(cape->name, eeprom_header.board_name, 32);
90		strncpy(cape->version, process_cape_version, 4);
91		strncpy(cape->owner, eeprom_header.manufacturer, 16);
92		list_add_tail(&cape->list, extension_list);
93		num_capes++;
94	}
95	return num_capes;
96}
97