vim3.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2020 BayLibre, SAS
  4. * Author: Neil Armstrong <narmstrong@baylibre.com>
  5. */
  6. #include <common.h>
  7. #include <dm.h>
  8. #include <env_internal.h>
  9. #include <init.h>
  10. #include <net.h>
  11. #include <asm/io.h>
  12. #include <asm/arch/boot.h>
  13. #include <asm/arch/eth.h>
  14. #include <asm/arch/sm.h>
  15. #include <asm/global_data.h>
  16. #include <i2c.h>
  17. #include "khadas-mcu.h"
  18. int mmc_get_env_dev(void)
  19. {
  20. switch (meson_get_boot_device()) {
  21. case BOOT_DEVICE_EMMC:
  22. return 2;
  23. case BOOT_DEVICE_SD:
  24. return 1;
  25. default:
  26. /* boot device is not EMMC|SD */
  27. return -1;
  28. }
  29. }
  30. /*
  31. * The VIM3 on-board MCU can mux the PCIe/USB3.0 shared differential
  32. * lines using a FUSB340TMX USB 3.1 SuperSpeed Data Switch between
  33. * an USB3.0 Type A connector and a M.2 Key M slot.
  34. * The PHY driving these differential lines is shared between
  35. * the USB3.0 controller and the PCIe Controller, thus only
  36. * a single controller can use it.
  37. */
  38. int meson_ft_board_setup(void *blob, struct bd_info *bd)
  39. {
  40. struct udevice *bus, *dev;
  41. int node, i2c_node, ret;
  42. unsigned int i2c_addr;
  43. u32 *val;
  44. /* Find I2C device */
  45. node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "khadas,mcu");
  46. if (node < 0) {
  47. printf("vim3: cannot find khadas,mcu node\n");
  48. return 0;
  49. }
  50. /* Get addr */
  51. val = (u32 *)fdt_getprop(gd->fdt_blob, node, "reg", NULL);
  52. if (!val) {
  53. printf("vim3: cannot find khadas,mcu node i2c addr\n");
  54. return 0;
  55. }
  56. i2c_addr = fdt32_to_cpu(*val);
  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. ret = uclass_get_device_by_of_offset(UCLASS_I2C, i2c_node, &bus);
  64. if (ret < 0) {
  65. printf("vim3: cannot find i2c bus (%d)\n", ret);
  66. return 0;
  67. }
  68. ret = i2c_get_chip(bus, i2c_addr, 1, &dev);
  69. if (ret < 0) {
  70. printf("vim3: cannot find i2c chip (%d)\n", ret);
  71. return 0;
  72. }
  73. /* Read USB_PCIE_SWITCH_REG */
  74. ret = dm_i2c_reg_read(dev, KHADAS_MCU_USB_PCIE_SWITCH_REG);
  75. if (ret < 0) {
  76. printf("vim3: failed to read i2c reg (%d)\n", ret);
  77. return 0;
  78. }
  79. debug("MCU_USB_PCIE_SWITCH_REG: %d\n", ret);
  80. /*
  81. * If in PCIe mode, alter DT
  82. * 0:Enable USB3.0,Disable PCIE, 1:Disable USB3.0, Enable PCIE
  83. */
  84. if (ret > 0) {
  85. static char data[32] __aligned(4);
  86. const void *ptmp;
  87. int len;
  88. /* Find USB node */
  89. node = fdt_node_offset_by_compatible(blob, -1, "amlogic,meson-g12a-usb-ctrl");
  90. if (node < 0) {
  91. printf("vim3: cannot find amlogic,meson-g12a-usb-ctrl node\n");
  92. return 0;
  93. }
  94. /* Update PHY names (mandatory to disable USB3.0) */
  95. len = strlcpy(data, "usb2-phy0", 32);
  96. len += strlcpy(&data[len], "usb2-phy1", 32 - len);
  97. ret = fdt_setprop(blob, node, "phy-names", data, len);
  98. if (ret < 0) {
  99. printf("vim3: failed to update usb phy names property (%d)\n", ret);
  100. return 0;
  101. }
  102. /* Update PHY list, by keeping the 2 first entries (optional) */
  103. ptmp = fdt_getprop(blob, node, "phys", &len);
  104. if (ptmp) {
  105. memcpy(data, ptmp, min_t(unsigned int, 2 * sizeof(u32), len));
  106. ret = fdt_setprop(blob, node, "phys", data,
  107. min_t(unsigned int, 2 * sizeof(u32), len));
  108. if (ret < 0)
  109. printf("vim3: failed to update usb phys property (%d)\n", ret);
  110. } else
  111. printf("vim3: cannot find usb node phys property\n");
  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. /* 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. printf("vim3: successfully enabled PCIe\n");
  126. }
  127. return 0;
  128. }
  129. #define EFUSE_MAC_OFFSET 0
  130. #define EFUSE_MAC_SIZE 12
  131. #define MAC_ADDR_LEN 6
  132. int misc_init_r(void)
  133. {
  134. u8 mac_addr[MAC_ADDR_LEN];
  135. char efuse_mac_addr[EFUSE_MAC_SIZE], tmp[3];
  136. ssize_t len;
  137. if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
  138. len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
  139. efuse_mac_addr, EFUSE_MAC_SIZE);
  140. if (len != EFUSE_MAC_SIZE)
  141. return 0;
  142. /* MAC is stored in ASCII format, 1bytes = 2characters */
  143. for (int i = 0; i < 6; i++) {
  144. tmp[0] = efuse_mac_addr[i * 2];
  145. tmp[1] = efuse_mac_addr[i * 2 + 1];
  146. tmp[2] = '\0';
  147. mac_addr[i] = hextoul(tmp, NULL);
  148. }
  149. if (is_valid_ethaddr(mac_addr))
  150. eth_env_set_enetaddr("ethaddr", mac_addr);
  151. else
  152. meson_generate_serial_ethaddr();
  153. eth_env_get_enetaddr("ethaddr", mac_addr);
  154. }
  155. return 0;
  156. }