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