From: Roger Quadros <rogerq@kernel.org>
To: nm@ti.com, vigneshr@ti.com, trini@konsulko.com
Cc: srk@ti.com, robertcnelson@gmail.com, u-boot@lists.denx.de,
Roger Quadros <rogerq@kernel.org>
Subject: [RFC PATCH 2/2] board: ti: am65x: Move to using Extension framework
Date: Mon, 10 Jul 2023 17:50:26 +0300 [thread overview]
Message-ID: <20230710145026.128481-3-rogerq@kernel.org> (raw)
In-Reply-To: <20230710145026.128481-1-rogerq@kernel.org>
Support the Expansion cards via Extension framework.
This should make 'expansion' command work to scan
for expansion cards and apply DT overlays.
Card detection code is moved to a library so
other boards can benefit from it.
Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
board/ti/am65x/evm.c | 264 ++++++++---------------------
board/ti/common/Kconfig | 8 +
board/ti/common/Makefile | 1 +
board/ti/common/ti_card_detect.c | 155 +++++++++++++++++
board/ti/common/ti_card_detect.h | 43 +++++
configs/am65x_evm_a53_defconfig | 2 +
configs/am65x_hs_evm_a53_defconfig | 2 +
7 files changed, 280 insertions(+), 195 deletions(-)
create mode 100644 board/ti/common/ti_card_detect.c
create mode 100644 board/ti/common/ti_card_detect.h
diff --git a/board/ti/am65x/evm.c b/board/ti/am65x/evm.c
index 706b219818..5bb187a062 100644
--- a/board/ti/am65x/evm.c
+++ b/board/ti/am65x/evm.c
@@ -22,21 +22,10 @@
#include <spl.h>
#include "../common/board_detect.h"
+#include "../common/ti_card_detect.h"
#define board_is_am65x_base_board() board_ti_is("AM6-COMPROCEVM")
-/* Daughter card presence detection signals */
-enum {
- AM65X_EVM_APP_BRD_DET,
- AM65X_EVM_LCD_BRD_DET,
- AM65X_EVM_SERDES_BRD_DET,
- AM65X_EVM_HDMI_GPMC_BRD_DET,
- AM65X_EVM_BRD_DET_COUNT,
-};
-
-/* Max number of MAC addresses that are parsed/processed per daughter card */
-#define DAUGHTER_CARD_NO_OF_MAC_ADDR 8
-
/* Regiter that controls the SERDES0 lane and clock assignment */
#define CTRLMMR_SERDES0_CTRL 0x00104080
#define PCIE_LANE0 0x1
@@ -99,6 +88,74 @@ int board_fit_config_name_match(const char *name)
}
#endif
+/* Expansion card Slot IDs */
+enum {
+ AM65X_EVM_APP_BRD_DET,
+ AM65X_EVM_LCD_BRD_DET,
+ AM65X_EVM_SERDES_BRD_DET,
+ AM65X_EVM_HDMI_GPMC_BRD_DET,
+ AM65X_EVM_BRD_DET_COUNT,
+};
+
+/* Expansion card slots */
+static const struct ti_card_slot_map am65x_slot_map[] = {
+ { "gpio@38_0", 0x52, }, /* AM65X_EVM_APP_BRD_DET */
+ { "gpio@38_1", 0x55, }, /* AM65X_EVM_LCD_BRD_DET */
+ { "gpio@38_2", 0x54, }, /* AM65X_EVM_SERDES_BRD_DET */
+ { "gpio@38_3", 0x53, }, /* AM65X_EVM_HDMI_GPMC_BRD_DET */
+};
+
+/* Supported Expansion cards */
+static const struct ti_card_info am65x_card_info[] = {
+ {
+ AM65X_EVM_APP_BRD_DET,
+ "AM6-GPAPPEVM",
+ "k3-am654-gp.dtbo",
+ 0,
+ TI_CARD_OWNER,
+ TI_CARD_VERSION_1,
+ },
+ {
+ AM65X_EVM_APP_BRD_DET,
+ "AM6-IDKAPPEVM",
+ "k3-am654-idk.dtbo",
+ 3,
+ TI_CARD_OWNER,
+ TI_CARD_VERSION_1,
+ },
+ {
+ AM65X_EVM_SERDES_BRD_DET,
+ "SER-PCIE2LEVM",
+ "k3-am654-pcie-usb2.dtbo",
+ 0,
+ TI_CARD_OWNER,
+ TI_CARD_VERSION_1,
+ },
+ {
+ AM65X_EVM_SERDES_BRD_DET,
+ "SER-PCIEUSBEVM",
+ "k3-am654-pcie-usb3.dtbo",
+ 0,
+ TI_CARD_OWNER,
+ TI_CARD_VERSION_1,
+ },
+ {
+ AM65X_EVM_LCD_BRD_DET,
+ "OLDI-LCD1EVM",
+ "k3-am654-evm-oldi-lcd1evm.dtbo",
+ 0,
+ TI_CARD_OWNER,
+ TI_CARD_VERSION_1,
+ },
+};
+
+int extension_board_scan(struct list_head *extension_list)
+{
+ return ti_card_detect(am65x_slot_map, ARRAY_SIZE(am65x_slot_map),
+ am65x_card_info, ARRAY_SIZE(am65x_card_info),
+ extension_list);
+}
+
#ifdef CONFIG_TI_I2C_BOARD_DETECT
int do_board_detect(void)
{
@@ -143,187 +200,7 @@ invalid_eeprom:
set_board_info_env_am6(name);
}
-static int init_daughtercard_det_gpio(char *gpio_name, struct gpio_desc *desc)
-{
- int ret;
-
- memset(desc, 0, sizeof(*desc));
-
- ret = dm_gpio_lookup_name(gpio_name, desc);
- if (ret < 0)
- return ret;
-
- /* Request GPIO, simply re-using the name as label */
- ret = dm_gpio_request(desc, gpio_name);
- if (ret < 0)
- return ret;
- return dm_gpio_set_dir_flags(desc, GPIOD_IS_IN);
-}
-
-static int probe_daughtercards(void)
-{
- struct ti_am6_eeprom ep;
- struct gpio_desc board_det_gpios[AM65X_EVM_BRD_DET_COUNT];
- char mac_addr[DAUGHTER_CARD_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN];
- u8 mac_addr_cnt;
- char name_overlays[1024] = { 0 };
- int i, j;
- int ret;
-
- /*
- * Daughter card presence detection signal name to GPIO (via I2C I/O
- * expander @ address 0x38) name and EEPROM I2C address mapping.
- */
- const struct {
- char *gpio_name;
- u8 i2c_addr;
- } slot_map[AM65X_EVM_BRD_DET_COUNT] = {
- { "gpio@38_0", 0x52, }, /* AM65X_EVM_APP_BRD_DET */
- { "gpio@38_1", 0x55, }, /* AM65X_EVM_LCD_BRD_DET */
- { "gpio@38_2", 0x54, }, /* AM65X_EVM_SERDES_BRD_DET */
- { "gpio@38_3", 0x53, }, /* AM65X_EVM_HDMI_GPMC_BRD_DET */
- };
-
- /* Declaration of daughtercards to probe */
- const struct {
- u8 slot_index; /* Slot the card is installed */
- char *card_name; /* EEPROM-programmed card name */
- char *dtbo_name; /* Device tree overlay to apply */
- u8 eth_offset; /* ethXaddr MAC address index offset */
- } cards[] = {
- {
- AM65X_EVM_APP_BRD_DET,
- "AM6-GPAPPEVM",
- "k3-am654-gp.dtbo",
- 0,
- },
- {
- AM65X_EVM_APP_BRD_DET,
- "AM6-IDKAPPEVM",
- "k3-am654-idk.dtbo",
- 3,
- },
- {
- AM65X_EVM_SERDES_BRD_DET,
- "SER-PCIE2LEVM",
- "k3-am654-pcie-usb2.dtbo",
- 0,
- },
- {
- AM65X_EVM_SERDES_BRD_DET,
- "SER-PCIEUSBEVM",
- "k3-am654-pcie-usb3.dtbo",
- 0,
- },
- {
- AM65X_EVM_LCD_BRD_DET,
- "OLDI-LCD1EVM",
- "k3-am654-evm-oldi-lcd1evm.dtbo",
- 0,
- },
- };
-
- /*
- * Initialize GPIO used for daughtercard slot presence detection and
- * keep the resulting handles in local array for easier access.
- */
- for (i = 0; i < AM65X_EVM_BRD_DET_COUNT; i++) {
- ret = init_daughtercard_det_gpio(slot_map[i].gpio_name,
- &board_det_gpios[i]);
- if (ret < 0)
- return ret;
- }
-
- for (i = 0; i < ARRAY_SIZE(cards); i++) {
- /* Obtain card-specific slot index and associated I2C address */
- u8 slot_index = cards[i].slot_index;
- u8 i2c_addr = slot_map[slot_index].i2c_addr;
-
- /*
- * The presence detection signal is active-low, hence skip
- * over this card slot if anything other than 0 is returned.
- */
- ret = dm_gpio_get_value(&board_det_gpios[slot_index]);
- if (ret < 0)
- return ret;
- else if (ret)
- continue;
-
- /* Get and parse the daughter card EEPROM record */
- ret = ti_i2c_eeprom_am6_get(CONFIG_EEPROM_BUS_ADDRESS, i2c_addr,
- &ep,
- (char **)mac_addr,
- DAUGHTER_CARD_NO_OF_MAC_ADDR,
- &mac_addr_cnt);
- if (ret) {
- pr_err("Reading daughtercard EEPROM at 0x%02x failed %d\n",
- i2c_addr, ret);
- /*
- * Even this is pretty serious let's just skip over
- * this particular daughtercard, rather than ending
- * the probing process altogether.
- */
- continue;
- }
-
- /* Only process the parsed data if we found a match */
- if (strncmp(ep.name, cards[i].card_name, sizeof(ep.name)))
- continue;
-
- printf("Detected: %s rev %s\n", ep.name, ep.version);
-
- /*
- * Populate any MAC addresses from daughtercard into the U-Boot
- * environment, starting with a card-specific offset so we can
- * have multiple cards contribute to the MAC pool in a well-
- * defined manner.
- */
- for (j = 0; j < mac_addr_cnt; j++) {
- if (!is_valid_ethaddr((u8 *)mac_addr[j]))
- continue;
-
- eth_env_set_enetaddr_by_index("eth",
- cards[i].eth_offset + j,
- (uchar *)mac_addr[j]);
- }
-
- /*
- * It has been observed that setting SERDES0 lane mux to USB prevents USB
- * 2.0 operation on USB0. Setting SERDES0 lane mux to non-USB when USB0 is
- * used in USB 2.0 only mode solves this issue. For USB3.0+2.0 operation
- * this issue is not present.
- *
- * Implement this workaround by writing 1 to LANE_FUNC_SEL field in
- * CTRLMMR_SERDES0_CTRL register.
- */
- if (!strncmp(ep.name, "SER-PCIE2LEVM", sizeof(ep.name)))
- writel(PCIE_LANE0, CTRLMMR_SERDES0_CTRL);
-
- /* Skip if no overlays are to be added */
- if (!strlen(cards[i].dtbo_name))
- continue;
-
- /*
- * Make sure we are not running out of buffer space by checking
- * if we can fit the new overlay, a trailing space to be used
- * as a separator, plus the terminating zero.
- */
- if (strlen(name_overlays) + strlen(cards[i].dtbo_name) + 2 >
- sizeof(name_overlays))
- return -ENOMEM;
-
- /* Append to our list of overlays */
- strcat(name_overlays, cards[i].dtbo_name);
- strcat(name_overlays, " ");
- }
-
- /* Apply device tree overlay(s) to the U-Boot environment, if any */
- if (strlen(name_overlays))
- return env_set("name_overlays", name_overlays);
-
- return 0;
-}
#endif
int board_late_init(void)
@@ -340,9 +217,6 @@ int board_late_init(void)
* an index of 1.
*/
board_ti_am6_set_ethaddr(1, ep->mac_addr_cnt);
-
- /* Check for and probe any plugged-in daughtercards */
- probe_daughtercards();
}
return 0;
diff --git a/board/ti/common/Kconfig b/board/ti/common/Kconfig
index 72ee2d6d0e..039a2722f3 100644
--- a/board/ti/common/Kconfig
+++ b/board/ti/common/Kconfig
@@ -12,6 +12,14 @@ config TI_CAPE_DETECT
Support Beagle Bone Cape detection for TI platforms
e.g. AM335x BeagleBone.
+config TI_CARD_DETECT
+ bool "Support Expansion Card detection for TI platforms"
+ default y if TARGET_AM654_A53_EVM
+ depends on SUPPORT_EXTENSION_SCAN
+ help
+ Support Expansion Card detection for TI platforms
+ e.g. AM654-EVM
+
config EEPROM_BUS_ADDRESS
int "Board EEPROM's I2C bus address"
range 0 8
diff --git a/board/ti/common/Makefile b/board/ti/common/Makefile
index 5db433f77f..f3922f231b 100644
--- a/board/ti/common/Makefile
+++ b/board/ti/common/Makefile
@@ -3,3 +3,4 @@
obj-${CONFIG_TI_I2C_BOARD_DETECT} += board_detect.o
obj-${CONFIG_TI_CAPE_DETECT} += cape_detect.o
+obj-${CONFIG_TI_CARD_DETECT} += ti_card_detect.o
diff --git a/board/ti/common/ti_card_detect.c b/board/ti/common/ti_card_detect.c
new file mode 100644
index 0000000000..7efb42cbbe
--- /dev/null
+++ b/board/ti/common/ti_card_detect.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * TI EVM Extension card handling
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <extension_board.h>
+#include "board_detect.h"
+#include "ti_card_detec.h"
+
+/* Max number of MAC addresses that are parsed/processed per daughter card */
+#define DAUGHTER_CARD_NO_OF_MAC_ADDR 8
+
+static const char *k3_dtbo_list[AM64X_MAX_DAUGHTER_CARDS] = {NULL};
+
+static int init_daughtercard_det_gpio(char *gpio_name, struct gpio_desc *desc)
+{
+ int ret;
+
+ memset(desc, 0, sizeof(*desc));
+
+ ret = dm_gpio_lookup_name(gpio_name, desc);
+ if (ret < 0)
+ return ret;
+
+ /* Request GPIO, simply re-using the name as label */
+ ret = dm_gpio_request(desc, gpio_name);
+ if (ret < 0)
+ return ret;
+
+ return dm_gpio_set_dir_flags(desc, GPIOD_IS_IN);
+}
+
+int ti_card_detect(const struct ti_card_slot_map *slot_map, int num_slots,
+ const struct ti_card_info *cards, int num_cards,
+ struct list_head *extension_list)
+{
+ char mac_addr[DAUGHTER_CARD_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN];
+ struct gpio_desc *board_det_gpios;
+ struct ti_am6_eeprom ep;
+ struct extension *extn;
+ u8 mac_addr_cnt;
+ int found_cards = 0;
+ int i, j;
+ int ret;
+
+ board_det_gpios = calloc(num_slots, sizeof(struct gpio_desc));
+ if (!board_det_gpios)
+ return -ENOMEM;
+
+ /*
+ * Initialize GPIO used for daughtercard slot presence detection and
+ * keep the resulting handles in local array for easier access.
+ */
+ for (i = 0; i < num_slots; i++) {
+ ret = init_daughtercard_det_gpio(slot_map[i].gpio_name,
+ &board_det_gpios[i]);
+ if (ret < 0) {
+ pr_err("Couldn't get Card detect GPIO for slot %d: %d\n",
+ i, ret);
+ return ret;
+ }
+ }
+
+ for (i = 0; i < num_cards; i++) {
+ extn = calloc(1, sizeof(struct extension));
+ /* freed in cmd/extension_board.c */
+ if (!extn) {
+ pr_err("%s: Error in memory allocation\n", __func__);
+ return found_cards;
+ }
+
+ /* Obtain card-specific slot index and associated I2C address */
+ u8 slot_index = cards[i].slot_index;
+ u8 i2c_addr = slot_map[slot_index].i2c_addr;
+
+ /*
+ * The presence detection signal is active-low, hence skip
+ * over this card slot if anything other than 0 is returned.
+ */
+ ret = dm_gpio_get_value(&board_det_gpios[slot_index]);
+ if (ret < 0)
+ return ret;
+ else if (ret)
+ continue;
+
+ /* Get and parse the daughter card EEPROM record */
+ ret = ti_i2c_eeprom_am6_get(CONFIG_EEPROM_BUS_ADDRESS, i2c_addr,
+ &ep,
+ (char **)mac_addr,
+ DAUGHTER_CARD_NO_OF_MAC_ADDR,
+ &mac_addr_cnt);
+ if (ret) {
+ pr_err("Reading expansion card EEPROM at 0x%02x failed %d\n",
+ i2c_addr, ret);
+ /*
+ * Even this is pretty serious let's just skip over
+ * this particular daughtercard, rather than ending
+ * the probing process altogether.
+ */
+ continue;
+ }
+
+ /* Only process the parsed data if we found a match */
+ if (strncmp(ep.name, cards[i].card_name, sizeof(ep.name)))
+ continue;
+
+ printf("Detected: %s rev %s\n", ep.name, ep.version);
+
+ /*
+ * Populate any MAC addresses from daughtercard into the U-Boot
+ * environment, starting with a card-specific offset so we can
+ * have multiple cards contribute to the MAC pool in a well-
+ * defined manner.
+ */
+ for (j = 0; j < mac_addr_cnt; j++) {
+ if (!is_valid_ethaddr((u8 *)mac_addr[j]))
+ continue;
+
+ eth_env_set_enetaddr_by_index("eth",
+ cards[i].eth_offset + j,
+ (uchar *)mac_addr[j]);
+ }
+
+ /*
+ * It has been observed that setting SERDES0 lane mux to USB prevents USB
+ * 2.0 operation on USB0. Setting SERDES0 lane mux to non-USB when USB0 is
+ * used in USB 2.0 only mode solves this issue. For USB3.0+2.0 operation
+ * this issue is not present.
+ *
+ * Implement this workaround by writing 1 to LANE_FUNC_SEL field in
+ * CTRLMMR_SERDES0_CTRL register.
+ */
+ if (!strncmp(ep.name, "SER-PCIE2LEVM", sizeof(ep.name)))
+ writel(PCIE_LANE0, CTRLMMR_SERDES0_CTRL);
+
+ /* Skip if no overlays are to be added */
+ if (!strlen(cards[i].dtbo_name))
+ continue;
+
+ strlcpy(extn->overlay, cards[i].dtbo_name, sizeof(extn->overlay));
+ strlcpy(extn->name, cards[i].card_name, sizeof(extn->name));
+ strlcpy(extn->version, cards[i].version, sizeof(extn->version));
+ strlcpy(extn->owner, cards[i].owner, sizeof(extn->owner));
+ list_add_tail(&extn->list, extension_list);
+
+ found_cards++;
+ }
+
+ return found_cards;
+}
diff --git a/board/ti/common/ti_card_detect.h b/board/ti/common/ti_card_detect.h
new file mode 100644
index 0000000000..398376976a
--- /dev/null
+++ b/board/ti/common/ti_card_detect.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * TI EVM Extension card handling
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#define TI_CARD_OWNER "Texas Instruments Inc."
+#define TI_CARD_VERSION_1 "v1"
+/*
+ * ti_card_slot_map - A board may have 1 or more expansion slots.
+ * This data structure provides information for 1 slot.
+ *
+ * @det_gpio_name: GPIO name for the Expansion Card presense sense
+ * @card_i2c_addr: I2C address of expansion card EEPROM
+ */
+struct ti_card_slot_map {
+ char *det_gpio_name;
+ u8 card_i2c_addr;
+};
+
+/*
+ * ti_card_info - Information about a particular expansion card
+ *
+ * @slot_index: The Slot the card is typically installed in
+ * @card_name: EEPROM-programmed card name
+ * @dtbo_name: Device tree overlay for this card
+ * @eth_offset: ethXaddr MAC address index offset
+ * @owner: Manufacturer string
+ * @version: Version string
+ */
+struct ti_card_info {
+ u8 slot_index;
+ char *card_name;
+ char *dtbo_name;
+ u8 eth_offset;
+ char *owner;
+ char *version;
+};
+
+int ti_card_detect(const struct ti_card_slot_map *slot_map, int num_slots,
+ const struct ti_card_info *cards, int num_cards,
+ struct list_head *extension_list);
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig
index f294a4595f..e8e13479ce 100644
--- a/configs/am65x_evm_a53_defconfig
+++ b/configs/am65x_evm_a53_defconfig
@@ -179,3 +179,5 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0451
CONFIG_USB_GADGET_PRODUCT_NUM=0x6162
CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_PHANDLE_CHECK_SEQ=y
+CONFIG_SUPPORT_EXTENSION_SCAN=y
+CONFIG_CMD_EXTENSION=y
diff --git a/configs/am65x_hs_evm_a53_defconfig b/configs/am65x_hs_evm_a53_defconfig
index e0277d4787..ff569a9216 100644
--- a/configs/am65x_hs_evm_a53_defconfig
+++ b/configs/am65x_hs_evm_a53_defconfig
@@ -157,3 +157,5 @@ CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
CONFIG_USB_GADGET_VENDOR_NUM=0x0451
CONFIG_USB_GADGET_PRODUCT_NUM=0x6162
CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_SUPPORT_EXTENSION_SCAN=y
+CONFIG_CMD_EXTENSION=y
--
2.34.1
next prev parent reply other threads:[~2023-07-10 14:51 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-10 14:50 [RFC PATCH 0/2] board: ti: Use Extension framework Roger Quadros
2023-07-10 14:50 ` [RFC PATCH 1/2] board: ti: common: Add CONFIG_TI_CAPE_DETECT for cape detection Roger Quadros
2023-07-10 14:50 ` Roger Quadros [this message]
2023-07-10 19:45 ` [RFC PATCH 2/2] board: ti: am65x: Move to using Extension framework Simon Glass
2023-07-11 12:29 ` Roger Quadros
2023-07-13 18:44 ` Nishanth Menon
2023-10-04 12:39 ` Roger Quadros
2023-10-06 13:26 ` Köry Maincent
2023-10-06 15:48 ` Roger Quadros
2023-10-06 16:47 ` Simon Glass
2024-01-11 14:14 ` Roger Quadros
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230710145026.128481-3-rogerq@kernel.org \
--to=rogerq@kernel.org \
--cc=nm@ti.com \
--cc=robertcnelson@gmail.com \
--cc=srk@ti.com \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
--cc=vigneshr@ti.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.