1795857dfSChen-Yu Tsai /* 2795857dfSChen-Yu Tsai * AXP809 driver based on AXP221 driver 3795857dfSChen-Yu Tsai * 4795857dfSChen-Yu Tsai * 5795857dfSChen-Yu Tsai * (C) Copyright 2016 Chen-Yu Tsai <wens@csie.org> 6795857dfSChen-Yu Tsai * 7795857dfSChen-Yu Tsai * Based on axp221.c 8795857dfSChen-Yu Tsai * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com> 9795857dfSChen-Yu Tsai * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl> 10795857dfSChen-Yu Tsai * 11795857dfSChen-Yu Tsai * SPDX-License-Identifier: GPL-2.0+ 12795857dfSChen-Yu Tsai */ 13795857dfSChen-Yu Tsai 14795857dfSChen-Yu Tsai #include <common.h> 15795857dfSChen-Yu Tsai #include <errno.h> 16795857dfSChen-Yu Tsai #include <asm/arch/gpio.h> 17795857dfSChen-Yu Tsai #include <asm/arch/pmic_bus.h> 18795857dfSChen-Yu Tsai #include <axp_pmic.h> 19795857dfSChen-Yu Tsai 20795857dfSChen-Yu Tsai static u8 axp809_mvolt_to_cfg(int mvolt, int min, int max, int div) 21795857dfSChen-Yu Tsai { 22795857dfSChen-Yu Tsai if (mvolt < min) 23795857dfSChen-Yu Tsai mvolt = min; 24795857dfSChen-Yu Tsai else if (mvolt > max) 25795857dfSChen-Yu Tsai mvolt = max; 26795857dfSChen-Yu Tsai 27795857dfSChen-Yu Tsai return (mvolt - min) / div; 28795857dfSChen-Yu Tsai } 29795857dfSChen-Yu Tsai 30795857dfSChen-Yu Tsai int axp_set_dcdc1(unsigned int mvolt) 31795857dfSChen-Yu Tsai { 32795857dfSChen-Yu Tsai int ret; 33795857dfSChen-Yu Tsai u8 cfg = axp809_mvolt_to_cfg(mvolt, 1600, 3400, 100); 34795857dfSChen-Yu Tsai 35795857dfSChen-Yu Tsai if (mvolt == 0) 36795857dfSChen-Yu Tsai return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 37795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL1_DCDC1_EN); 38795857dfSChen-Yu Tsai 39795857dfSChen-Yu Tsai ret = pmic_bus_write(AXP809_DCDC1_CTRL, cfg); 40795857dfSChen-Yu Tsai if (ret) 41795857dfSChen-Yu Tsai return ret; 42795857dfSChen-Yu Tsai 43795857dfSChen-Yu Tsai ret = pmic_bus_setbits(AXP809_OUTPUT_CTRL2, 44795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL2_DC1SW_EN); 45795857dfSChen-Yu Tsai if (ret) 46795857dfSChen-Yu Tsai return ret; 47795857dfSChen-Yu Tsai 48795857dfSChen-Yu Tsai return pmic_bus_setbits(AXP809_OUTPUT_CTRL1, 49795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL1_DCDC1_EN); 50795857dfSChen-Yu Tsai } 51795857dfSChen-Yu Tsai 52795857dfSChen-Yu Tsai int axp_set_dcdc2(unsigned int mvolt) 53795857dfSChen-Yu Tsai { 54795857dfSChen-Yu Tsai int ret; 55795857dfSChen-Yu Tsai u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20); 56795857dfSChen-Yu Tsai 57795857dfSChen-Yu Tsai if (mvolt == 0) 58795857dfSChen-Yu Tsai return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 59795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL1_DCDC2_EN); 60795857dfSChen-Yu Tsai 61795857dfSChen-Yu Tsai ret = pmic_bus_write(AXP809_DCDC2_CTRL, cfg); 62795857dfSChen-Yu Tsai if (ret) 63795857dfSChen-Yu Tsai return ret; 64795857dfSChen-Yu Tsai 65795857dfSChen-Yu Tsai return pmic_bus_setbits(AXP809_OUTPUT_CTRL1, 66795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL1_DCDC2_EN); 67795857dfSChen-Yu Tsai } 68795857dfSChen-Yu Tsai 69795857dfSChen-Yu Tsai int axp_set_dcdc3(unsigned int mvolt) 70795857dfSChen-Yu Tsai { 71795857dfSChen-Yu Tsai int ret; 72795857dfSChen-Yu Tsai u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1860, 20); 73795857dfSChen-Yu Tsai 74795857dfSChen-Yu Tsai if (mvolt == 0) 75795857dfSChen-Yu Tsai return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 76795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL1_DCDC3_EN); 77795857dfSChen-Yu Tsai 78795857dfSChen-Yu Tsai ret = pmic_bus_write(AXP809_DCDC3_CTRL, cfg); 79795857dfSChen-Yu Tsai if (ret) 80795857dfSChen-Yu Tsai return ret; 81795857dfSChen-Yu Tsai 82795857dfSChen-Yu Tsai return pmic_bus_setbits(AXP809_OUTPUT_CTRL1, 83795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL1_DCDC3_EN); 84795857dfSChen-Yu Tsai } 85795857dfSChen-Yu Tsai 86795857dfSChen-Yu Tsai int axp_set_dcdc4(unsigned int mvolt) 87795857dfSChen-Yu Tsai { 88795857dfSChen-Yu Tsai int ret; 89795857dfSChen-Yu Tsai u8 cfg = axp809_mvolt_to_cfg(mvolt, 600, 1540, 20); 90795857dfSChen-Yu Tsai 91795857dfSChen-Yu Tsai if (mvolt >= 1540) 92795857dfSChen-Yu Tsai cfg = 0x30 + axp809_mvolt_to_cfg(mvolt, 1800, 2600, 100); 93795857dfSChen-Yu Tsai 94795857dfSChen-Yu Tsai if (mvolt == 0) 95795857dfSChen-Yu Tsai return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 96795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL1_DCDC4_EN); 97795857dfSChen-Yu Tsai 98795857dfSChen-Yu Tsai ret = pmic_bus_write(AXP809_DCDC5_CTRL, cfg); 99795857dfSChen-Yu Tsai if (ret) 100795857dfSChen-Yu Tsai return ret; 101795857dfSChen-Yu Tsai 102795857dfSChen-Yu Tsai return pmic_bus_setbits(AXP809_OUTPUT_CTRL1, 103795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL1_DCDC4_EN); 104795857dfSChen-Yu Tsai } 105795857dfSChen-Yu Tsai 106795857dfSChen-Yu Tsai int axp_set_dcdc5(unsigned int mvolt) 107795857dfSChen-Yu Tsai { 108795857dfSChen-Yu Tsai int ret; 109795857dfSChen-Yu Tsai u8 cfg = axp809_mvolt_to_cfg(mvolt, 1000, 2550, 50); 110795857dfSChen-Yu Tsai 111795857dfSChen-Yu Tsai if (mvolt == 0) 112795857dfSChen-Yu Tsai return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 113795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL1_DCDC5_EN); 114795857dfSChen-Yu Tsai 115795857dfSChen-Yu Tsai ret = pmic_bus_write(AXP809_DCDC5_CTRL, cfg); 116795857dfSChen-Yu Tsai if (ret) 117795857dfSChen-Yu Tsai return ret; 118795857dfSChen-Yu Tsai 119795857dfSChen-Yu Tsai return pmic_bus_setbits(AXP809_OUTPUT_CTRL1, 120795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL1_DCDC5_EN); 121795857dfSChen-Yu Tsai } 122795857dfSChen-Yu Tsai 123795857dfSChen-Yu Tsai int axp_set_aldo(int aldo_num, unsigned int mvolt) 124795857dfSChen-Yu Tsai { 125795857dfSChen-Yu Tsai int ret; 126795857dfSChen-Yu Tsai u8 cfg; 127795857dfSChen-Yu Tsai 128795857dfSChen-Yu Tsai if (aldo_num < 1 || aldo_num > 3) 129795857dfSChen-Yu Tsai return -EINVAL; 130795857dfSChen-Yu Tsai 131795857dfSChen-Yu Tsai if (mvolt == 0 && aldo_num == 3) 132795857dfSChen-Yu Tsai return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2, 133795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL2_ALDO3_EN); 134795857dfSChen-Yu Tsai if (mvolt == 0) 135795857dfSChen-Yu Tsai return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 136795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL1_ALDO1_EN << (aldo_num - 1)); 137795857dfSChen-Yu Tsai 138795857dfSChen-Yu Tsai cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100); 139795857dfSChen-Yu Tsai ret = pmic_bus_write(AXP809_ALDO1_CTRL + (aldo_num - 1), cfg); 140795857dfSChen-Yu Tsai if (ret) 141795857dfSChen-Yu Tsai return ret; 142795857dfSChen-Yu Tsai 143795857dfSChen-Yu Tsai if (aldo_num == 3) 144795857dfSChen-Yu Tsai return pmic_bus_setbits(AXP809_OUTPUT_CTRL2, 145795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL2_ALDO3_EN); 146795857dfSChen-Yu Tsai return pmic_bus_clrbits(AXP809_OUTPUT_CTRL1, 147795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL1_ALDO1_EN << (aldo_num - 1)); 148795857dfSChen-Yu Tsai } 149795857dfSChen-Yu Tsai 150795857dfSChen-Yu Tsai /* TODO: re-work other AXP drivers to consolidate ALDO functions. */ 151795857dfSChen-Yu Tsai int axp_set_aldo1(unsigned int mvolt) 152795857dfSChen-Yu Tsai { 153795857dfSChen-Yu Tsai return axp_set_aldo(1, mvolt); 154795857dfSChen-Yu Tsai } 155795857dfSChen-Yu Tsai 156795857dfSChen-Yu Tsai int axp_set_aldo2(unsigned int mvolt) 157795857dfSChen-Yu Tsai { 158795857dfSChen-Yu Tsai return axp_set_aldo(2, mvolt); 159795857dfSChen-Yu Tsai } 160795857dfSChen-Yu Tsai 161795857dfSChen-Yu Tsai int axp_set_aldo3(unsigned int mvolt) 162795857dfSChen-Yu Tsai { 163795857dfSChen-Yu Tsai return axp_set_aldo(3, mvolt); 164795857dfSChen-Yu Tsai } 165795857dfSChen-Yu Tsai 166795857dfSChen-Yu Tsai int axp_set_dldo(int dldo_num, unsigned int mvolt) 167795857dfSChen-Yu Tsai { 168795857dfSChen-Yu Tsai u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100); 169795857dfSChen-Yu Tsai int ret; 170795857dfSChen-Yu Tsai 171795857dfSChen-Yu Tsai if (dldo_num < 1 || dldo_num > 2) 172795857dfSChen-Yu Tsai return -EINVAL; 173795857dfSChen-Yu Tsai 174795857dfSChen-Yu Tsai if (mvolt == 0) 175795857dfSChen-Yu Tsai return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2, 176795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1)); 177795857dfSChen-Yu Tsai 178795857dfSChen-Yu Tsai if (dldo_num == 1 && mvolt > 3300) 179795857dfSChen-Yu Tsai cfg += 1 + axp809_mvolt_to_cfg(mvolt, 3400, 4200, 200); 180795857dfSChen-Yu Tsai ret = pmic_bus_write(AXP809_DLDO1_CTRL + (dldo_num - 1), cfg); 181795857dfSChen-Yu Tsai if (ret) 182795857dfSChen-Yu Tsai return ret; 183795857dfSChen-Yu Tsai 184795857dfSChen-Yu Tsai return pmic_bus_setbits(AXP809_OUTPUT_CTRL2, 185795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL2_DLDO1_EN << (dldo_num - 1)); 186795857dfSChen-Yu Tsai } 187795857dfSChen-Yu Tsai 188795857dfSChen-Yu Tsai int axp_set_eldo(int eldo_num, unsigned int mvolt) 189795857dfSChen-Yu Tsai { 190795857dfSChen-Yu Tsai int ret; 191795857dfSChen-Yu Tsai u8 cfg = axp809_mvolt_to_cfg(mvolt, 700, 3300, 100); 192795857dfSChen-Yu Tsai 193795857dfSChen-Yu Tsai if (eldo_num < 1 || eldo_num > 3) 194795857dfSChen-Yu Tsai return -EINVAL; 195795857dfSChen-Yu Tsai 196795857dfSChen-Yu Tsai if (mvolt == 0) 197795857dfSChen-Yu Tsai return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2, 198795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1)); 199795857dfSChen-Yu Tsai 200795857dfSChen-Yu Tsai ret = pmic_bus_write(AXP809_ELDO1_CTRL + (eldo_num - 1), cfg); 201795857dfSChen-Yu Tsai if (ret) 202795857dfSChen-Yu Tsai return ret; 203795857dfSChen-Yu Tsai 204795857dfSChen-Yu Tsai return pmic_bus_setbits(AXP809_OUTPUT_CTRL2, 205795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL2_ELDO1_EN << (eldo_num - 1)); 206795857dfSChen-Yu Tsai } 207795857dfSChen-Yu Tsai 208795857dfSChen-Yu Tsai int axp_set_sw(bool on) 209795857dfSChen-Yu Tsai { 210795857dfSChen-Yu Tsai if (on) 211795857dfSChen-Yu Tsai return pmic_bus_setbits(AXP809_OUTPUT_CTRL2, 212795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL2_SWOUT_EN); 213795857dfSChen-Yu Tsai 214795857dfSChen-Yu Tsai return pmic_bus_clrbits(AXP809_OUTPUT_CTRL2, 215795857dfSChen-Yu Tsai AXP809_OUTPUT_CTRL2_SWOUT_EN); 216795857dfSChen-Yu Tsai } 217795857dfSChen-Yu Tsai 218795857dfSChen-Yu Tsai int axp_init(void) 219795857dfSChen-Yu Tsai { 220*a4ca3799SMasahiro Yamada return pmic_bus_init(); 221795857dfSChen-Yu Tsai } 222795857dfSChen-Yu Tsai 223795857dfSChen-Yu Tsai int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 224795857dfSChen-Yu Tsai { 225795857dfSChen-Yu Tsai pmic_bus_write(AXP809_SHUTDOWN, AXP809_SHUTDOWN_POWEROFF); 226795857dfSChen-Yu Tsai 227795857dfSChen-Yu Tsai /* infinite loop during shutdown */ 228795857dfSChen-Yu Tsai while (1) {} 229795857dfSChen-Yu Tsai 230795857dfSChen-Yu Tsai /* not reached */ 231795857dfSChen-Yu Tsai return 0; 232795857dfSChen-Yu Tsai } 233