blob: d298e6b8adafedf0c6ef52519da18f1f4f856155 [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>
Samuel Holland1dad2652019-10-20 21:34:38 -050011#include <drivers/allwinner/axp.h>
Samuel Hollandcb093f22020-12-13 22:34:10 -060012#include <drivers/allwinner/sunxi_rsb.h>
Andre Przywara51760752021-02-14 23:56:04 +000013#include <lib/mmio.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000014
Andre Przywara51760752021-02-14 23:56:04 +000015#include <sunxi_cpucfg.h>
Andre Przywara67537762018-10-14 22:13:53 +010016#include <sunxi_def.h>
Icenowy Zheng8d769822018-07-22 21:30:14 +080017#include <sunxi_mmap.h>
Andre Przywara456208a2018-10-14 12:02:02 +010018#include <sunxi_private.h>
Icenowy Zheng8d769822018-07-22 21:30:14 +080019
Samuel Hollandcb093f22020-12-13 22:34:10 -060020#define AXP805_HW_ADDR 0x745
21#define AXP805_RT_ADDR 0x3a
Icenowy Zheng8d769822018-07-22 21:30:14 +080022
Samuel Hollandf95b3682019-10-20 15:12:20 -050023static enum pmic_type {
24 UNKNOWN,
Icenowy Zheng8d769822018-07-22 21:30:14 +080025 AXP805,
Samuel Hollandf95b3682019-10-20 15:12:20 -050026} pmic;
Icenowy Zheng8d769822018-07-22 21:30:14 +080027
Samuel Holland1dad2652019-10-20 21:34:38 -050028int axp_read(uint8_t reg)
Icenowy Zheng8d769822018-07-22 21:30:14 +080029{
Samuel Hollandcb093f22020-12-13 22:34:10 -060030 return rsb_read(AXP805_RT_ADDR, reg);
Icenowy Zheng8d769822018-07-22 21:30:14 +080031}
32
Samuel Holland1dad2652019-10-20 21:34:38 -050033int axp_write(uint8_t reg, uint8_t val)
Icenowy Zheng8d769822018-07-22 21:30:14 +080034{
Samuel Hollandcb093f22020-12-13 22:34:10 -060035 return rsb_write(AXP805_RT_ADDR, reg, val);
Icenowy Zheng8d769822018-07-22 21:30:14 +080036}
37
Samuel Hollandcb093f22020-12-13 22:34:10 -060038static int rsb_init(void)
Icenowy Zheng8d769822018-07-22 21:30:14 +080039{
40 int ret;
Icenowy Zheng8d769822018-07-22 21:30:14 +080041
Samuel Hollandcb093f22020-12-13 22:34:10 -060042 ret = rsb_init_controller();
Samuel Hollandf39fd862019-10-20 15:28:14 -050043 if (ret)
44 return ret;
Icenowy Zheng8d769822018-07-22 21:30:14 +080045
Samuel Hollandcb093f22020-12-13 22:34:10 -060046 /* Switch to the recommended 3 MHz bus clock. */
47 ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
Samuel Hollandf39fd862019-10-20 15:28:14 -050048 if (ret)
49 return ret;
Icenowy Zheng8d769822018-07-22 21:30:14 +080050
Samuel Hollandcb093f22020-12-13 22:34:10 -060051 /* Initiate an I2C transaction to switch the PMIC to RSB mode. */
52 ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
53 if (ret)
54 return ret;
55
56 /* Associate the 8-bit runtime address with the 12-bit bus address. */
57 ret = rsb_assign_runtime_address(AXP805_HW_ADDR, AXP805_RT_ADDR);
58 if (ret)
59 return ret;
60
61 return axp_check_id();
Icenowy Zheng8d769822018-07-22 21:30:14 +080062}
Icenowy Zheng7508bef2018-07-21 20:41:12 +080063
Andre Przywara4e4b1e62018-09-08 19:18:37 +010064int sunxi_pmic_setup(uint16_t socid, const void *fdt)
Icenowy Zheng7508bef2018-07-21 20:41:12 +080065{
Icenowy Zheng8d769822018-07-22 21:30:14 +080066 int ret;
67
Samuel Hollandcb093f22020-12-13 22:34:10 -060068 INFO("PMIC: Probing AXP805 on RSB\n");
Samuel Hollandf39fd862019-10-20 15:28:14 -050069
Samuel Hollandcb093f22020-12-13 22:34:10 -060070 ret = sunxi_init_platform_r_twi(socid, true);
Samuel Hollandf39fd862019-10-20 15:28:14 -050071 if (ret)
72 return ret;
73
Samuel Hollandcb093f22020-12-13 22:34:10 -060074 ret = rsb_init();
75 if (ret)
76 return ret;
Icenowy Zheng8d769822018-07-22 21:30:14 +080077
Samuel Hollandcb093f22020-12-13 22:34:10 -060078 /* Switch the AXP805 to master/single-PMIC mode. */
79 ret = axp_write(0xff, 0x0);
Icenowy Zheng8d769822018-07-22 21:30:14 +080080 if (ret)
Samuel Hollandf95b3682019-10-20 15:12:20 -050081 return ret;
82
83 pmic = AXP805;
Samuel Holland1dad2652019-10-20 21:34:38 -050084 axp_setup_regulators(fdt);
Icenowy Zheng7508bef2018-07-21 20:41:12 +080085
Samuel Hollandcb093f22020-12-13 22:34:10 -060086 /* Switch the PMIC back to I2C mode. */
87 ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
88 if (ret)
89 return ret;
90
Icenowy Zheng7508bef2018-07-21 20:41:12 +080091 return 0;
92}
Icenowy Zhengbd57eb52018-07-22 21:52:50 +080093
Samuel Hollandfa4d9352019-10-20 15:06:57 -050094void sunxi_power_down(void)
Icenowy Zhengbd57eb52018-07-22 21:52:50 +080095{
Icenowy Zhengbd57eb52018-07-22 21:52:50 +080096 switch (pmic) {
97 case AXP805:
Samuel Hollandcb093f22020-12-13 22:34:10 -060098 /* (Re-)init RSB in case the rich OS has disabled it. */
99 sunxi_init_platform_r_twi(SUNXI_SOC_H6, true);
100 rsb_init();
Samuel Holland1dad2652019-10-20 21:34:38 -0500101 axp_power_off();
Icenowy Zhengbd57eb52018-07-22 21:52:50 +0800102 break;
103 default:
104 break;
105 }
Icenowy Zhengbd57eb52018-07-22 21:52:50 +0800106}
Andre Przywara51760752021-02-14 23:56:04 +0000107
108void sunxi_cpu_power_off_self(void)
109{
110 u_register_t mpidr = read_mpidr();
111 unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
112
113 /* Enable the CPUIDLE hardware (only really needs to be done once). */
114 mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0x16aa0000);
115 mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0xaa160001);
116
117 /* Trigger power off for this core. */
118 mmio_write_32(SUNXI_CORE_CLOSE_REG, BIT_32(core));
119}