blob: d298e6b8adafedf0c6ef52519da18f1f4f856155 [file] [log] [blame]
Icenowy Zheng7c26b6e2018-07-21 20:41:12 +08001/*
Samuel Hollandc0e109f2019-10-20 15:12:20 -05002 * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
Icenowy Zheng7c26b6e2018-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 Zheng6d372822018-07-22 21:30:14 +08008#include <errno.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +00009
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +000010#include <common/debug.h>
Samuel Hollandfb23b102019-10-20 21:34:38 -050011#include <drivers/allwinner/axp.h>
Samuel Holland7060e0d2020-12-13 22:34:10 -060012#include <drivers/allwinner/sunxi_rsb.h>
Andre Przywara92277192021-02-14 23:56:04 +000013#include <lib/mmio.h>
Antonio Nino Diaz09d40e02018-12-14 00:18:21 +000014
Andre Przywara92277192021-02-14 23:56:04 +000015#include <sunxi_cpucfg.h>
Andre Przywarad5ddf672018-10-14 22:13:53 +010016#include <sunxi_def.h>
Icenowy Zheng6d372822018-07-22 21:30:14 +080017#include <sunxi_mmap.h>
Andre Przywara4ec1a232018-10-14 12:02:02 +010018#include <sunxi_private.h>
Icenowy Zheng6d372822018-07-22 21:30:14 +080019
Samuel Holland7060e0d2020-12-13 22:34:10 -060020#define AXP805_HW_ADDR 0x745
21#define AXP805_RT_ADDR 0x3a
Icenowy Zheng6d372822018-07-22 21:30:14 +080022
Samuel Hollandc0e109f2019-10-20 15:12:20 -050023static enum pmic_type {
24 UNKNOWN,
Icenowy Zheng6d372822018-07-22 21:30:14 +080025 AXP805,
Samuel Hollandc0e109f2019-10-20 15:12:20 -050026} pmic;
Icenowy Zheng6d372822018-07-22 21:30:14 +080027
Samuel Hollandfb23b102019-10-20 21:34:38 -050028int axp_read(uint8_t reg)
Icenowy Zheng6d372822018-07-22 21:30:14 +080029{
Samuel Holland7060e0d2020-12-13 22:34:10 -060030 return rsb_read(AXP805_RT_ADDR, reg);
Icenowy Zheng6d372822018-07-22 21:30:14 +080031}
32
Samuel Hollandfb23b102019-10-20 21:34:38 -050033int axp_write(uint8_t reg, uint8_t val)
Icenowy Zheng6d372822018-07-22 21:30:14 +080034{
Samuel Holland7060e0d2020-12-13 22:34:10 -060035 return rsb_write(AXP805_RT_ADDR, reg, val);
Icenowy Zheng6d372822018-07-22 21:30:14 +080036}
37
Samuel Holland7060e0d2020-12-13 22:34:10 -060038static int rsb_init(void)
Icenowy Zheng6d372822018-07-22 21:30:14 +080039{
40 int ret;
Icenowy Zheng6d372822018-07-22 21:30:14 +080041
Samuel Holland7060e0d2020-12-13 22:34:10 -060042 ret = rsb_init_controller();
Samuel Holland4538c492019-10-20 15:28:14 -050043 if (ret)
44 return ret;
Icenowy Zheng6d372822018-07-22 21:30:14 +080045
Samuel Holland7060e0d2020-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 Holland4538c492019-10-20 15:28:14 -050048 if (ret)
49 return ret;
Icenowy Zheng6d372822018-07-22 21:30:14 +080050
Samuel Holland7060e0d2020-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 Zheng6d372822018-07-22 21:30:14 +080062}
Icenowy Zheng7c26b6e2018-07-21 20:41:12 +080063
Andre Przywaradf301602018-09-08 19:18:37 +010064int sunxi_pmic_setup(uint16_t socid, const void *fdt)
Icenowy Zheng7c26b6e2018-07-21 20:41:12 +080065{
Icenowy Zheng6d372822018-07-22 21:30:14 +080066 int ret;
67
Samuel Holland7060e0d2020-12-13 22:34:10 -060068 INFO("PMIC: Probing AXP805 on RSB\n");
Samuel Holland4538c492019-10-20 15:28:14 -050069
Samuel Holland7060e0d2020-12-13 22:34:10 -060070 ret = sunxi_init_platform_r_twi(socid, true);
Samuel Holland4538c492019-10-20 15:28:14 -050071 if (ret)
72 return ret;
73
Samuel Holland7060e0d2020-12-13 22:34:10 -060074 ret = rsb_init();
75 if (ret)
76 return ret;
Icenowy Zheng6d372822018-07-22 21:30:14 +080077
Samuel Holland7060e0d2020-12-13 22:34:10 -060078 /* Switch the AXP805 to master/single-PMIC mode. */
79 ret = axp_write(0xff, 0x0);
Icenowy Zheng6d372822018-07-22 21:30:14 +080080 if (ret)
Samuel Hollandc0e109f2019-10-20 15:12:20 -050081 return ret;
82
83 pmic = AXP805;
Samuel Hollandfb23b102019-10-20 21:34:38 -050084 axp_setup_regulators(fdt);
Icenowy Zheng7c26b6e2018-07-21 20:41:12 +080085
Samuel Holland7060e0d2020-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 Zheng7c26b6e2018-07-21 20:41:12 +080091 return 0;
92}
Icenowy Zheng5069c1c2018-07-22 21:52:50 +080093
Samuel Holland818e6732019-10-20 15:06:57 -050094void sunxi_power_down(void)
Icenowy Zheng5069c1c2018-07-22 21:52:50 +080095{
Icenowy Zheng5069c1c2018-07-22 21:52:50 +080096 switch (pmic) {
97 case AXP805:
Samuel Holland7060e0d2020-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 Hollandfb23b102019-10-20 21:34:38 -0500101 axp_power_off();
Icenowy Zheng5069c1c2018-07-22 21:52:50 +0800102 break;
103 default:
104 break;
105 }
Icenowy Zheng5069c1c2018-07-22 21:52:50 +0800106}
Andre Przywara92277192021-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}