Created
May 5, 2021 02:50
-
-
Save macromorgan/95099bf2d43b395ad68301e30c83aac6 to your computer and use it in GitHub Desktop.
Updated macc24's battery driver
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| From 786be1506dbf839f9d93b2613c26221a067f202c Mon Sep 17 00:00:00 2001 | |
| From: Chris Morgan <macromorgan@hotmail.com> | |
| 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 <linux/delay.h> | |
| +#include <linux/extcon.h> | |
| +#include <linux/fb.h> | |
| +#include <linux/gpio.h> | |
| +#include <linux/iio/consumer.h> | |
| +#include <linux/iio/iio.h> | |
| +#include <linux/irq.h> | |
| +#include <linux/jiffies.h> | |
| +#include <linux/mfd/rk808.h> | |
| +#include <linux/module.h> | |
| +#include <linux/of_device.h> | |
| +#include <linux/of_gpio.h> | |
| +#include <linux/platform_device.h> | |
| +#include <linux/regmap.h> | |
| +#include <linux/rtc.h> | |
| +#include <linux/timer.h> | |
| +#include <linux/workqueue.h> | |
| +#include <linux/power_supply.h> | |
| + | |
| +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 <maccraft123mc@gmail.com>"); | |
| +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 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment