Kory Maincent | 2655110 | 2021-05-04 19:31:24 +0200 | [diff] [blame] | 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 | |
| 14 | static 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 | |
| 24 | int 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 | } |