ti/common: add support for extension_scan_board function

The BeagleBone platforms all use a common mechanism to discover and
identify extension boards (called "capes"): each extension board has an
I2C-connected EEPROM describing itself.

This patch implements a generic extension_scan_board() feature that can
be used by all BeagleBone platforms to read those I2C EEPROMs and fill
in the list of "extension" structures.

Following commits will enable this common logic on two BeagleBone
platforms.

Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
This commit is contained in:
Kory Maincent 2021-05-04 19:31:24 +02:00 committed by Tom Rini
parent 95300f203f
commit 8c1d443206
4 changed files with 131 additions and 0 deletions

View File

@ -16,6 +16,12 @@ config EEPROM_CHIP_ADDRESS
default 0x50
depends on TI_I2C_BOARD_DETECT
config CAPE_EEPROM_BUS_NUM
int "Cape EEPROM's I2C bus address"
range 0 8
default 2
depends on CMD_EXTENSION
config TI_COMMON_CMD_OPTIONS
bool "Enable cmd options on TI platforms"
imply CMD_ASKENV

View File

@ -2,3 +2,4 @@
# Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
obj-${CONFIG_TI_I2C_BOARD_DETECT} += board_detect.o
obj-${CONFIG_CMD_EXTENSION} += cape_detect.o

View File

@ -0,0 +1,96 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2021
* Köry Maincent, Bootlin, <kory.maincent@bootlin.com>
*/
#include <common.h>
#include <malloc.h>
#include <i2c.h>
#include <extension_board.h>
#include "cape_detect.h"
static void sanitize_field(char *text, size_t size)
{
char *c = NULL;
for (c = text; c < text + (int)size; c++) {
if (*c == 0xFF)
*c = 0;
}
}
int extension_board_scan(struct list_head *extension_list)
{
struct extension *cape;
struct am335x_cape_eeprom_id eeprom_header;
int num_capes = 0;
int ret, i;
struct udevice *dev;
unsigned char addr;
char process_cape_part_number[17] = {'0'};
char process_cape_version[5] = {'0'};
uint8_t cursor = 0;
for (addr = CAPE_EEPROM_FIRST_ADDR; addr <= CAPE_EEPROM_LAST_ADDR; addr++) {
ret = i2c_get_chip_for_busnum(CONFIG_CAPE_EEPROM_BUS_NUM, addr, 1, &dev);
if (ret)
continue;
/* Move the read cursor to the beginning of the EEPROM */
dm_i2c_write(dev, 0, &cursor, 1);
ret = dm_i2c_read(dev, 0, (uint8_t *)&eeprom_header,
sizeof(struct am335x_cape_eeprom_id));
if (ret) {
printf("Cannot read i2c EEPROM\n");
continue;
}
if (eeprom_header.header != CAPE_MAGIC)
continue;
sanitize_field(eeprom_header.board_name, sizeof(eeprom_header.board_name));
sanitize_field(eeprom_header.version, sizeof(eeprom_header.version));
sanitize_field(eeprom_header.manufacturer, sizeof(eeprom_header.manufacturer));
sanitize_field(eeprom_header.part_number, sizeof(eeprom_header.part_number));
/* Process cape part_number */
memset(process_cape_part_number, 0, sizeof(process_cape_part_number));
strncpy(process_cape_part_number, eeprom_header.part_number, 16);
/* Some capes end with '.' */
for (i = 15; i >= 0; i--) {
if (process_cape_part_number[i] == '.')
process_cape_part_number[i] = '\0';
else
break;
}
/* Process cape version */
memset(process_cape_version, 0, sizeof(process_cape_version));
strncpy(process_cape_version, eeprom_header.version, 4);
for (i = 0; i < 4; i++) {
if (process_cape_version[i] == 0)
process_cape_version[i] = '0';
}
printf("BeagleBone Cape: %s (0x%x)\n", eeprom_header.board_name, addr);
cape = calloc(1, sizeof(struct extension));
if (!cape) {
printf("Error in memory allocation\n");
return num_capes;
}
snprintf(cape->overlay, sizeof(cape->overlay), "%s-%s.dtbo",
process_cape_part_number, process_cape_version);
strncpy(cape->name, eeprom_header.board_name, 32);
strncpy(cape->version, process_cape_version, 4);
strncpy(cape->owner, eeprom_header.manufacturer, 16);
list_add_tail(&cape->list, extension_list);
num_capes++;
}
return num_capes;
}

View File

@ -0,0 +1,28 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2021
* Köry Maincent, Bootlin, <kory.maincent@bootlin.com>
*/
#ifndef __CAPE_DETECT_H
#define __CAPE_DETECT_H
struct am335x_cape_eeprom_id {
unsigned int header;
char eeprom_rev[2];
char board_name[32];
char version[4];
char manufacturer[16];
char part_number[16];
};
#define CAPE_EEPROM_FIRST_ADDR 0x54
#define CAPE_EEPROM_LAST_ADDR 0x57
#define CAPE_EEPROM_ADDR_LEN 0x10
#define CAPE_MAGIC 0xEE3355AA
int extension_board_scan(struct list_head *extension_list);
#endif /* __CAPE_DETECT_H */