sunxi_rsb.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <errno.h>
  7. #include <common/debug.h>
  8. #include <drivers/delay_timer.h>
  9. #include <lib/mmio.h>
  10. #include <sunxi_mmap.h>
  11. #define RSB_CTRL 0x00
  12. #define RSB_CCR 0x04
  13. #define RSB_INTE 0x08
  14. #define RSB_STAT 0x0c
  15. #define RSB_DADDR0 0x10
  16. #define RSB_DLEN 0x18
  17. #define RSB_DATA0 0x1c
  18. #define RSB_LCR 0x24
  19. #define RSB_PMCR 0x28
  20. #define RSB_CMD 0x2c
  21. #define RSB_SADDR 0x30
  22. #define RSBCMD_SRTA 0xE8
  23. #define RSBCMD_RD8 0x8B
  24. #define RSBCMD_RD16 0x9C
  25. #define RSBCMD_RD32 0xA6
  26. #define RSBCMD_WR8 0x4E
  27. #define RSBCMD_WR16 0x59
  28. #define RSBCMD_WR32 0x63
  29. #define MAX_TRIES 100000
  30. static int rsb_wait_bit(const char *desc, unsigned int offset, uint32_t mask)
  31. {
  32. uint32_t reg, tries = MAX_TRIES;
  33. do
  34. reg = mmio_read_32(SUNXI_R_RSB_BASE + offset);
  35. while ((reg & mask) && --tries); /* transaction in progress */
  36. if (reg & mask) {
  37. ERROR("%s: timed out\n", desc);
  38. return -ETIMEDOUT;
  39. }
  40. return 0;
  41. }
  42. static int rsb_wait_stat(const char *desc)
  43. {
  44. uint32_t reg;
  45. int ret = rsb_wait_bit(desc, RSB_CTRL, BIT(7));
  46. if (ret)
  47. return ret;
  48. reg = mmio_read_32(SUNXI_R_RSB_BASE + RSB_STAT);
  49. if (reg == 0x01)
  50. return 0;
  51. ERROR("%s: 0x%x\n", desc, reg);
  52. return -reg;
  53. }
  54. /* Initialize the RSB controller. */
  55. int rsb_init_controller(void)
  56. {
  57. mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x01); /* soft reset */
  58. return rsb_wait_bit("RSB: reset controller", RSB_CTRL, BIT(0));
  59. }
  60. int rsb_read(uint8_t rt_addr, uint8_t reg_addr)
  61. {
  62. int ret;
  63. mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_RD8); /* read a byte */
  64. mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16);
  65. mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr);
  66. mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */
  67. ret = rsb_wait_stat("RSB: read command");
  68. if (ret)
  69. return ret;
  70. return mmio_read_32(SUNXI_R_RSB_BASE + RSB_DATA0) & 0xff; /* result */
  71. }
  72. int rsb_write(uint8_t rt_addr, uint8_t reg_addr, uint8_t value)
  73. {
  74. mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_WR8); /* byte write */
  75. mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16);
  76. mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr);
  77. mmio_write_32(SUNXI_R_RSB_BASE + RSB_DATA0, value);
  78. mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */
  79. return rsb_wait_stat("RSB: write command");
  80. }
  81. int rsb_set_device_mode(uint32_t device_mode)
  82. {
  83. mmio_write_32(SUNXI_R_RSB_BASE + RSB_PMCR,
  84. (device_mode & 0x00ffffff) | BIT(31));
  85. return rsb_wait_bit("RSB: set device to RSB", RSB_PMCR, BIT(31));
  86. }
  87. int rsb_set_bus_speed(uint32_t source_freq, uint32_t bus_freq)
  88. {
  89. uint32_t reg;
  90. if (bus_freq == 0)
  91. return -EINVAL;
  92. reg = source_freq / bus_freq;
  93. if (reg < 2)
  94. return -EINVAL;
  95. reg = reg / 2 - 1;
  96. reg |= (1U << 8); /* one cycle of CD output delay */
  97. mmio_write_32(SUNXI_R_RSB_BASE + RSB_CCR, reg);
  98. return 0;
  99. }
  100. /* Initialize the RSB PMIC connection. */
  101. int rsb_assign_runtime_address(uint16_t hw_addr, uint8_t rt_addr)
  102. {
  103. mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, hw_addr | (rt_addr << 16));
  104. mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_SRTA);
  105. mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);
  106. return rsb_wait_stat("RSB: set run-time address");
  107. }