xref: /rk3399_ARM-atf/plat/allwinner/sun50i_h6/sunxi_power.c (revision c1dd9e63bfc6298905441a79e4a06ee29b789483)
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>
11*658b3154SAndre Przywara #include <common/fdt_wrappers.h>
12fb23b104SSamuel Holland #include <drivers/allwinner/axp.h>
137060e0d8SSamuel Holland #include <drivers/allwinner/sunxi_rsb.h>
14*658b3154SAndre Przywara #include <libfdt.h>
159227719dSAndre Przywara #include <lib/mmio.h>
1609d40e0eSAntonio Nino Diaz 
179227719dSAndre Przywara #include <sunxi_cpucfg.h>
18d5ddf67aSAndre Przywara #include <sunxi_def.h>
196d372828SIcenowy Zheng #include <sunxi_mmap.h>
204ec1a239SAndre Przywara #include <sunxi_private.h>
216d372828SIcenowy Zheng 
227060e0d8SSamuel Holland #define AXP805_HW_ADDR	0x745
237060e0d8SSamuel Holland #define AXP805_RT_ADDR	0x3a
246d372828SIcenowy Zheng 
25c0e109f2SSamuel Holland static enum pmic_type {
26c0e109f2SSamuel Holland 	UNKNOWN,
276d372828SIcenowy Zheng 	AXP805,
28c0e109f2SSamuel Holland } pmic;
296d372828SIcenowy Zheng 
axp_read(uint8_t reg)30fb23b104SSamuel Holland int axp_read(uint8_t reg)
316d372828SIcenowy Zheng {
327060e0d8SSamuel Holland 	return rsb_read(AXP805_RT_ADDR, reg);
33fb23b104SSamuel Holland }
34fb23b104SSamuel Holland 
axp_write(uint8_t reg,uint8_t val)35fb23b104SSamuel Holland int axp_write(uint8_t reg, uint8_t val)
366d372828SIcenowy Zheng {
377060e0d8SSamuel Holland 	return rsb_write(AXP805_RT_ADDR, reg, val);
386d372828SIcenowy Zheng }
396d372828SIcenowy Zheng 
rsb_init(void)407060e0d8SSamuel Holland static int rsb_init(void)
416d372828SIcenowy Zheng {
426d372828SIcenowy Zheng 	int ret;
436d372828SIcenowy Zheng 
447060e0d8SSamuel Holland 	ret = rsb_init_controller();
454538c498SSamuel Holland 	if (ret)
464538c498SSamuel Holland 		return ret;
476d372828SIcenowy Zheng 
487060e0d8SSamuel Holland 	/* Switch to the recommended 3 MHz bus clock. */
497060e0d8SSamuel Holland 	ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
504538c498SSamuel Holland 	if (ret)
514538c498SSamuel Holland 		return ret;
526d372828SIcenowy Zheng 
537060e0d8SSamuel Holland 	/* Initiate an I2C transaction to switch the PMIC to RSB mode. */
547060e0d8SSamuel Holland 	ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
557060e0d8SSamuel Holland 	if (ret)
567060e0d8SSamuel Holland 		return ret;
577060e0d8SSamuel Holland 
587060e0d8SSamuel Holland 	/* Associate the 8-bit runtime address with the 12-bit bus address. */
597060e0d8SSamuel Holland 	ret = rsb_assign_runtime_address(AXP805_HW_ADDR, AXP805_RT_ADDR);
607060e0d8SSamuel Holland 	if (ret)
617060e0d8SSamuel Holland 		return ret;
627060e0d8SSamuel Holland 
637060e0d8SSamuel Holland 	return axp_check_id();
646d372828SIcenowy Zheng }
657c26b6ecSIcenowy Zheng 
sunxi_pmic_setup(uint16_t socid,const void * fdt)66df301601SAndre Przywara int sunxi_pmic_setup(uint16_t socid, const void *fdt)
677c26b6ecSIcenowy Zheng {
68*658b3154SAndre Przywara 	int node, ret;
69*658b3154SAndre Przywara 
70*658b3154SAndre Przywara 	node = fdt_node_offset_by_compatible(fdt, 0, "allwinner,sun8i-a23-rsb");
71*658b3154SAndre Przywara 	if ((node < 0) || !fdt_node_is_enabled(fdt, node)) {
72*658b3154SAndre Przywara 		return -ENODEV;
73*658b3154SAndre Przywara 	}
746d372828SIcenowy Zheng 
757060e0d8SSamuel Holland 	INFO("PMIC: Probing AXP805 on RSB\n");
764538c498SSamuel Holland 
777060e0d8SSamuel Holland 	ret = sunxi_init_platform_r_twi(socid, true);
784538c498SSamuel Holland 	if (ret)
794538c498SSamuel Holland 		return ret;
804538c498SSamuel Holland 
817060e0d8SSamuel Holland 	ret = rsb_init();
827060e0d8SSamuel Holland 	if (ret)
837060e0d8SSamuel Holland 		return ret;
846d372828SIcenowy Zheng 
857060e0d8SSamuel Holland 	/* Switch the AXP805 to master/single-PMIC mode. */
867060e0d8SSamuel Holland 	ret = axp_write(0xff, 0x0);
876d372828SIcenowy Zheng 	if (ret)
88c0e109f2SSamuel Holland 		return ret;
89c0e109f2SSamuel Holland 
906d372828SIcenowy Zheng 	pmic = AXP805;
91fb23b104SSamuel Holland 	axp_setup_regulators(fdt);
927c26b6ecSIcenowy Zheng 
937060e0d8SSamuel Holland 	/* Switch the PMIC back to I2C mode. */
947060e0d8SSamuel Holland 	ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
957060e0d8SSamuel Holland 	if (ret)
967060e0d8SSamuel Holland 		return ret;
977060e0d8SSamuel Holland 
987c26b6ecSIcenowy Zheng 	return 0;
997c26b6ecSIcenowy Zheng }
1005069c1cfSIcenowy Zheng 
sunxi_power_down(void)101818e6732SSamuel Holland void sunxi_power_down(void)
1025069c1cfSIcenowy Zheng {
1035069c1cfSIcenowy Zheng 	switch (pmic) {
1045069c1cfSIcenowy Zheng 	case AXP805:
1057060e0d8SSamuel Holland 		/* (Re-)init RSB in case the rich OS has disabled it. */
1067060e0d8SSamuel Holland 		sunxi_init_platform_r_twi(SUNXI_SOC_H6, true);
1077060e0d8SSamuel Holland 		rsb_init();
108fb23b104SSamuel Holland 		axp_power_off();
1095069c1cfSIcenowy Zheng 		break;
1105069c1cfSIcenowy Zheng 	default:
1115069c1cfSIcenowy Zheng 		break;
1125069c1cfSIcenowy Zheng 	}
1135069c1cfSIcenowy Zheng }
1149227719dSAndre Przywara 
sunxi_cpu_power_off_self(void)1159227719dSAndre Przywara void sunxi_cpu_power_off_self(void)
1169227719dSAndre Przywara {
1179227719dSAndre Przywara 	u_register_t mpidr = read_mpidr();
1189227719dSAndre Przywara 	unsigned int core  = MPIDR_AFFLVL0_VAL(mpidr);
1199227719dSAndre Przywara 
1209227719dSAndre Przywara 	/* Enable the CPUIDLE hardware (only really needs to be done once). */
1219227719dSAndre Przywara 	mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0x16aa0000);
1229227719dSAndre Przywara 	mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0xaa160001);
1239227719dSAndre Przywara 
1249227719dSAndre Przywara 	/* Trigger power off for this core. */
1259227719dSAndre Przywara 	mmio_write_32(SUNXI_CORE_CLOSE_REG, BIT_32(core));
1269227719dSAndre Przywara }
127