blob: 09ef39ff30adbd4faf6ae99af2a8d20fe46f6f44 [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>
Neil Armstrong29f59e82020-09-21 09:34:15 +020014#include <i2c.h>
15#include "khadas-mcu.h"
16
17/*
18 * The VIM3 on-board MCU can mux the PCIe/USB3.0 shared differential
19 * lines using a FUSB340TMX USB 3.1 SuperSpeed Data Switch between
20 * an USB3.0 Type A connector and a M.2 Key M slot.
21 * The PHY driving these differential lines is shared between
22 * the USB3.0 controller and the PCIe Controller, thus only
23 * a single controller can use it.
24 */
25int meson_ft_board_setup(void *blob, struct bd_info *bd)
26{
27 struct udevice *bus, *dev;
28 int node, i2c_node, ret;
29 unsigned int i2c_addr;
30 u32 *val;
31
32 /* Find I2C device */
33 node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "khadas,mcu");
34 if (node < 0) {
35 printf("vim3: cannot find khadas,mcu node\n");
36 return 0;
37 }
38
39 /* Get addr */
40 val = (u32 *)fdt_getprop(gd->fdt_blob, node, "reg", NULL);
41 if (!val) {
42 printf("vim3: cannot find khadas,mcu node i2c addr\n");
43 return 0;
44 }
45 i2c_addr = fdt32_to_cpu(*val);
46
47 /* Get i2c device */
48 i2c_node = fdt_parent_offset(gd->fdt_blob, node);
49 if (node < 0) {
50 printf("vim3: cannot find khadas,mcu i2c node\n");
51 return 0;
52 }
53
54 ret = uclass_get_device_by_of_offset(UCLASS_I2C, i2c_node, &bus);
55 if (ret < 0) {
56 printf("vim3: cannot find i2c bus (%d)\n", ret);
57 return 0;
58 }
59
60 ret = i2c_get_chip(bus, i2c_addr, 1, &dev);
61 if (ret < 0) {
62 printf("vim3: cannot find i2c chip (%d)\n", ret);
63 return 0;
64 }
65
66 /* Read USB_PCIE_SWITCH_REG */
67 ret = dm_i2c_reg_read(dev, KHADAS_MCU_USB_PCIE_SWITCH_REG);
68 if (ret < 0) {
69 printf("vim3: failed to read i2c reg (%d)\n", ret);
70 return 0;
71 }
72 debug("MCU_USB_PCIE_SWITCH_REG: %d\n", ret);
73
74 /*
75 * If in PCIe mode, alter DT
76 * 0:Enable USB3.0,Disable PCIE, 1:Disable USB3.0, Enable PCIE
77 */
78 if (ret > 0) {
79 static char data[32] __aligned(4);
80 const void *ptmp;
81 int len;
82
83 /* Find USB node */
84 node = fdt_node_offset_by_compatible(blob, -1, "amlogic,meson-g12a-usb-ctrl");
85 if (node < 0) {
86 printf("vim3: cannot find amlogic,meson-g12a-usb-ctrl node\n");
87 return 0;
88 }
89
90 /* Update PHY names (mandatory to disable USB3.0) */
91 len = strlcpy(data, "usb2-phy0", 32) + 1;
92 len += strlcpy(&data[len], "usb2-phy1", 32 - len) + 1;
93 ret = fdt_setprop(blob, node, "phy-names", data, len);
94 if (ret < 0) {
95 printf("vim3: failed to update usb phy names property (%d)\n", ret);
96 return 0;
97 }
98
99 /* Update PHY list, by keeping the 2 first entries (optional) */
100 ptmp = fdt_getprop(blob, node, "phys", &len);
101 if (ptmp) {
102 memcpy(data, ptmp, min_t(unsigned int, 2 * sizeof(u32), len));
103
104 ret = fdt_setprop(blob, node, "phys", data,
105 min_t(unsigned int, 2 * sizeof(u32), len));
106 if (ret < 0)
107 printf("vim3: failed to update usb phys property (%d)\n", ret);
108 } else
109 printf("vim3: cannot find usb node phys property\n");
110
111 /* Find PCIe node */
112 node = fdt_node_offset_by_compatible(blob, -1, "amlogic,g12a-pcie");
113 if (node < 0) {
114 printf("vim3: cannot find amlogic,g12a-pcie node\n");
115 return 0;
116 }
117
118 /* Enable PCIe */
119 len = strlcpy(data, "okay", 32);
120 ret = fdt_setprop(blob, node, "status", data, len);
121 if (ret < 0) {
122 printf("vim3: failed to enable pcie node (%d)\n", ret);
123 return 0;
124 }
125
126 printf("vim3: successfully enabled PCIe\n");
127 }
128
129 return 0;
130}
Neil Armstrong7520aba2020-09-21 09:34:13 +0200131
132int misc_init_r(void)
133{
134 meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
135
136 return 0;
137}