jh7110.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2022 StarFive
  5. *
  6. * Authors:
  7. * Wei Liang Lim <weiliang.lim@starfivetech.com>
  8. * Minda Chen <minda.chen@starfivetech.com>
  9. */
  10. #include <libfdt.h>
  11. #include <platform_override.h>
  12. #include <sbi/sbi_error.h>
  13. #include <sbi/sbi_bitops.h>
  14. #include <sbi/sbi_system.h>
  15. #include <sbi/sbi_console.h>
  16. #include <sbi/sbi_timer.h>
  17. #include <sbi/riscv_io.h>
  18. #include <sbi_utils/fdt/fdt_helper.h>
  19. #include <sbi_utils/reset/fdt_reset.h>
  20. #include <sbi_utils/i2c/fdt_i2c.h>
  21. struct pmic {
  22. struct i2c_adapter *adapter;
  23. u32 dev_addr;
  24. const char *compatible;
  25. };
  26. struct jh7110 {
  27. u64 pmu_reg_base;
  28. u64 clk_reg_base;
  29. u32 i2c_index;
  30. };
  31. static struct pmic pmic_inst;
  32. static struct jh7110 jh7110_inst;
  33. static u32 selected_hartid = -1;
  34. /* PMU register define */
  35. #define HW_EVENT_TURN_ON_MASK 0x04
  36. #define HW_EVENT_TURN_OFF_MASK 0x08
  37. #define SW_TURN_ON_POWER_MODE 0x0C
  38. #define SW_TURN_OFF_POWER_MODE 0x10
  39. #define SW_ENCOURAGE 0x44
  40. #define PMU_INT_MASK 0x48
  41. #define PCH_BYPASS 0x4C
  42. #define PCH_PSTATE 0x50
  43. #define PCH_TIMEOUT 0x54
  44. #define LP_TIMEOUT 0x58
  45. #define HW_TURN_ON_MODE 0x5C
  46. #define CURR_POWER_MODE 0x80
  47. #define PMU_EVENT_STATUS 0x88
  48. #define PMU_INT_STATUS 0x8C
  49. /* sw encourage cfg */
  50. #define SW_MODE_ENCOURAGE_EN_LO 0x05
  51. #define SW_MODE_ENCOURAGE_EN_HI 0x50
  52. #define SW_MODE_ENCOURAGE_DIS_LO 0x0A
  53. #define SW_MODE_ENCOURAGE_DIS_HI 0xA0
  54. #define SW_MODE_ENCOURAGE_ON 0xFF
  55. #define DEVICE_PD_MASK 0xfc
  56. #define SYSTOP_CPU_PD_MASK 0x3
  57. #define TIMEOUT_COUNT 100000
  58. #define AXP15060_POWER_REG 0x32
  59. #define AXP15060_POWER_OFF_BIT BIT(7)
  60. #define AXP15060_RESET_BIT BIT(6)
  61. #define I2C_APB_CLK_OFFSET 0x228
  62. #define I2C_APB_CLK_ENABLE_BIT BIT(31)
  63. static int pm_system_reset_check(u32 type, u32 reason)
  64. {
  65. switch (type) {
  66. case SBI_SRST_RESET_TYPE_SHUTDOWN:
  67. return 1;
  68. case SBI_SRST_RESET_TYPE_COLD_REBOOT:
  69. return 255;
  70. default:
  71. break;
  72. }
  73. return 0;
  74. }
  75. static int wait_pmu_pd_state(u32 mask)
  76. {
  77. int count = 0;
  78. unsigned long addr = jh7110_inst.pmu_reg_base;
  79. u32 val;
  80. do {
  81. val = readl((void *)(addr + CURR_POWER_MODE));
  82. if (val == mask)
  83. return 0;
  84. sbi_timer_udelay(2);
  85. count += 1;
  86. if (count == TIMEOUT_COUNT)
  87. return SBI_ETIMEDOUT;
  88. } while (1);
  89. }
  90. static int shutdown_device_power_domain(void)
  91. {
  92. unsigned long addr = jh7110_inst.pmu_reg_base;
  93. u32 curr_mode;
  94. int ret = 0;
  95. curr_mode = readl((void *)(addr + CURR_POWER_MODE));
  96. curr_mode &= DEVICE_PD_MASK;
  97. if (curr_mode) {
  98. writel(curr_mode, (void *)(addr + SW_TURN_OFF_POWER_MODE));
  99. writel(SW_MODE_ENCOURAGE_ON, (void *)(addr + SW_ENCOURAGE));
  100. writel(SW_MODE_ENCOURAGE_DIS_LO, (void *)(addr + SW_ENCOURAGE));
  101. writel(SW_MODE_ENCOURAGE_DIS_HI, (void *)(addr + SW_ENCOURAGE));
  102. ret = wait_pmu_pd_state(SYSTOP_CPU_PD_MASK);
  103. if (ret)
  104. sbi_printf("%s shutdown device power %x error\n",
  105. __func__, curr_mode);
  106. }
  107. return ret;
  108. }
  109. static void pmic_ops(struct pmic *pmic, int type)
  110. {
  111. int ret = 0;
  112. u8 val;
  113. ret = shutdown_device_power_domain();
  114. if (ret)
  115. return;
  116. if (!sbi_strcmp("stf,axp15060-regulator", pmic->compatible)) {
  117. ret = i2c_adapter_reg_read(pmic->adapter, pmic->dev_addr,
  118. AXP15060_POWER_REG, &val);
  119. if (ret) {
  120. sbi_printf("%s: cannot read pmic power register\n",
  121. __func__);
  122. return;
  123. }
  124. val |= AXP15060_POWER_OFF_BIT;
  125. if (type == SBI_SRST_RESET_TYPE_SHUTDOWN)
  126. val |= AXP15060_POWER_OFF_BIT;
  127. else
  128. val |= AXP15060_RESET_BIT;
  129. ret = i2c_adapter_reg_write(pmic->adapter, pmic->dev_addr,
  130. AXP15060_POWER_REG, val);
  131. if (ret)
  132. sbi_printf("%s: cannot write pmic power register\n",
  133. __func__);
  134. }
  135. }
  136. static void pmic_i2c_clk_enable(void)
  137. {
  138. unsigned long clock_base;
  139. unsigned int val;
  140. clock_base = jh7110_inst.clk_reg_base +
  141. I2C_APB_CLK_OFFSET +
  142. (jh7110_inst.i2c_index << 2);
  143. val = readl((void *)clock_base);
  144. if (!val)
  145. writel(I2C_APB_CLK_ENABLE_BIT, (void *)clock_base);
  146. }
  147. static void pm_system_reset(u32 type, u32 reason)
  148. {
  149. if (pmic_inst.adapter) {
  150. switch (type) {
  151. case SBI_SRST_RESET_TYPE_SHUTDOWN:
  152. case SBI_SRST_RESET_TYPE_COLD_REBOOT:
  153. /* i2c clk may be disabled by kernel driver */
  154. pmic_i2c_clk_enable();
  155. pmic_ops(&pmic_inst, type);
  156. break;
  157. default:
  158. break;
  159. }
  160. }
  161. sbi_hart_hang();
  162. }
  163. static struct sbi_system_reset_device pm_reset = {
  164. .name = "pm-reset",
  165. .system_reset_check = pm_system_reset_check,
  166. .system_reset = pm_system_reset
  167. };
  168. static int pm_reset_init(void *fdt, int nodeoff,
  169. const struct fdt_match *match)
  170. {
  171. int rc;
  172. int i2c_bus;
  173. struct i2c_adapter *adapter;
  174. u64 addr;
  175. rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL);
  176. if (rc)
  177. return rc;
  178. pmic_inst.dev_addr = addr;
  179. pmic_inst.compatible = match->compatible;
  180. i2c_bus = fdt_parent_offset(fdt, nodeoff);
  181. if (i2c_bus < 0)
  182. return i2c_bus;
  183. /* i2c adapter get */
  184. rc = fdt_i2c_adapter_get(fdt, i2c_bus, &adapter);
  185. if (rc)
  186. return rc;
  187. pmic_inst.adapter = adapter;
  188. sbi_system_reset_add_device(&pm_reset);
  189. return 0;
  190. }
  191. static const struct fdt_match pm_reset_match[] = {
  192. { .compatible = "stf,axp15060-regulator", .data = (void *)true },
  193. { },
  194. };
  195. static struct fdt_reset fdt_reset_pmic = {
  196. .match_table = pm_reset_match,
  197. .init = pm_reset_init,
  198. };
  199. static int starfive_jh7110_inst_init(void *fdt)
  200. {
  201. int noff, rc = 0;
  202. const char *name;
  203. u64 addr;
  204. noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-pmu");
  205. if (-1 < noff) {
  206. rc = fdt_get_node_addr_size(fdt, noff, 0, &addr, NULL);
  207. if (rc)
  208. goto err;
  209. jh7110_inst.pmu_reg_base = addr;
  210. }
  211. noff = fdt_node_offset_by_compatible(fdt, -1, "starfive,jh7110-clkgen");
  212. if (-1 < noff) {
  213. rc = fdt_get_node_addr_size(fdt, noff, 0, &addr, NULL);
  214. if (rc)
  215. goto err;
  216. jh7110_inst.clk_reg_base = addr;
  217. }
  218. if (pmic_inst.adapter) {
  219. name = fdt_get_name(fdt, pmic_inst.adapter->id, NULL);
  220. if (!sbi_strncmp(name, "i2c", 3))
  221. jh7110_inst.i2c_index = name[3] - '0';
  222. else
  223. rc = SBI_EINVAL;
  224. }
  225. err:
  226. return rc;
  227. }
  228. static int starfive_jh7110_final_init(bool cold_boot,
  229. const struct fdt_match *match)
  230. {
  231. void *fdt = fdt_get_address();
  232. if (cold_boot) {
  233. fdt_reset_driver_init(fdt, &fdt_reset_pmic);
  234. return starfive_jh7110_inst_init(fdt);
  235. }
  236. return 0;
  237. }
  238. static bool starfive_jh7110_cold_boot_allowed(u32 hartid,
  239. const struct fdt_match *match)
  240. {
  241. if (selected_hartid != -1)
  242. return (selected_hartid == hartid);
  243. return true;
  244. }
  245. static void starfive_jh7110_fw_init(void *fdt, const struct fdt_match *match)
  246. {
  247. const fdt32_t *val;
  248. int len, coff;
  249. coff = fdt_path_offset(fdt, "/chosen");
  250. if (-1 < coff) {
  251. val = fdt_getprop(fdt, coff, "starfive,boot-hart-id", &len);
  252. if (val && len >= sizeof(fdt32_t))
  253. selected_hartid = (u32) fdt32_to_cpu(*val);
  254. }
  255. }
  256. static const struct fdt_match starfive_jh7110_match[] = {
  257. { .compatible = "starfive,jh7110" },
  258. { },
  259. };
  260. const struct platform_override starfive_jh7110 = {
  261. .match_table = starfive_jh7110_match,
  262. .cold_boot_allowed = starfive_jh7110_cold_boot_allowed,
  263. .fw_init = starfive_jh7110_fw_init,
  264. .final_init = starfive_jh7110_final_init,
  265. };