blob: a36df61583d93d3e4c2978068f72c04bf4ce9287 [file] [log] [blame]
Neil Armstrong7520aba2020-09-21 09:34:13 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2020 BayLibre, SAS
4 * Author: Neil Armstrong <narmstrong@baylibre.com>
5 */
6
7#include <common.h>
8#include <dm.h>
9#include <env_internal.h>
10#include <init.h>
11#include <net.h>
12#include <asm/io.h>
13#include <asm/arch/eth.h>
Marek Szyprowskibdcffaf2020-12-17 08:26:42 +010014#include <asm/arch/sm.h>
Neil Armstrong29f59e82020-09-21 09:34:15 +020015#include <i2c.h>
16#include "khadas-mcu.h"
17
18/*
19 * The VIM3 on-board MCU can mux the PCIe/USB3.0 shared differential
20 * lines using a FUSB340TMX USB 3.1 SuperSpeed Data Switch between
21 * an USB3.0 Type A connector and a M.2 Key M slot.
22 * The PHY driving these differential lines is shared between
23 * the USB3.0 controller and the PCIe Controller, thus only
24 * a single controller can use it.
25 */
26int meson_ft_board_setup(void *blob, struct bd_info *bd)
27{
28 struct udevice *bus, *dev;
29 int node, i2c_node, ret;
30 unsigned int i2c_addr;
31 u32 *val;
32
33 /* Find I2C device */
34 node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "khadas,mcu");
35 if (node < 0) {
36 printf("vim3: cannot find khadas,mcu node\n");
37 return 0;
38 }
39
40 /* Get addr */
41 val = (u32 *)fdt_getprop(gd->fdt_blob, node, "reg", NULL);
42 if (!val) {
43 printf("vim3: cannot find khadas,mcu node i2c addr\n");
44 return 0;
45 }
46 i2c_addr = fdt32_to_cpu(*val);
47
48 /* Get i2c device */
49 i2c_node = fdt_parent_offset(gd->fdt_blob, node);
50 if (node < 0) {
51 printf("vim3: cannot find khadas,mcu i2c node\n");
52 return 0;
53 }
54
55 ret = uclass_get_device_by_of_offset(UCLASS_I2C, i2c_node, &bus);
56 if (ret < 0) {
57 printf("vim3: cannot find i2c bus (%d)\n", ret);
58 return 0;
59 }
60
61 ret = i2c_get_chip(bus, i2c_addr, 1, &dev);
62 if (ret < 0) {
63 printf("vim3: cannot find i2c chip (%d)\n", ret);
64 return 0;
65 }
66
67 /* Read USB_PCIE_SWITCH_REG */
68 ret = dm_i2c_reg_read(dev, KHADAS_MCU_USB_PCIE_SWITCH_REG);
69 if (ret < 0) {
70 printf("vim3: failed to read i2c reg (%d)\n", ret);
71 return 0;
72 }
73 debug("MCU_USB_PCIE_SWITCH_REG: %d\n", ret);
74
75 /*
76 * If in PCIe mode, alter DT
77 * 0:Enable USB3.0,Disable PCIE, 1:Disable USB3.0, Enable PCIE
78 */
79 if (ret > 0) {
80 static char data[32] __aligned(4);
81 const void *ptmp;
82 int len;
83
84 /* Find USB node */
85 node = fdt_node_offset_by_compatible(blob, -1, "amlogic,meson-g12a-usb-ctrl");
86 if (node < 0) {
87 printf("vim3: cannot find amlogic,meson-g12a-usb-ctrl node\n");
88 return 0;
89 }
90
91 /* Update PHY names (mandatory to disable USB3.0) */
92 len = strlcpy(data, "usb2-phy0", 32) + 1;
93 len += strlcpy(&data[len], "usb2-phy1", 32 - len) + 1;
94 ret = fdt_setprop(blob, node, "phy-names", data, len);
95 if (ret < 0) {
96 printf("vim3: failed to update usb phy names property (%d)\n", ret);
97 return 0;
98 }
99
100 /* Update PHY list, by keeping the 2 first entries (optional) */
101 ptmp = fdt_getprop(blob, node, "phys", &len);
102 if (ptmp) {
103 memcpy(data, ptmp, min_t(unsigned int, 2 * sizeof(u32), len));
104
105 ret = fdt_setprop(blob, node, "phys", data,
106 min_t(unsigned int, 2 * sizeof(u32), len));
107 if (ret < 0)
108 printf("vim3: failed to update usb phys property (%d)\n", ret);
109 } else
110 printf("vim3: cannot find usb node phys property\n");
111
112 /* Find PCIe node */
113 node = fdt_node_offset_by_compatible(blob, -1, "amlogic,g12a-pcie");
114 if (node < 0) {
115 printf("vim3: cannot find amlogic,g12a-pcie node\n");
116 return 0;
117 }
118
119 /* Enable PCIe */
120 len = strlcpy(data, "okay", 32);
121 ret = fdt_setprop(blob, node, "status", data, len);
122 if (ret < 0) {
123 printf("vim3: failed to enable pcie node (%d)\n", ret);
124 return 0;
125 }
126
127 printf("vim3: successfully enabled PCIe\n");
128 }
129
130 return 0;
131}
Neil Armstrong7520aba2020-09-21 09:34:13 +0200132
Marek Szyprowskibdcffaf2020-12-17 08:26:42 +0100133#define EFUSE_MAC_OFFSET 0
134#define EFUSE_MAC_SIZE 6
135
Neil Armstrong7520aba2020-09-21 09:34:13 +0200136int misc_init_r(void)
137{
Marek Szyprowskibdcffaf2020-12-17 08:26:42 +0100138 uint8_t mac_addr[EFUSE_MAC_SIZE];
139 ssize_t len;
140
Neil Armstrong7520aba2020-09-21 09:34:13 +0200141 meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
142
Marek Szyprowskibdcffaf2020-12-17 08:26:42 +0100143 if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
144 len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
145 mac_addr, EFUSE_MAC_SIZE);
146 if (len != EFUSE_MAC_SIZE)
147 return 0;
148
149 if (is_valid_ethaddr(mac_addr))
150 eth_env_set_enetaddr("ethaddr", mac_addr);
151 else
152 meson_generate_serial_ethaddr();
153 }
154
Neil Armstrong7520aba2020-09-21 09:34:13 +0200155 return 0;
156}