1 /* 2 * (C) Copyright 2012 3 * Henrik Nordstrom <henrik@henriknordstrom.net> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <i2c.h> 10 #include <asm/arch/gpio.h> 11 #include <axp209.h> 12 13 static int axp209_write(enum axp209_reg reg, u8 val) 14 { 15 return i2c_write(0x34, reg, 1, &val, 1); 16 } 17 18 static int axp209_read(enum axp209_reg reg, u8 *val) 19 { 20 return i2c_read(0x34, reg, 1, val, 1); 21 } 22 23 static u8 axp209_mvolt_to_cfg(int mvolt, int min, int max, int div) 24 { 25 if (mvolt < min) 26 mvolt = min; 27 else if (mvolt > max) 28 mvolt = max; 29 30 return (mvolt - min) / div; 31 } 32 33 int axp209_set_dcdc2(int mvolt) 34 { 35 int rc; 36 u8 cfg, current; 37 38 cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25); 39 40 /* Do we really need to be this gentle? It has built-in voltage slope */ 41 while ((rc = axp209_read(AXP209_DCDC2_VOLTAGE, ¤t)) == 0 && 42 current != cfg) { 43 if (current < cfg) 44 current++; 45 else 46 current--; 47 48 rc = axp209_write(AXP209_DCDC2_VOLTAGE, current); 49 if (rc) 50 break; 51 } 52 53 return rc; 54 } 55 56 int axp209_set_dcdc3(int mvolt) 57 { 58 u8 cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25); 59 60 return axp209_write(AXP209_DCDC3_VOLTAGE, cfg); 61 } 62 63 int axp209_set_ldo2(int mvolt) 64 { 65 int rc; 66 u8 cfg, reg; 67 68 cfg = axp209_mvolt_to_cfg(mvolt, 1800, 3300, 100); 69 70 rc = axp209_read(AXP209_LDO24_VOLTAGE, ®); 71 if (rc) 72 return rc; 73 74 /* LDO2 configuration is in upper 4 bits */ 75 reg = (reg & 0x0f) | (cfg << 4); 76 return axp209_write(AXP209_LDO24_VOLTAGE, reg); 77 } 78 79 int axp209_set_ldo3(int mvolt) 80 { 81 u8 cfg; 82 83 if (mvolt == -1) 84 cfg = 0x80; /* determined by LDO3IN pin */ 85 else 86 cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25); 87 88 return axp209_write(AXP209_LDO3_VOLTAGE, cfg); 89 } 90 91 int axp209_set_ldo4(int mvolt) 92 { 93 int rc; 94 static const int vindex[] = { 95 1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500, 96 2700, 2800, 3000, 3100, 3200, 3300 97 }; 98 u8 cfg, reg; 99 100 /* Translate mvolt to register cfg value, requested <= selected */ 101 for (cfg = 15; vindex[cfg] > mvolt && cfg > 0; cfg--); 102 103 rc = axp209_read(AXP209_LDO24_VOLTAGE, ®); 104 if (rc) 105 return rc; 106 107 /* LDO4 configuration is in lower 4 bits */ 108 reg = (reg & 0xf0) | (cfg << 0); 109 return axp209_write(AXP209_LDO24_VOLTAGE, reg); 110 } 111 112 int axp209_init(void) 113 { 114 u8 ver; 115 int i, rc; 116 117 rc = axp209_read(AXP209_CHIP_VERSION, &ver); 118 if (rc) 119 return rc; 120 121 /* Low 4 bits is chip version */ 122 ver &= 0x0f; 123 124 if (ver != 0x1) 125 return -1; 126 127 /* Mask all interrupts */ 128 for (i = AXP209_IRQ_ENABLE1; i <= AXP209_IRQ_ENABLE5; i++) { 129 rc = axp209_write(i, 0); 130 if (rc) 131 return rc; 132 } 133 134 return 0; 135 } 136 137 int axp209_poweron_by_dc(void) 138 { 139 u8 v; 140 141 if (axp209_read(AXP209_POWER_STATUS, &v)) 142 return 0; 143 144 return (v & AXP209_POWER_STATUS_ON_BY_DC); 145 } 146 147 int axp209_power_button(void) 148 { 149 u8 v; 150 151 if (axp209_read(AXP209_IRQ_STATUS5, &v)) 152 return 0; 153 154 axp209_write(AXP209_IRQ_STATUS5, AXP209_IRQ5_PEK_DOWN); 155 156 return v & AXP209_IRQ5_PEK_DOWN; 157 } 158