blob: 1257076dfd1ba28f49472342b672e3befde6572e [file] [log] [blame]
Icenowy Zheng7508bef2018-07-21 20:41:12 +08001/*
Samuel Hollandf95b3682019-10-20 15:12:20 -05002 * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
Icenowy Zheng7508bef2018-07-21 20:41:12 +08003 * Copyright (c) 2018, Icenowy Zheng <icenowy@aosc.io>
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
Icenowy Zheng8d769822018-07-22 21:30:14 +08008#include <errno.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00009
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010#include <common/debug.h>
Andre Przywara4f6b8072023-02-01 22:28:37 +000011#include <common/fdt_wrappers.h>
Samuel Holland1dad2652019-10-20 21:34:38 -050012#include <drivers/allwinner/axp.h>
Samuel Hollandcb093f22020-12-13 22:34:10 -060013#include <drivers/allwinner/sunxi_rsb.h>
Andre Przywara4f6b8072023-02-01 22:28:37 +000014#include <libfdt.h>
Andre Przywara51760752021-02-14 23:56:04 +000015#include <lib/mmio.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000016
Andre Przywara51760752021-02-14 23:56:04 +000017#include <sunxi_cpucfg.h>
Andre Przywara67537762018-10-14 22:13:53 +010018#include <sunxi_def.h>
Icenowy Zheng8d769822018-07-22 21:30:14 +080019#include <sunxi_mmap.h>
Andre Przywara456208a2018-10-14 12:02:02 +010020#include <sunxi_private.h>
Icenowy Zheng8d769822018-07-22 21:30:14 +080021
Samuel Hollandcb093f22020-12-13 22:34:10 -060022#define AXP805_HW_ADDR 0x745
23#define AXP805_RT_ADDR 0x3a
Icenowy Zheng8d769822018-07-22 21:30:14 +080024
Samuel Hollandf95b3682019-10-20 15:12:20 -050025static enum pmic_type {
26 UNKNOWN,
Icenowy Zheng8d769822018-07-22 21:30:14 +080027 AXP805,
Samuel Hollandf95b3682019-10-20 15:12:20 -050028} pmic;
Icenowy Zheng8d769822018-07-22 21:30:14 +080029
Samuel Holland1dad2652019-10-20 21:34:38 -050030int axp_read(uint8_t reg)
Icenowy Zheng8d769822018-07-22 21:30:14 +080031{
Samuel Hollandcb093f22020-12-13 22:34:10 -060032 return rsb_read(AXP805_RT_ADDR, reg);
Icenowy Zheng8d769822018-07-22 21:30:14 +080033}
34
Samuel Holland1dad2652019-10-20 21:34:38 -050035int axp_write(uint8_t reg, uint8_t val)
Icenowy Zheng8d769822018-07-22 21:30:14 +080036{
Samuel Hollandcb093f22020-12-13 22:34:10 -060037 return rsb_write(AXP805_RT_ADDR, reg, val);
Icenowy Zheng8d769822018-07-22 21:30:14 +080038}
39
Samuel Hollandcb093f22020-12-13 22:34:10 -060040static int rsb_init(void)
Icenowy Zheng8d769822018-07-22 21:30:14 +080041{
42 int ret;
Icenowy Zheng8d769822018-07-22 21:30:14 +080043
Samuel Hollandcb093f22020-12-13 22:34:10 -060044 ret = rsb_init_controller();
Samuel Hollandf39fd862019-10-20 15:28:14 -050045 if (ret)
46 return ret;
Icenowy Zheng8d769822018-07-22 21:30:14 +080047
Samuel Hollandcb093f22020-12-13 22:34:10 -060048 /* Switch to the recommended 3 MHz bus clock. */
49 ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
Samuel Hollandf39fd862019-10-20 15:28:14 -050050 if (ret)
51 return ret;
Icenowy Zheng8d769822018-07-22 21:30:14 +080052
Samuel Hollandcb093f22020-12-13 22:34:10 -060053 /* Initiate an I2C transaction to switch the PMIC to RSB mode. */
54 ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
55 if (ret)
56 return ret;
57
58 /* Associate the 8-bit runtime address with the 12-bit bus address. */
59 ret = rsb_assign_runtime_address(AXP805_HW_ADDR, AXP805_RT_ADDR);
60 if (ret)
61 return ret;
62
63 return axp_check_id();
Icenowy Zheng8d769822018-07-22 21:30:14 +080064}
Icenowy Zheng7508bef2018-07-21 20:41:12 +080065
Andre Przywara4e4b1e62018-09-08 19:18:37 +010066int sunxi_pmic_setup(uint16_t socid, const void *fdt)
Icenowy Zheng7508bef2018-07-21 20:41:12 +080067{
Andre Przywara4f6b8072023-02-01 22:28:37 +000068 int node, ret;
69
70 node = fdt_node_offset_by_compatible(fdt, 0, "allwinner,sun8i-a23-rsb");
71 if ((node < 0) || !fdt_node_is_enabled(fdt, node)) {
72 return -ENODEV;
73 }
Icenowy Zheng8d769822018-07-22 21:30:14 +080074
Samuel Hollandcb093f22020-12-13 22:34:10 -060075 INFO("PMIC: Probing AXP805 on RSB\n");
Samuel Hollandf39fd862019-10-20 15:28:14 -050076
Samuel Hollandcb093f22020-12-13 22:34:10 -060077 ret = sunxi_init_platform_r_twi(socid, true);
Samuel Hollandf39fd862019-10-20 15:28:14 -050078 if (ret)
79 return ret;
80
Samuel Hollandcb093f22020-12-13 22:34:10 -060081 ret = rsb_init();
82 if (ret)
83 return ret;
Icenowy Zheng8d769822018-07-22 21:30:14 +080084
Samuel Hollandcb093f22020-12-13 22:34:10 -060085 /* Switch the AXP805 to master/single-PMIC mode. */
86 ret = axp_write(0xff, 0x0);
Icenowy Zheng8d769822018-07-22 21:30:14 +080087 if (ret)
Samuel Hollandf95b3682019-10-20 15:12:20 -050088 return ret;
89
90 pmic = AXP805;
Samuel Holland1dad2652019-10-20 21:34:38 -050091 axp_setup_regulators(fdt);
Icenowy Zheng7508bef2018-07-21 20:41:12 +080092
Samuel Hollandcb093f22020-12-13 22:34:10 -060093 /* Switch the PMIC back to I2C mode. */
94 ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
95 if (ret)
96 return ret;
97
Icenowy Zheng7508bef2018-07-21 20:41:12 +080098 return 0;
99}
Icenowy Zhengbd57eb52018-07-22 21:52:50 +0800100
Samuel Hollandfa4d9352019-10-20 15:06:57 -0500101void sunxi_power_down(void)
Icenowy Zhengbd57eb52018-07-22 21:52:50 +0800102{
Icenowy Zhengbd57eb52018-07-22 21:52:50 +0800103 switch (pmic) {
104 case AXP805:
Samuel Hollandcb093f22020-12-13 22:34:10 -0600105 /* (Re-)init RSB in case the rich OS has disabled it. */
106 sunxi_init_platform_r_twi(SUNXI_SOC_H6, true);
107 rsb_init();
Samuel Holland1dad2652019-10-20 21:34:38 -0500108 axp_power_off();
Icenowy Zhengbd57eb52018-07-22 21:52:50 +0800109 break;
110 default:
111 break;
112 }
Icenowy Zhengbd57eb52018-07-22 21:52:50 +0800113}
Andre Przywara51760752021-02-14 23:56:04 +0000114
115void sunxi_cpu_power_off_self(void)
116{
117 u_register_t mpidr = read_mpidr();
118 unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
119
120 /* Enable the CPUIDLE hardware (only really needs to be done once). */
121 mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0x16aa0000);
122 mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0xaa160001);
123
124 /* Trigger power off for this core. */
125 mmio_write_32(SUNXI_CORE_CLOSE_REG, BIT_32(core));
126}