1 /* 2 * Copyright (C) 2013 Samsung Electronics 3 * Piotr Wilczek <p.wilczek@samsung.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <power/pmic.h> 10 #include <power/max77693_fg.h> 11 #include <i2c.h> 12 #include <power/power_chrg.h> 13 #include <power/battery.h> 14 #include <power/fg_battery_cell_params.h> 15 #include <errno.h> 16 17 static int max77693_get_vcell(u32 *vcell) 18 { 19 u16 value; 20 u8 ret; 21 22 ret = i2c_read(MAX77693_FUEL_I2C_ADDR, MAX77693_VCELL, 1, 23 (u8 *)&value, 2); 24 if (ret) 25 return ret; 26 27 *vcell = (u32)(value >> 3); 28 *vcell = *vcell * 625; 29 30 return 0; 31 } 32 33 static int max77693_get_soc(u32 *soc) 34 { 35 u16 value; 36 u8 ret; 37 38 ret = i2c_read(MAX77693_FUEL_I2C_ADDR, MAX77693_VFSOC, 1, 39 (u8 *)&value, 2); 40 if (ret) 41 return ret; 42 43 *soc = (u32)(value >> 8); 44 45 return 0; 46 } 47 48 static int power_update_battery(struct pmic *p, struct pmic *bat) 49 { 50 struct power_battery *pb = bat->pbat; 51 int ret; 52 53 if (pmic_probe(p)) { 54 puts("Can't find max77693 fuel gauge\n"); 55 return -ENODEV; 56 } 57 58 ret = max77693_get_soc(&pb->bat->state_of_chrg); 59 if (ret) 60 return ret; 61 62 max77693_get_vcell(&pb->bat->voltage_uV); 63 if (ret) 64 return ret; 65 66 return 0; 67 } 68 69 static int power_check_battery(struct pmic *p, struct pmic *bat) 70 { 71 struct power_battery *pb = bat->pbat; 72 unsigned int val; 73 int ret = 0; 74 75 if (pmic_probe(p)) { 76 puts("Can't find max77693 fuel gauge\n"); 77 return -ENODEV; 78 } 79 80 ret = pmic_reg_read(p, MAX77693_STATUS, &val); 81 if (ret) 82 return ret; 83 debug("fg status: 0x%x\n", val); 84 85 ret = pmic_reg_read(p, MAX77693_VERSION, &pb->bat->version); 86 if (ret) 87 return ret; 88 89 ret = power_update_battery(p, bat); 90 if (ret) 91 return ret; 92 debug("fg ver: 0x%x\n", pb->bat->version); 93 printf("BAT: state_of_charge(SOC):%d%%\n", 94 pb->bat->state_of_chrg); 95 96 printf(" voltage: %d.%6.6d [V] (expected to be %d [mAh])\n", 97 pb->bat->voltage_uV / 1000000, 98 pb->bat->voltage_uV % 1000000, 99 pb->bat->capacity); 100 101 if (pb->bat->voltage_uV > 3850000) 102 pb->bat->state = EXT_SOURCE; 103 else if (pb->bat->voltage_uV < 3600000 || pb->bat->state_of_chrg < 5) 104 pb->bat->state = CHARGE; 105 else 106 pb->bat->state = NORMAL; 107 108 return 0; 109 } 110 111 static struct power_fg power_fg_ops = { 112 .fg_battery_check = power_check_battery, 113 .fg_battery_update = power_update_battery, 114 }; 115 116 int power_fg_init(unsigned char bus) 117 { 118 static const char name[] = "MAX77693_FG"; 119 struct pmic *p = pmic_alloc(); 120 121 if (!p) { 122 printf("%s: POWER allocation error!\n", __func__); 123 return -ENOMEM; 124 } 125 126 debug("Board Fuel Gauge init\n"); 127 128 p->name = name; 129 p->interface = PMIC_I2C; 130 p->number_of_regs = FG_NUM_OF_REGS; 131 p->hw.i2c.addr = MAX77693_FUEL_I2C_ADDR; 132 p->hw.i2c.tx_num = 2; 133 p->sensor_byte_order = PMIC_SENSOR_BYTE_ORDER_BIG; 134 p->bus = bus; 135 136 p->fg = &power_fg_ops; 137 138 return 0; 139 } 140