1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2011-2013 4 * Texas Instruments, <www.ti.com> 5 */ 6 7 #include <common.h> 8 #include <i2c.h> 9 #include <linux/errno.h> 10 #include <power/pmic.h> 11 #include <power/tps65218.h> 12 13 #ifndef CONFIG_DM_I2C 14 int tps65218_reg_read(uchar dest_reg, uchar *dest_val) 15 { 16 uchar read_val; 17 int ret; 18 19 ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1); 20 if (ret) 21 return ret; 22 23 *dest_val = read_val; 24 25 return 0; 26 } 27 28 /** 29 * tps65218_reg_write() - Generic function that can write a TPS65218 PMIC 30 * register or bit field regardless of protection 31 * level. 32 * 33 * @prot_level: Register password protection. Use 34 * TPS65218_PROT_LEVEL_NONE, 35 * TPS65218_PROT_LEVEL_1 or TPS65218_PROT_LEVEL_2 36 * @dest_reg: Register address to write. 37 * @dest_val: Value to write. 38 * @mask: Bit mask (8 bits) to be applied. Function will only 39 * change bits that are set in the bit mask. 40 * 41 * @return: 0 for success, not 0 on failure, as per the i2c API 42 */ 43 int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val, 44 uchar mask) 45 { 46 uchar read_val; 47 uchar xor_reg; 48 int ret; 49 50 /* 51 * If we are affecting only a bit field, read dest_reg and apply the 52 * mask 53 */ 54 if (mask != TPS65218_MASK_ALL_BITS) { 55 ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1); 56 if (ret) 57 return ret; 58 read_val &= (~mask); 59 read_val |= (dest_val & mask); 60 dest_val = read_val; 61 } 62 63 if (prot_level > 0) { 64 xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK; 65 ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1, 66 &xor_reg, 1); 67 if (ret) 68 return ret; 69 } 70 71 ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1); 72 if (ret) 73 return ret; 74 75 if (prot_level == TPS65218_PROT_LEVEL_2) { 76 ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1, 77 &xor_reg, 1); 78 if (ret) 79 return ret; 80 81 ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1); 82 if (ret) 83 return ret; 84 } 85 86 return 0; 87 } 88 #else 89 struct udevice *tps65218_dev __attribute__((section(".data"))) = NULL; 90 91 int tps65218_reg_read(uchar dest_reg, uchar *dest_val) 92 { 93 uchar read_val; 94 int ret; 95 96 if (!tps65218_dev) 97 return -ENODEV; 98 99 ret = dm_i2c_read(tps65218_dev, dest_reg, &read_val, 1); 100 if (ret) 101 return ret; 102 103 *dest_val = read_val; 104 105 return 0; 106 } 107 108 int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val, 109 uchar mask) 110 { 111 uchar read_val; 112 uchar xor_reg; 113 int ret; 114 115 if (!tps65218_dev) 116 return -ENODEV; 117 118 /* 119 * If we are affecting only a bit field, read dest_reg and apply the 120 * mask 121 */ 122 if (mask != TPS65218_MASK_ALL_BITS) { 123 ret = dm_i2c_read(tps65218_dev, dest_reg, &read_val, 1); 124 if (ret) 125 return ret; 126 127 read_val &= (~mask); 128 read_val |= (dest_val & mask); 129 dest_val = read_val; 130 } 131 132 if (prot_level > 0) { 133 xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK; 134 ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg, 135 1); 136 if (ret) 137 return ret; 138 } 139 140 ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1); 141 if (ret) 142 return ret; 143 144 if (prot_level == TPS65218_PROT_LEVEL_2) { 145 ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg, 146 1); 147 if (ret) 148 return ret; 149 150 ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1); 151 if (ret) 152 return ret; 153 } 154 155 return 0; 156 } 157 #endif 158 159 /** 160 * tps65218_voltage_update() - Function to change a voltage level, as this 161 * is a multi-step process. 162 * @dc_cntrl_reg: DC voltage control register to change. 163 * @volt_sel: New value for the voltage register 164 * @return: 0 for success, not 0 on failure. 165 */ 166 int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel) 167 { 168 if ((dc_cntrl_reg != TPS65218_DCDC1) && 169 (dc_cntrl_reg != TPS65218_DCDC2) && 170 (dc_cntrl_reg != TPS65218_DCDC3)) 171 return 1; 172 173 /* set voltage level */ 174 if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, dc_cntrl_reg, volt_sel, 175 TPS65218_DCDC_VSEL_MASK)) 176 return 1; 177 178 /* set GO bit to initiate voltage transition */ 179 if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_SLEW, 180 TPS65218_DCDC_GO, TPS65218_DCDC_GO)) 181 return 1; 182 183 return 0; 184 } 185 186 /** 187 * tps65218_toggle_fseal() - Perform the sequence that toggles the FSEAL bit. 188 * 189 * @return: 0 on success, -EBADE if the sequence was broken 190 */ 191 int tps65218_toggle_fseal(void) 192 { 193 if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD, 194 0xb1, TPS65218_MASK_ALL_BITS)) 195 return -EBADE; 196 197 if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD, 198 0xfe, TPS65218_MASK_ALL_BITS)) 199 return -EBADE; 200 201 if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD, 202 0xa3, TPS65218_MASK_ALL_BITS)) 203 return -EBADE; 204 205 return 0; 206 } 207 208 /** 209 * tps65218_lock_fseal() - Perform the sequence that locks the FSEAL bit to 1. 210 * 211 * The FSEAL bit prevents the PMIC from turning off DCDC5 and DCDC6. It can be 212 * toggled at most 3 times: 0->1, 1->0, and finally 0->1. After the third switch 213 * its value is locked and can only be reset by powering off the PMIC entirely. 214 * 215 * @return: 0 on success, -EBADE if the sequence was broken 216 */ 217 int tps65218_lock_fseal(void) 218 { 219 int i; 220 221 for (i = 0; i < 3; i++) 222 if (tps65218_toggle_fseal()) 223 return -EBADE; 224 225 return 0; 226 } 227 228 #ifndef CONFIG_DM_I2C 229 int power_tps65218_init(unsigned char bus) 230 { 231 static const char name[] = "TPS65218_PMIC"; 232 struct pmic *p = pmic_alloc(); 233 234 if (!p) { 235 printf("%s: POWER allocation error!\n", __func__); 236 return -ENOMEM; 237 } 238 239 p->name = name; 240 p->interface = PMIC_I2C; 241 p->number_of_regs = TPS65218_PMIC_NUM_OF_REGS; 242 p->hw.i2c.addr = TPS65218_CHIP_PM; 243 p->hw.i2c.tx_num = 1; 244 p->bus = bus; 245 246 return 0; 247 } 248 #else 249 int power_tps65218_init(unsigned char bus) 250 { 251 struct udevice *dev = NULL; 252 int rc; 253 254 rc = i2c_get_chip_for_busnum(bus, TPS65218_CHIP_PM, 1, &dev); 255 if (rc) 256 return rc; 257 tps65218_dev = dev; 258 return 0; 259 } 260 #endif 261