xref: /rk3399_ARM-atf/plat/allwinner/sun50i_h6/sunxi_power.c (revision 7060e0d891b9f9cccf46867de142e1808c61fd6d)
17c26b6ecSIcenowy Zheng /*
2c0e109f2SSamuel Holland  * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
37c26b6ecSIcenowy Zheng  * Copyright (c) 2018, Icenowy Zheng <icenowy@aosc.io>
47c26b6ecSIcenowy Zheng  *
57c26b6ecSIcenowy Zheng  * SPDX-License-Identifier: BSD-3-Clause
67c26b6ecSIcenowy Zheng  */
77c26b6ecSIcenowy Zheng 
86d372828SIcenowy Zheng #include <errno.h>
909d40e0eSAntonio Nino Diaz 
1009d40e0eSAntonio Nino Diaz #include <common/debug.h>
11fb23b104SSamuel Holland #include <drivers/allwinner/axp.h>
12*7060e0d8SSamuel Holland #include <drivers/allwinner/sunxi_rsb.h>
1309d40e0eSAntonio Nino Diaz 
14d5ddf67aSAndre Przywara #include <sunxi_def.h>
156d372828SIcenowy Zheng #include <sunxi_mmap.h>
164ec1a239SAndre Przywara #include <sunxi_private.h>
176d372828SIcenowy Zheng 
18*7060e0d8SSamuel Holland #define AXP805_HW_ADDR	0x745
19*7060e0d8SSamuel Holland #define AXP805_RT_ADDR	0x3a
206d372828SIcenowy Zheng 
21c0e109f2SSamuel Holland static enum pmic_type {
22c0e109f2SSamuel Holland 	UNKNOWN,
236d372828SIcenowy Zheng 	AXP805,
24c0e109f2SSamuel Holland } pmic;
256d372828SIcenowy Zheng 
26fb23b104SSamuel Holland int axp_read(uint8_t reg)
276d372828SIcenowy Zheng {
28*7060e0d8SSamuel Holland 	return rsb_read(AXP805_RT_ADDR, reg);
29fb23b104SSamuel Holland }
30fb23b104SSamuel Holland 
31fb23b104SSamuel Holland int axp_write(uint8_t reg, uint8_t val)
326d372828SIcenowy Zheng {
33*7060e0d8SSamuel Holland 	return rsb_write(AXP805_RT_ADDR, reg, val);
346d372828SIcenowy Zheng }
356d372828SIcenowy Zheng 
36*7060e0d8SSamuel Holland static int rsb_init(void)
376d372828SIcenowy Zheng {
386d372828SIcenowy Zheng 	int ret;
396d372828SIcenowy Zheng 
40*7060e0d8SSamuel Holland 	ret = rsb_init_controller();
414538c498SSamuel Holland 	if (ret)
424538c498SSamuel Holland 		return ret;
436d372828SIcenowy Zheng 
44*7060e0d8SSamuel Holland 	/* Switch to the recommended 3 MHz bus clock. */
45*7060e0d8SSamuel Holland 	ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
464538c498SSamuel Holland 	if (ret)
474538c498SSamuel Holland 		return ret;
486d372828SIcenowy Zheng 
49*7060e0d8SSamuel Holland 	/* Initiate an I2C transaction to switch the PMIC to RSB mode. */
50*7060e0d8SSamuel Holland 	ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
51*7060e0d8SSamuel Holland 	if (ret)
52*7060e0d8SSamuel Holland 		return ret;
53*7060e0d8SSamuel Holland 
54*7060e0d8SSamuel Holland 	/* Associate the 8-bit runtime address with the 12-bit bus address. */
55*7060e0d8SSamuel Holland 	ret = rsb_assign_runtime_address(AXP805_HW_ADDR, AXP805_RT_ADDR);
56*7060e0d8SSamuel Holland 	if (ret)
57*7060e0d8SSamuel Holland 		return ret;
58*7060e0d8SSamuel Holland 
59*7060e0d8SSamuel Holland 	return axp_check_id();
606d372828SIcenowy Zheng }
617c26b6ecSIcenowy Zheng 
62df301601SAndre Przywara int sunxi_pmic_setup(uint16_t socid, const void *fdt)
637c26b6ecSIcenowy Zheng {
646d372828SIcenowy Zheng 	int ret;
656d372828SIcenowy Zheng 
66*7060e0d8SSamuel Holland 	INFO("PMIC: Probing AXP805 on RSB\n");
674538c498SSamuel Holland 
68*7060e0d8SSamuel Holland 	ret = sunxi_init_platform_r_twi(socid, true);
694538c498SSamuel Holland 	if (ret)
704538c498SSamuel Holland 		return ret;
714538c498SSamuel Holland 
72*7060e0d8SSamuel Holland 	ret = rsb_init();
73*7060e0d8SSamuel Holland 	if (ret)
74*7060e0d8SSamuel Holland 		return ret;
756d372828SIcenowy Zheng 
76*7060e0d8SSamuel Holland 	/* Switch the AXP805 to master/single-PMIC mode. */
77*7060e0d8SSamuel Holland 	ret = axp_write(0xff, 0x0);
786d372828SIcenowy Zheng 	if (ret)
79c0e109f2SSamuel Holland 		return ret;
80c0e109f2SSamuel Holland 
816d372828SIcenowy Zheng 	pmic = AXP805;
82fb23b104SSamuel Holland 	axp_setup_regulators(fdt);
837c26b6ecSIcenowy Zheng 
84*7060e0d8SSamuel Holland 	/* Switch the PMIC back to I2C mode. */
85*7060e0d8SSamuel Holland 	ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
86*7060e0d8SSamuel Holland 	if (ret)
87*7060e0d8SSamuel Holland 		return ret;
88*7060e0d8SSamuel Holland 
897c26b6ecSIcenowy Zheng 	return 0;
907c26b6ecSIcenowy Zheng }
915069c1cfSIcenowy Zheng 
92818e6732SSamuel Holland void sunxi_power_down(void)
935069c1cfSIcenowy Zheng {
945069c1cfSIcenowy Zheng 	switch (pmic) {
955069c1cfSIcenowy Zheng 	case AXP805:
96*7060e0d8SSamuel Holland 		/* (Re-)init RSB in case the rich OS has disabled it. */
97*7060e0d8SSamuel Holland 		sunxi_init_platform_r_twi(SUNXI_SOC_H6, true);
98*7060e0d8SSamuel Holland 		rsb_init();
99fb23b104SSamuel Holland 		axp_power_off();
1005069c1cfSIcenowy Zheng 		break;
1015069c1cfSIcenowy Zheng 	default:
1025069c1cfSIcenowy Zheng 		break;
1035069c1cfSIcenowy Zheng 	}
1045069c1cfSIcenowy Zheng }
105