Updated macc24’s battery driver

Home   »   Updated macc24’s battery driver

From 786be1506dbf839f9d93b2613c26221a067f202c Mon Sep 17 00:00:00 2001
From: Chris Morgan 
Date: Tue, 4 May 2021 21:45:31 -0500
Subject: [PATCH] Updated macc24's battery driver

---
 .../boot/dts/rockchip/rk3326-odroid-go2.dts   |  37 +++
 drivers/mfd/rk808.c                           |  12 +-
 drivers/power/supply/Kconfig                  |   7 +
 drivers/power/supply/Makefile                 |   1 +
 drivers/power/supply/rk817_battery.c          | 266 ++++++++++++++++++
 include/linux/mfd/rk808.h                     |  34 +++
 6 files changed, 356 insertions(+), 1 deletion(-)
 create mode 100644 drivers/power/supply/rk817_battery.c

diff --git a/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts
index e8c2b5a817a7..335fbfed954b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts
@@ -52,6 +52,21 @@ backlight: backlight {
 		pwms = <&pwm1 0 25000 0>;
 	};
 
+	battery_cell: battery-cell {
+		compatible = "simple-battery";
+		energy-full-design-microamp-hours = <3000000>;
+		voltage-min-design-microvolt = <3500000>;
+		voltage-max-design-microvolt = <4100000>;
+
+		ocv-capacity-celcius = <20>;
+		ocv-capacity-table-0 =  <3500 0>, <3625 5>, <3685 10>, <3697 15>,
+					<3718 20>, <3735 25>, <3748 30>, <3760 35>,
+					<3774 40>, <3788 45>, <3802 50>, <3816 55>,
+					<3834 60>, <3853 65>, <3877 70>, <3908 75>,
+					<3946 80>, <3975 85>, <4018 90>, <4071 95>,
+					<4106 100>;
+	};
+
 	gpio-keys {
 		compatible = "gpio-keys";
 		pinctrl-names = "default";
@@ -464,6 +494,13 @@ regulator-state-mem {
 		rk817_codec: codec {
 			rockchip,mic-in-differential;
 		};
+
+		rk817_battery: battery {
+			compatible = "rk817,battery";
+			monitored-battery = <&battery_cell>;
+			bat_res = <180>;
+			sample_res = <10>;
+                };
 	};
 };
 
diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
index 9231209184e0..13f160a03554 100644
--- a/drivers/mfd/rk808.c
+++ b/drivers/mfd/rk808.c
@@ -66,6 +66,10 @@ static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
 	case RK817_SECONDS_REG ... RK817_WEEKS_REG:
 	case RK817_RTC_STATUS_REG:
 	case RK817_CODEC_DTOP_LPT_SRST:
+	case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0:
+	case RK817_PMIC_CHRG_STS:
+	case RK817_PMIC_CHRG_OUT:
+	case RK817_PMIC_CHRG_IN:
 	case RK817_INT_STS_REG0:
 	case RK817_INT_STS_REG1:
 	case RK817_INT_STS_REG2:
@@ -73,7 +77,7 @@ static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg)
 		return true;
 	}
 
-	return true;
+	return false;
 }
 
 static const struct regmap_config rk818_regmap_config = {
@@ -169,6 +173,12 @@ static const struct mfd_cell rk817s[] = {
 		.name = "rk817-codec",
 	},
 #endif
+#ifdef CONFIG_BATTERY_RK817
+	{
+		.name = "rk817-battery",
+		.of_compatible = "rk817,battery",
+	},
+#endif
 };
 
 static const struct mfd_cell rk818s[] = {
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index e696364126f1..a1289746ebc4 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -718,6 +718,13 @@ config BATTERY_RT5033
 	  The fuelgauge calculates and determines the battery state of charge
 	  according to battery open circuit voltage.
 
+config BATTERY_RK817
+	bool "RK817 Battery Driver"
+	depends on MFD_RK808
+	help
+	  This adds support for the battery for the Rockchip RK817 PMIC.
+	  The battery is an optional device for the RK817 PMIC.
+
 config CHARGER_RT9455
 	tristate "Richtek RT9455 battery charger driver"
 	depends on I2C
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index a7309a3d1a47..f23b1554fdbf 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_BATTERY_MAX17040)	+= max17040_battery.o
 obj-$(CONFIG_BATTERY_MAX17042)	+= max17042_battery.o
 obj-$(CONFIG_BATTERY_MAX1721X)	+= max1721x_battery.o
 obj-$(CONFIG_BATTERY_Z2)	+= z2_battery.o
+obj-$(CONFIG_BATTERY_RK817)	+= rk817_battery.o
 obj-$(CONFIG_BATTERY_RT5033)	+= rt5033_battery.o
 obj-$(CONFIG_CHARGER_RT9455)	+= rt9455_charger.o
 obj-$(CONFIG_BATTERY_S3C_ADC)	+= s3c_adc_battery.o
diff --git a/drivers/power/supply/rk817_battery.c b/drivers/power/supply/rk817_battery.c
new file mode 100644
index 000000000000..7212b785b3ff
--- /dev/null
+++ b/drivers/power/supply/rk817_battery.c
@@ -0,0 +1,266 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+enum charge_status {
+	CHRG_OFF,
+	DEAD_CHRG,
+	TRICKLE_CHRG,
+	CC_OR_CV_CHRG,
+	CHARGE_FINISH,
+	USB_OVER_VOL,
+	BAT_TMP_ERR,
+	BAT_TIM_ERR,
+};
+
+struct rk817_bat {
+	struct platform_device *pdev;
+	struct device *dev;
+	struct i2c_client *client;
+	struct rk808 *rk808;
+
+	struct power_supply *bat_ps;
+	struct power_supply_battery_info info;
+
+	/* FIXME: do i move it into other struct? */
+	uint32_t voltage_k;
+	uint32_t voltage_b;
+	int res_div;
+	int sample_res;
+};
+
+static int rk817_get_reg_hl(struct rk817_bat *battery, int regH, int regL)
+{
+	int tmp, ret;
+	uint32_t out;
+	struct rk808 *rk808 = battery->rk808;
+
+	ret = regmap_read(rk808->regmap, regL, &tmp);
+	if (ret)
+		return ret;
+	out |= tmp;
+
+	ret = regmap_read(rk808->regmap, regH, &tmp);
+	if (ret)
+		return ret;
+	out |= tmp << 8;
+
+	return out;
+}
+
+static void rk817_write_reg_hl(struct rk817_bat *battery, int regH, int regL, int val)
+{
+	uint8_t tmp;
+	struct rk808 *rk808 = battery->rk808;
+
+	tmp = val & 0xff;
+	regmap_write(rk808->regmap, regL, tmp);
+	tmp = (val >> 8) & 0xff;
+	regmap_write(rk808->regmap, regH, tmp);
+}
+
+static void rk817_bat_calib_vol(struct rk817_bat *battery)
+{
+	uint32_t vcalib0 = 0;
+	uint32_t vcalib1 = 0;
+
+	/* calibrate voltage */
+	vcalib0 = rk817_get_reg_hl(battery, RK817_GAS_GAUGE_VCALIB0_H, RK817_GAS_GAUGE_VCALIB0_L);
+	vcalib1 = rk817_get_reg_hl(battery, RK817_GAS_GAUGE_VCALIB1_H, RK817_GAS_GAUGE_VCALIB1_L);
+
+	/* values were taken from BSP kernel */
+	battery->voltage_k = (4025 - 2300) * 1000 / ((vcalib1 - vcalib0) ? (vcalib1 - vcalib0) : 1);
+	battery->voltage_b = 4025 - (battery->voltage_k * vcalib1) / 1000;
+
+}
+
+static void rk817_bat_calib_cur(struct rk817_bat *battery)
+{
+	int ioffset = 0;
+	/* calibrate current */
+	ioffset = rk817_get_reg_hl(battery, RK817_GAS_GAUGE_IOFFSET_H, RK817_GAS_GAUGE_IOFFSET_H);
+	rk817_write_reg_hl(battery, RK817_GAS_GAUGE_CAL_OFFSET_H, RK817_GAS_GAUGE_CAL_OFFSET_L, ioffset);
+}
+
+static int rk817_bat_get_prop(struct power_supply *ps,
+		enum power_supply_property prop,
+		union power_supply_propval *val)
+{
+	struct rk817_bat *battery = power_supply_get_drvdata(ps);
+	uint32_t tmp = 0;
+	int ret = 0;
+	int reg = 0;
+	struct rk808 *rk808 = battery->rk808;
+
+	/* recalibrate voltage and current readings if we need to */
+	/* BSP does both on CUR_CALIB_UPD, ignoring VOL_CALIB_UPD */
+	regmap_read(rk808->regmap, RK817_GAS_GAUGE_ADC_CONFIG1, ®);
+	tmp = (reg >> 7) & RK817_CUR_CALIB_UPD;
+	if (tmp == 0)
+	{
+		rk817_bat_calib_vol(battery);
+		rk817_bat_calib_cur(battery);
+		regmap_update_bits(rk808->regmap, RK817_GAS_GAUGE_ADC_CONFIG1,  RK817_CUR_CALIB_UPD, 1);
+	}
+
+	switch (prop) {
+		case POWER_SUPPLY_PROP_STATUS:
+			ret = regmap_read(rk808->regmap, RK817_PMIC_CHRG_STS, ®);
+			if (ret)
+				return ret;
+			tmp = (reg >> 4) & RK817_CHG_STS;
+			switch(tmp) {
+				case CHRG_OFF:
+					val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+					break;
+				case DEAD_CHRG:
+					val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+					break;
+				case TRICKLE_CHRG:
+				case CC_OR_CV_CHRG:
+					val->intval = POWER_SUPPLY_STATUS_CHARGING;
+					break;
+				case CHARGE_FINISH:
+					val->intval = POWER_SUPPLY_STATUS_FULL;
+					break;
+				default:
+					val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+					printk("Error getting battery value");
+					return -EINVAL;
+
+			}
+			break;
+		case POWER_SUPPLY_PROP_CHARGE_TYPE:
+			ret = regmap_read(rk808->regmap, RK817_PMIC_CHRG_STS, ®);
+			if (ret)
+				return ret;
+			tmp = (reg >> 4) & RK817_CHG_STS;
+			switch(tmp) {
+				case CHRG_OFF:
+				case DEAD_CHRG:
+					val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+					break;
+				case TRICKLE_CHRG:
+					val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+					break;
+				case CC_OR_CV_CHRG:
+					val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+					break;
+				default:
+					val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+					break;
+			}
+			break;
+		case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+			val->intval = battery->info.voltage_min_design_uv;
+			break;
+		case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+			tmp = rk817_get_reg_hl(battery, RK817_GAS_GAUGE_BAT_VOL_H, RK817_GAS_GAUGE_BAT_VOL_L);
+			val->intval = 1000 * ((battery->voltage_k * tmp) / (1000 + battery->voltage_b));
+			break;
+		case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+			val->intval = battery->info.voltage_max_design_uv;
+			break;
+		default:
+			return -EINVAL;
+	}
+	return 0;
+}
+
+
+
+static enum power_supply_property rk817_bat_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_CHARGE_TYPE,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+};
+
+static const struct power_supply_desc rk817_desc = {
+	.name = "rk817-battery",
+	.type = POWER_SUPPLY_TYPE_BATTERY,
+	.properties = rk817_bat_props,
+	.num_properties = ARRAY_SIZE(rk817_bat_props),
+	.get_property = rk817_bat_get_prop,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id rk817_bat_of_match[] = {
+	{ .compatible = "rk817,battery", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, rk817_bat_of_match);
+#endif
+
+static int rk817_bat_probe(struct platform_device *pdev)
+{
+	struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
+	struct rk817_bat *battery;
+	struct device *dev = &pdev->dev;
+	struct power_supply_config pscfg = {};
+	int ret;
+
+	if (!of_device_is_available(pdev->dev.of_node))
+		return -ENODEV;
+
+	battery = devm_kzalloc(&pdev->dev, sizeof(battery), GFP_KERNEL);
+	if (!battery)
+		return -ENOMEM;
+
+	battery->rk808 = rk808;
+
+	battery->dev = &pdev->dev;
+	platform_set_drvdata(pdev, battery);
+
+	rk817_bat_calib_vol(battery);
+
+	pscfg.drv_data = battery;
+	pscfg.of_node = pdev->dev.of_node;
+
+	/* some boards may use different values for sample resistor */
+	ret = of_property_read_u32(pdev->dev.of_node, "sample_res", &battery->sample_res);
+	if (ret < 0)
+		dev_err(dev, "Error reading sample_res");
+	battery->res_div = (battery->sample_res == 20) ? 1 : 2;
+
+	battery->bat_ps = devm_power_supply_register(&pdev->dev, &rk817_desc, &pscfg);
+
+	ret = power_supply_get_battery_info(battery->bat_ps, &battery->info);
+	if (ret) {
+		dev_err(dev, "Unable to get battery info: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+
+static struct platform_driver rk817_bat_driver = {
+	.probe    = rk817_bat_probe,
+	.driver   = {
+		.name  = "rk817-battery",
+		.of_match_table = rk817_bat_of_match,
+	},
+};
+module_platform_driver(rk817_bat_driver);
+
+MODULE_DESCRIPTION("Battery power supply driver for RK817 PMIC");
+MODULE_AUTHOR("Maciej Matuszczyk ");
+MODULE_LICENSE("GPL");
+
diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h
index a96e6d43ca06..1efa37017c04 100644
--- a/include/linux/mfd/rk808.h
+++ b/include/linux/mfd/rk808.h
@@ -495,6 +495,34 @@ enum rk809_reg_id {
 #define RK817_CODEC_DI2S_TXCR2		0x4e
 #define RK817_CODEC_DI2S_TXCR3_TXCMD	0x4f
 
+/* RK817 Battery Registers */
+#define RK817_GAS_GAUGE_ADC_CONFIG0	0x50
+#define RK817_GAS_GAUGE_ADC_CONFIG1	0x55
+
+#define RK817_CUR_CALIB_UPD		(0x1 << 7)
+#define RK817_VOL_CALIB_UPD		(0x1 << 6)
+
+#define RK817_GAS_GAUGE_OCV_THRE_VOL	0x62
+#define RK817_GAS_GAUGE_OCV_VOL_H	0x63
+#define RK817_GAS_GAUGE_OCV_VOL_L	0x64
+#define RK817_GAS_GAUGE_Q_PRES_H3	0x74
+#define RK817_GAS_GAUGE_Q_PRES_H2	0x75
+#define RK817_GAS_GAUGE_Q_PRES_L1	0x76
+#define RK817_GAS_GAUGE_Q_PRES_L0	0x77
+#define RK817_GAS_GAUGE_BAT_VOL_H	0x78
+#define RK817_GAS_GAUGE_BAT_VOL_L	0x79
+#define RK817_GAS_GAUGE_SYS_VOL_H	0x80
+#define RK817_GAS_GAUGE_SYS_VOL_L	0x81
+#define RK817_GAS_GAUGE_CAL_OFFSET_H	0x91
+#define RK817_GAS_GAUGE_CAL_OFFSET_L	0x92
+#define RK817_GAS_GAUGE_VCALIB0_H	0x93
+#define RK817_GAS_GAUGE_VCALIB0_L	0x94
+#define RK817_GAS_GAUGE_VCALIB1_H	0x95
+#define RK817_GAS_GAUGE_VCALIB1_L	0x96
+#define RK817_GAS_GAUGE_IOFFSET_H	0x97
+#define RK817_GAS_GAUGE_IOFFSET_L	0x98
+#define RK817_GAS_GAUGE_CUR_ADC_K0	0xb0
+
 /* RK817_CODEC_DI2S_CKM */
 #define RK817_I2S_MODE_MASK		(0x1 << 0)
 #define RK817_I2S_MODE_MST		(0x1 << 0)
@@ -543,6 +571,12 @@ enum rk809_reg_id {
 #define RK817_LDO_ON_VSEL_REG(idx)	(0xcc + (idx) * 2)
 #define RK817_BOOST_OTG_CFG		(0xde)
 
+#define RK817_PMIC_CHRG_OUT		0xe4
+#define RK817_PMIC_CHRG_IN		0xe5
+#define RK817_PMIC_CHRG_STS		0xeb
+
+#define RK817_CHG_STS			(0x07 << 4)
+
 #define RK817_ID_MSB			0xed
 #define RK817_ID_LSB			0xee
 
-- 
2.25.1

Leave a Reply

Your email address will not be published. Required fields are marked *