cpld.c 3.7 KB

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