vim3.c 3.5 KB

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