usb: xhci: Make debug output better readable and checkpatch clean
[platform/kernel/u-boot.git] / board / amlogic / vim3 / vim3.c
1 // 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/boot.h>
14 #include <asm/arch/eth.h>
15 #include <asm/arch/sm.h>
16 #include <asm/global_data.h>
17 #include <i2c.h>
18 #include "khadas-mcu.h"
19
20 int mmc_get_env_dev(void)
21 {
22         if (meson_get_boot_device() == BOOT_DEVICE_EMMC)
23                 return 2;
24         return 1;
25 }
26
27 /*
28  * The VIM3 on-board  MCU can mux the PCIe/USB3.0 shared differential
29  * lines using a FUSB340TMX USB 3.1 SuperSpeed Data Switch between
30  * an USB3.0 Type A connector and a M.2 Key M slot.
31  * The PHY driving these differential lines is shared between
32  * the USB3.0 controller and the PCIe Controller, thus only
33  * a single controller can use it.
34  */
35 int meson_ft_board_setup(void *blob, struct bd_info *bd)
36 {
37         struct udevice *bus, *dev;
38         int node, i2c_node, ret;
39         unsigned int i2c_addr;
40         u32 *val;
41
42         /* Find I2C device */
43         node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "khadas,mcu");
44         if (node < 0) {
45                 printf("vim3: cannot find khadas,mcu node\n");
46                 return 0;
47         }
48
49         /* Get addr */
50         val = (u32 *)fdt_getprop(gd->fdt_blob, node, "reg", NULL);
51         if (!val) {
52                 printf("vim3: cannot find khadas,mcu node i2c addr\n");
53                 return 0;
54         }
55         i2c_addr = fdt32_to_cpu(*val);
56
57         /* Get i2c device */
58         i2c_node = fdt_parent_offset(gd->fdt_blob, node);
59         if (node < 0) {
60                 printf("vim3: cannot find khadas,mcu i2c node\n");
61                 return 0;
62         }
63
64         ret = uclass_get_device_by_of_offset(UCLASS_I2C, i2c_node, &bus);
65         if (ret < 0) {
66                 printf("vim3: cannot find i2c bus (%d)\n", ret);
67                 return 0;
68         }
69
70         ret = i2c_get_chip(bus, i2c_addr, 1, &dev);
71         if (ret < 0) {
72                 printf("vim3: cannot find i2c chip (%d)\n", ret);
73                 return 0;
74         }
75
76         /* Read USB_PCIE_SWITCH_REG */
77         ret = dm_i2c_reg_read(dev, KHADAS_MCU_USB_PCIE_SWITCH_REG);
78         if (ret < 0) {
79                 printf("vim3: failed to read i2c reg (%d)\n", ret);
80                 return 0;
81         }
82         debug("MCU_USB_PCIE_SWITCH_REG: %d\n", ret);
83
84         /*
85          * If in PCIe mode, alter DT
86          * 0:Enable USB3.0,Disable PCIE, 1:Disable USB3.0, Enable PCIE
87          */
88         if (ret > 0) {
89                 static char data[32] __aligned(4);
90                 const void *ptmp;
91                 int len;
92
93                 /* Find USB node */
94                 node = fdt_node_offset_by_compatible(blob, -1, "amlogic,meson-g12a-usb-ctrl");
95                 if (node < 0) {
96                         printf("vim3: cannot find amlogic,meson-g12a-usb-ctrl node\n");
97                         return 0;
98                 }
99
100                 /* Update PHY names (mandatory to disable USB3.0) */
101                 len = strlcpy(data, "usb2-phy0", 32) + 1;
102                 len += strlcpy(&data[len], "usb2-phy1", 32 - len) + 1;
103                 ret = fdt_setprop(blob, node, "phy-names", data, len);
104                 if (ret < 0) {
105                         printf("vim3: failed to update usb phy names property (%d)\n", ret);
106                         return 0;
107                 }
108
109                 /* Update PHY list, by keeping the 2 first entries (optional) */
110                 ptmp = fdt_getprop(blob, node, "phys", &len);
111                 if (ptmp) {
112                         memcpy(data, ptmp, min_t(unsigned int, 2 * sizeof(u32), len));
113
114                         ret = fdt_setprop(blob, node, "phys", data,
115                                           min_t(unsigned int, 2 * sizeof(u32), len));
116                         if (ret < 0)
117                                 printf("vim3: failed to update usb phys property (%d)\n", ret);
118                 } else
119                         printf("vim3: cannot find usb node phys property\n");
120
121                 /* Find PCIe node */
122                 node = fdt_node_offset_by_compatible(blob, -1, "amlogic,g12a-pcie");
123                 if (node < 0) {
124                         printf("vim3: cannot find amlogic,g12a-pcie node\n");
125                         return 0;
126                 }
127
128                 /* Enable PCIe */
129                 len = strlcpy(data, "okay", 32);
130                 ret = fdt_setprop(blob, node, "status", data, len);
131                 if (ret < 0) {
132                         printf("vim3: failed to enable pcie node (%d)\n", ret);
133                         return 0;
134                 }
135
136                 printf("vim3: successfully enabled PCIe\n");
137         }
138
139         return 0;
140 }
141
142 #define EFUSE_MAC_OFFSET        0
143 #define EFUSE_MAC_SIZE          12
144 #define MAC_ADDR_LEN            6
145
146 int misc_init_r(void)
147 {
148         u8 mac_addr[MAC_ADDR_LEN];
149         char efuse_mac_addr[EFUSE_MAC_SIZE], tmp[3];
150         ssize_t len;
151
152         meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
153
154         if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
155                 len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
156                                           efuse_mac_addr, EFUSE_MAC_SIZE);
157                 if (len != EFUSE_MAC_SIZE)
158                         return 0;
159
160                 /* MAC is stored in ASCII format, 1bytes = 2characters */
161                 for (int i = 0; i < 6; i++) {
162                         tmp[0] = efuse_mac_addr[i * 2];
163                         tmp[1] = efuse_mac_addr[i * 2 + 1];
164                         tmp[2] = '\0';
165                         mac_addr[i] = simple_strtoul(tmp, NULL, 16);
166                 }
167
168                 if (is_valid_ethaddr(mac_addr))
169                         eth_env_set_enetaddr("ethaddr", mac_addr);
170                 else
171                         meson_generate_serial_ethaddr();
172
173                 eth_env_get_enetaddr("ethaddr", mac_addr);
174         }
175
176         return 0;
177 }