aboutsummaryrefslogtreecommitdiff
path: root/board/CZ.NIC
diff options
context:
space:
mode:
authorPali Rohár2022-03-02 12:47:58 +0100
committerStefan Roese2022-05-02 07:28:25 +0200
commit73c7db73e8f1a1e6ea59f0e5bdd8e825792eb41c (patch)
tree48d33d927411aef17278acdd69ed0afeb2565ec4 /board/CZ.NIC
parent72a9dd264c15e287ac5168d387cfa77710d22982 (diff)
arm: mvebu: turris_omnia: Add support for USB3.0 mode in WWAN MiniPCIe slot
PCIe Mini CEM 2.1 spec added support for USB3.0 mode on MiniPCIe cards. USB3.0 and PCIe share same pins and only one function can be active at the same time. PCIe Mini CEM 2.1 spec says that determining function is platform specific and spec does not define any dedicated pin which could say if card is USB3.0-based or PCIe-based. Implement this platform specific decision (USB3.0 vs PCIe) for WWAN MiniPCIe slot on Turris Omnia via U-Boot env variable "omnia_wwan_slot", similarly like is implemented forced mode for MiniPCIe/mSATA slot via "omnia_msata_slot" env variable. Value "usb3" for "omnia_wwan_slot" would mean to set USB3.0 mode and value "pcie" original PCIe mode. A385 SoC on Turris Omnia has configurable fifth SerDes line (exported to MiniPCIe WWAN slot with SIM card) either to USB3.0 or PCIe functionality, so implementation of this new PCIe Mini CEM 2.1 feature is simple, by just configuring SerDes to USB 3.0 mode. Other twos MiniPCIe slots on Turris Omnia do not have this new functionality as their SerDes lines cannot be switched to USB3.0 functionality. Note that A385 SoC does not have too many USB3.0 blocks, so activating USB3.0 in MiniPCIe cause that one external USB3.0 USB-A port would loose USB3.0 functionality and would be downgraded just to USB2.0. By default this MiniPCIe WWAN slot is in PCIe mode, like before. To set this MiniPCIe WWAN slot to USB3.0 mode, call U-Boot commands: => setenv omnia_wwan_slot usb3 => saveenv => reset Signed-off-by: Pali Rohár <pali@kernel.org>
Diffstat (limited to 'board/CZ.NIC')
-rw-r--r--board/CZ.NIC/turris_omnia/turris_omnia.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c
index 1f69b3d166d..e768e6e5322 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -239,6 +239,22 @@ static bool omnia_detect_sata(const char *msata_slot)
return stsword & MSATA_IND_STSBIT ? true : false;
}
+static bool omnia_detect_wwan_usb3(const char *wwan_slot)
+{
+ puts("WWAN slot configuration... ");
+
+ if (wwan_slot && strcmp(wwan_slot, "usb3") == 0) {
+ puts("USB3.0\n");
+ return true;
+ }
+
+ if (wwan_slot && strcmp(wwan_slot, "pcie") != 0)
+ printf("unsupported env value '%s', fallback to... ", wwan_slot);
+
+ puts("PCIe+USB2.0\n");
+ return false;
+}
+
void *env_sf_get_env_addr(void)
{
/* SPI Flash is mapped to address 0xD4000000 only in SPL */
@@ -269,6 +285,20 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
board_serdes_map[0].serdes_mode = SERDES_DEFAULT_MODE;
}
+#ifdef CONFIG_SPL_ENV_SUPPORT
+ /* beware that env_get() returns static allocated memory */
+ env_value = has_env ? env_get("omnia_wwan_slot") : NULL;
+#endif
+
+ if (omnia_detect_wwan_usb3(env_value)) {
+ /* Disable SerDes for USB 3.0 pins on the front USB-A port */
+ board_serdes_map[1].serdes_type = DEFAULT_SERDES;
+ /* Change SerDes for third mPCIe port (WWAN) from PCIe to USB 3.0 */
+ board_serdes_map[4].serdes_type = USB3_HOST0;
+ board_serdes_map[4].serdes_speed = SERDES_SPEED_5_GBPS;
+ board_serdes_map[4].serdes_mode = SERDES_DEFAULT_MODE;
+ }
+
*serdes_map_array = board_serdes_map;
*count = ARRAY_SIZE(board_serdes_map);
@@ -590,12 +620,38 @@ static void fixup_msata_port_nodes(void *blob)
}
}
+static void fixup_wwan_port_nodes(void *blob)
+{
+ bool mode_usb3;
+
+ /* Determine if SerDes 4 is configured to USB3 mode */
+ mode_usb3 = ((readl(MVEBU_REGISTER(0x183fc)) & GENMASK(19, 16)) >> 16) == 4;
+
+ /* If SerDes 4 is not configured to USB3 mode then nothing is needed to fixup */
+ if (!mode_usb3)
+ return;
+
+ /*
+ * We're either adding status = "disabled" property, or changing
+ * status = "okay" to status = "disabled". In both cases we'll need more
+ * space. Increase the size a little.
+ */
+ if (fdt_increase_size(blob, 32) < 0) {
+ printf("Cannot increase FDT size!\n");
+ return;
+ }
+
+ /* Disable PCIe port 2 DT node (WWAN) */
+ disable_pcie_node(blob, 2);
+}
+
#endif
#if IS_ENABLED(CONFIG_OF_BOARD_FIXUP)
int board_fix_fdt(void *blob)
{
fixup_msata_port_nodes(blob);
+ fixup_wwan_port_nodes(blob);
return 0;
}
@@ -741,6 +797,7 @@ int ft_board_setup(void *blob, struct bd_info *bd)
{
fixup_spi_nor_partitions(blob);
fixup_msata_port_nodes(blob);
+ fixup_wwan_port_nodes(blob);
return 0;
}