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