cpld.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Stout board CPLD access support
  4. *
  5. * Copyright (C) 2015 Renesas Electronics Europe GmbH
  6. * Copyright (C) 2015 Renesas Electronics Corporation
  7. * Copyright (C) 2015 Cogent Embedded, Inc.
  8. */
  9. #include <common.h>
  10. #include <asm/io.h>
  11. #include <asm/gpio.h>
  12. #include "cpld.h"
  13. #define SCLK (92 + 24)
  14. #define SSTBZ (92 + 25)
  15. #define MOSI (92 + 26)
  16. #define MISO (92 + 27)
  17. #define CPLD_ADDR_MODE 0x00 /* RW */
  18. #define CPLD_ADDR_MUX 0x01 /* RW */
  19. #define CPLD_ADDR_HDMI 0x02 /* RW */
  20. #define CPLD_ADDR_DIPSW 0x08 /* R */
  21. #define CPLD_ADDR_RESET 0x80 /* RW */
  22. #define CPLD_ADDR_VERSION 0xFF /* R */
  23. static u32 cpld_read(u8 addr)
  24. {
  25. int i;
  26. u32 data = 0;
  27. for (i = 0; i < 8; i++) {
  28. gpio_set_value(MOSI, addr & 0x80); /* MSB first */
  29. gpio_set_value(SCLK, 1);
  30. addr <<= 1;
  31. gpio_set_value(SCLK, 0);
  32. }
  33. gpio_set_value(MOSI, 0); /* READ */
  34. gpio_set_value(SSTBZ, 0);
  35. gpio_set_value(SCLK, 1);
  36. gpio_set_value(SCLK, 0);
  37. gpio_set_value(SSTBZ, 1);
  38. for (i = 0; i < 32; i++) {
  39. gpio_set_value(SCLK, 1);
  40. data <<= 1;
  41. data |= gpio_get_value(MISO); /* MSB first */
  42. gpio_set_value(SCLK, 0);
  43. }
  44. return data;
  45. }
  46. static void cpld_write(u8 addr, u32 data)
  47. {
  48. int i;
  49. for (i = 0; i < 32; i++) {
  50. gpio_set_value(MOSI, data & (1 << 31)); /* MSB first */
  51. gpio_set_value(SCLK, 1);
  52. data <<= 1;
  53. gpio_set_value(SCLK, 0);
  54. }
  55. for (i = 0; i < 8; i++) {
  56. gpio_set_value(MOSI, addr & 0x80); /* MSB first */
  57. gpio_set_value(SCLK, 1);
  58. addr <<= 1;
  59. gpio_set_value(SCLK, 0);
  60. }
  61. gpio_set_value(MOSI, 1); /* WRITE */
  62. gpio_set_value(SSTBZ, 0);
  63. gpio_set_value(SCLK, 1);
  64. gpio_set_value(SCLK, 0);
  65. gpio_set_value(SSTBZ, 1);
  66. }
  67. /* LSI pin pull-up control */
  68. #define PUPR3 0xe606010C
  69. #define PUPR3_SD3_DAT1 (1 << 27)
  70. void cpld_init(void)
  71. {
  72. u32 val;
  73. /* PULL-UP on MISO line */
  74. val = readl(PUPR3);
  75. val |= PUPR3_SD3_DAT1;
  76. writel(val, PUPR3);
  77. gpio_request(SCLK, "SCLK");
  78. gpio_request(SSTBZ, "SSTBZ");
  79. gpio_request(MOSI, "MOSI");
  80. gpio_request(MISO, "MISO");
  81. gpio_direction_output(SCLK, 0);
  82. gpio_direction_output(SSTBZ, 1);
  83. gpio_direction_output(MOSI, 0);
  84. gpio_direction_input(MISO);
  85. /* dummy read */
  86. cpld_read(CPLD_ADDR_VERSION);
  87. printf("CPLD version: 0x%08x\n",
  88. cpld_read(CPLD_ADDR_VERSION));
  89. printf("H2 Mode setting (MD0..28): 0x%08x\n",
  90. cpld_read(CPLD_ADDR_MODE));
  91. printf("Multiplexer settings: 0x%08x\n",
  92. cpld_read(CPLD_ADDR_MUX));
  93. printf("HDMI setting: 0x%08x\n",
  94. cpld_read(CPLD_ADDR_HDMI));
  95. printf("DIPSW (SW3): 0x%08x\n",
  96. cpld_read(CPLD_ADDR_DIPSW));
  97. #ifdef CONFIG_SH_SDHI
  98. /* switch MUX to SD0 */
  99. val = cpld_read(CPLD_ADDR_MUX);
  100. val &= ~MUX_MSK_SD0;
  101. val |= MUX_VAL_SD0;
  102. cpld_write(CPLD_ADDR_MUX, val);
  103. #endif
  104. }
  105. static int do_cpld(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  106. {
  107. u32 addr, val;
  108. if (argc < 3)
  109. return CMD_RET_USAGE;
  110. addr = simple_strtoul(argv[2], NULL, 16);
  111. if (!(addr == CPLD_ADDR_VERSION || addr == CPLD_ADDR_MODE ||
  112. addr == CPLD_ADDR_MUX || addr == CPLD_ADDR_HDMI ||
  113. addr == CPLD_ADDR_DIPSW || addr == CPLD_ADDR_RESET)) {
  114. printf("cpld invalid addr\n");
  115. return CMD_RET_USAGE;
  116. }
  117. if (argc == 3 && strcmp(argv[1], "read") == 0) {
  118. printf("0x%x\n", cpld_read(addr));
  119. } else if (argc == 4 && strcmp(argv[1], "write") == 0) {
  120. val = simple_strtoul(argv[3], NULL, 16);
  121. if (addr == CPLD_ADDR_MUX) {
  122. /* never mask SCIFA0 console */
  123. val &= ~MUX_MSK_SCIFA0_USB;
  124. val |= MUX_VAL_SCIFA0_USB;
  125. }
  126. cpld_write(addr, val);
  127. }
  128. return 0;
  129. }
  130. U_BOOT_CMD(
  131. cpld, 4, 1, do_cpld,
  132. "CPLD access",
  133. "read addr\n"
  134. "cpld write addr val\n"
  135. );
  136. void reset_cpu(ulong addr)
  137. {
  138. cpld_write(CPLD_ADDR_RESET, 1);
  139. }