Neil Armstrong | 7520aba | 2020-09-21 09:34:13 +0200 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | /* |
| 3 | * Copyright (C) 2020 BayLibre, SAS |
| 4 | * Author: Neil Armstrong <narmstrong@baylibre.com> |
| 5 | */ |
| 6 | |
Neil Armstrong | 7520aba | 2020-09-21 09:34:13 +0200 | [diff] [blame] | 7 | #include <dm.h> |
| 8 | #include <env_internal.h> |
| 9 | #include <init.h> |
| 10 | #include <net.h> |
| 11 | #include <asm/io.h> |
Marek Szyprowski | b3e9712 | 2020-12-18 15:26:45 +0100 | [diff] [blame] | 12 | #include <asm/arch/boot.h> |
Neil Armstrong | 7520aba | 2020-09-21 09:34:13 +0200 | [diff] [blame] | 13 | #include <asm/arch/eth.h> |
Marek Szyprowski | bdcffaf | 2020-12-17 08:26:42 +0100 | [diff] [blame] | 14 | #include <asm/arch/sm.h> |
Simon Glass | 3ba929a | 2020-10-30 21:38:53 -0600 | [diff] [blame] | 15 | #include <asm/global_data.h> |
Neil Armstrong | 29f59e8 | 2020-09-21 09:34:15 +0200 | [diff] [blame] | 16 | #include <i2c.h> |
| 17 | #include "khadas-mcu.h" |
| 18 | |
Marek Szyprowski | b3e9712 | 2020-12-18 15:26:45 +0100 | [diff] [blame] | 19 | int mmc_get_env_dev(void) |
| 20 | { |
Artem Lapkin | de89f45 | 2021-05-27 15:35:28 +0800 | [diff] [blame] | 21 | switch (meson_get_boot_device()) { |
| 22 | case BOOT_DEVICE_EMMC: |
Marek Szyprowski | b3e9712 | 2020-12-18 15:26:45 +0100 | [diff] [blame] | 23 | return 2; |
Artem Lapkin | de89f45 | 2021-05-27 15:35:28 +0800 | [diff] [blame] | 24 | case BOOT_DEVICE_SD: |
| 25 | return 1; |
| 26 | default: |
| 27 | /* boot device is not EMMC|SD */ |
| 28 | return -1; |
| 29 | } |
Marek Szyprowski | b3e9712 | 2020-12-18 15:26:45 +0100 | [diff] [blame] | 30 | } |
| 31 | |
Neil Armstrong | 29f59e8 | 2020-09-21 09:34:15 +0200 | [diff] [blame] | 32 | /* |
| 33 | * The VIM3 on-board MCU can mux the PCIe/USB3.0 shared differential |
| 34 | * lines using a FUSB340TMX USB 3.1 SuperSpeed Data Switch between |
| 35 | * an USB3.0 Type A connector and a M.2 Key M slot. |
| 36 | * The PHY driving these differential lines is shared between |
| 37 | * the USB3.0 controller and the PCIe Controller, thus only |
| 38 | * a single controller can use it. |
| 39 | */ |
| 40 | int meson_ft_board_setup(void *blob, struct bd_info *bd) |
| 41 | { |
| 42 | struct udevice *bus, *dev; |
| 43 | int node, i2c_node, ret; |
| 44 | unsigned int i2c_addr; |
| 45 | u32 *val; |
| 46 | |
| 47 | /* Find I2C device */ |
| 48 | node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "khadas,mcu"); |
| 49 | if (node < 0) { |
| 50 | printf("vim3: cannot find khadas,mcu node\n"); |
| 51 | return 0; |
| 52 | } |
| 53 | |
| 54 | /* Get addr */ |
| 55 | val = (u32 *)fdt_getprop(gd->fdt_blob, node, "reg", NULL); |
| 56 | if (!val) { |
| 57 | printf("vim3: cannot find khadas,mcu node i2c addr\n"); |
| 58 | return 0; |
| 59 | } |
| 60 | i2c_addr = fdt32_to_cpu(*val); |
| 61 | |
| 62 | /* Get i2c device */ |
| 63 | i2c_node = fdt_parent_offset(gd->fdt_blob, node); |
| 64 | if (node < 0) { |
| 65 | printf("vim3: cannot find khadas,mcu i2c node\n"); |
| 66 | return 0; |
| 67 | } |
| 68 | |
| 69 | ret = uclass_get_device_by_of_offset(UCLASS_I2C, i2c_node, &bus); |
| 70 | if (ret < 0) { |
| 71 | printf("vim3: cannot find i2c bus (%d)\n", ret); |
| 72 | return 0; |
| 73 | } |
| 74 | |
| 75 | ret = i2c_get_chip(bus, i2c_addr, 1, &dev); |
| 76 | if (ret < 0) { |
| 77 | printf("vim3: cannot find i2c chip (%d)\n", ret); |
| 78 | return 0; |
| 79 | } |
| 80 | |
| 81 | /* Read USB_PCIE_SWITCH_REG */ |
| 82 | ret = dm_i2c_reg_read(dev, KHADAS_MCU_USB_PCIE_SWITCH_REG); |
| 83 | if (ret < 0) { |
| 84 | printf("vim3: failed to read i2c reg (%d)\n", ret); |
| 85 | return 0; |
| 86 | } |
| 87 | debug("MCU_USB_PCIE_SWITCH_REG: %d\n", ret); |
| 88 | |
| 89 | /* |
| 90 | * If in PCIe mode, alter DT |
Michal Simek | cc046dc | 2024-04-16 08:55:19 +0200 | [diff] [blame] | 91 | * 0: Enable USB3.0, Disable PCIE, 1: Disable USB3.0, Enable PCIE |
Neil Armstrong | 29f59e8 | 2020-09-21 09:34:15 +0200 | [diff] [blame] | 92 | */ |
| 93 | if (ret > 0) { |
| 94 | static char data[32] __aligned(4); |
| 95 | const void *ptmp; |
| 96 | int len; |
| 97 | |
| 98 | /* Find USB node */ |
| 99 | node = fdt_node_offset_by_compatible(blob, -1, "amlogic,meson-g12a-usb-ctrl"); |
| 100 | if (node < 0) { |
| 101 | printf("vim3: cannot find amlogic,meson-g12a-usb-ctrl node\n"); |
| 102 | return 0; |
| 103 | } |
| 104 | |
| 105 | /* Update PHY names (mandatory to disable USB3.0) */ |
Matthias Schiffer | 02482ee | 2023-07-14 13:24:50 +0200 | [diff] [blame] | 106 | len = strlcpy(data, "usb2-phy0", 32) + 1; |
| 107 | len += strlcpy(&data[len], "usb2-phy1", 32 - len) + 1; |
Neil Armstrong | 29f59e8 | 2020-09-21 09:34:15 +0200 | [diff] [blame] | 108 | ret = fdt_setprop(blob, node, "phy-names", data, len); |
| 109 | if (ret < 0) { |
| 110 | printf("vim3: failed to update usb phy names property (%d)\n", ret); |
| 111 | return 0; |
| 112 | } |
| 113 | |
| 114 | /* Update PHY list, by keeping the 2 first entries (optional) */ |
| 115 | ptmp = fdt_getprop(blob, node, "phys", &len); |
| 116 | if (ptmp) { |
| 117 | memcpy(data, ptmp, min_t(unsigned int, 2 * sizeof(u32), len)); |
| 118 | |
| 119 | ret = fdt_setprop(blob, node, "phys", data, |
| 120 | min_t(unsigned int, 2 * sizeof(u32), len)); |
| 121 | if (ret < 0) |
| 122 | printf("vim3: failed to update usb phys property (%d)\n", ret); |
| 123 | } else |
| 124 | printf("vim3: cannot find usb node phys property\n"); |
| 125 | |
| 126 | /* Find PCIe node */ |
| 127 | node = fdt_node_offset_by_compatible(blob, -1, "amlogic,g12a-pcie"); |
| 128 | if (node < 0) { |
| 129 | printf("vim3: cannot find amlogic,g12a-pcie node\n"); |
| 130 | return 0; |
| 131 | } |
| 132 | |
| 133 | /* Enable PCIe */ |
Matthias Schiffer | 02482ee | 2023-07-14 13:24:50 +0200 | [diff] [blame] | 134 | len = strlcpy(data, "okay", 32) + 1; |
Neil Armstrong | 29f59e8 | 2020-09-21 09:34:15 +0200 | [diff] [blame] | 135 | ret = fdt_setprop(blob, node, "status", data, len); |
| 136 | if (ret < 0) { |
| 137 | printf("vim3: failed to enable pcie node (%d)\n", ret); |
| 138 | return 0; |
| 139 | } |
| 140 | |
| 141 | printf("vim3: successfully enabled PCIe\n"); |
| 142 | } |
| 143 | |
| 144 | return 0; |
| 145 | } |
Neil Armstrong | 7520aba | 2020-09-21 09:34:13 +0200 | [diff] [blame] | 146 | |
Marek Szyprowski | bdcffaf | 2020-12-17 08:26:42 +0100 | [diff] [blame] | 147 | #define EFUSE_MAC_OFFSET 0 |
Artem Lapkin | 400b9556 | 2021-01-12 19:42:12 +0800 | [diff] [blame] | 148 | #define EFUSE_MAC_SIZE 12 |
| 149 | #define MAC_ADDR_LEN 6 |
Marek Szyprowski | bdcffaf | 2020-12-17 08:26:42 +0100 | [diff] [blame] | 150 | |
Neil Armstrong | 7520aba | 2020-09-21 09:34:13 +0200 | [diff] [blame] | 151 | int misc_init_r(void) |
| 152 | { |
Neil Armstrong | bfbe81a | 2024-03-20 09:46:11 +0100 | [diff] [blame] | 153 | u8 mac_addr[MAC_ADDR_LEN + 1]; |
Artem Lapkin | 400b9556 | 2021-01-12 19:42:12 +0800 | [diff] [blame] | 154 | char efuse_mac_addr[EFUSE_MAC_SIZE], tmp[3]; |
Mattijs Korpershoek | a96d6b5 | 2022-01-19 15:24:00 +0100 | [diff] [blame] | 155 | char serial_string[EFUSE_MAC_SIZE + 1]; |
Marek Szyprowski | bdcffaf | 2020-12-17 08:26:42 +0100 | [diff] [blame] | 156 | ssize_t len; |
| 157 | |
Marek Szyprowski | bdcffaf | 2020-12-17 08:26:42 +0100 | [diff] [blame] | 158 | if (!eth_env_get_enetaddr("ethaddr", mac_addr)) { |
| 159 | len = meson_sm_read_efuse(EFUSE_MAC_OFFSET, |
Artem Lapkin | 400b9556 | 2021-01-12 19:42:12 +0800 | [diff] [blame] | 160 | efuse_mac_addr, EFUSE_MAC_SIZE); |
Marek Szyprowski | bdcffaf | 2020-12-17 08:26:42 +0100 | [diff] [blame] | 161 | if (len != EFUSE_MAC_SIZE) |
| 162 | return 0; |
| 163 | |
Artem Lapkin | 400b9556 | 2021-01-12 19:42:12 +0800 | [diff] [blame] | 164 | /* MAC is stored in ASCII format, 1bytes = 2characters */ |
| 165 | for (int i = 0; i < 6; i++) { |
| 166 | tmp[0] = efuse_mac_addr[i * 2]; |
| 167 | tmp[1] = efuse_mac_addr[i * 2 + 1]; |
| 168 | tmp[2] = '\0'; |
Simon Glass | 3ff49ec | 2021-07-24 09:03:29 -0600 | [diff] [blame] | 169 | mac_addr[i] = hextoul(tmp, NULL); |
Artem Lapkin | 400b9556 | 2021-01-12 19:42:12 +0800 | [diff] [blame] | 170 | } |
Neil Armstrong | bfbe81a | 2024-03-20 09:46:11 +0100 | [diff] [blame] | 171 | mac_addr[MAC_ADDR_LEN] = '\0'; |
Artem Lapkin | 400b9556 | 2021-01-12 19:42:12 +0800 | [diff] [blame] | 172 | |
Marek Szyprowski | bdcffaf | 2020-12-17 08:26:42 +0100 | [diff] [blame] | 173 | if (is_valid_ethaddr(mac_addr)) |
| 174 | eth_env_set_enetaddr("ethaddr", mac_addr); |
| 175 | else |
| 176 | meson_generate_serial_ethaddr(); |
Artem Lapkin | 400b9556 | 2021-01-12 19:42:12 +0800 | [diff] [blame] | 177 | |
| 178 | eth_env_get_enetaddr("ethaddr", mac_addr); |
Marek Szyprowski | bdcffaf | 2020-12-17 08:26:42 +0100 | [diff] [blame] | 179 | } |
| 180 | |
Mattijs Korpershoek | a96d6b5 | 2022-01-19 15:24:00 +0100 | [diff] [blame] | 181 | if (!env_get("serial#")) { |
| 182 | eth_env_get_enetaddr("ethaddr", mac_addr); |
| 183 | sprintf(serial_string, "%02X%02X%02X%02X%02X%02X", |
| 184 | mac_addr[0], mac_addr[1], mac_addr[2], |
| 185 | mac_addr[3], mac_addr[4], mac_addr[5]); |
| 186 | env_set("serial#", serial_string); |
| 187 | } |
| 188 | |
Neil Armstrong | 7520aba | 2020-09-21 09:34:13 +0200 | [diff] [blame] | 189 | return 0; |
| 190 | } |