[RK3399][Android7.1] 移植筆記 — 偽電池驅動新增

NO IMAGE

Platform: RK3399
OS: Android 7.1
Kernel: v4.4.83

原因:

由於電池是外接到其他平臺,rk3399在拿到電量資訊之後需要更新到系統中,
因此寫了個偽電池驅動,來適配此需求。

改動:

DTS:

diff --git a/arch/arm64/boot/dts/rockchip/rk3399-eco.dts b/arch/arm64/boot/dts/rockchip/rk3399-eco.dts
index e39f165..2975223 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-eco.dts
b/arch/arm64/boot/dts/rockchip/rk3399-eco.dts
@@ -229,6  229,12 @@
//Kris,180706, porting rt5640 on i2s1.
status = "disabled";
};
//Kris, 180709, Add pseudo battery driver.
pseudo-battery {
compatible = "eco,battery";
status = "okay";
};
};
&rk_key {
@@ -313,6  319,7 @@
status = "okay";
};
//Kris,180709, add support for eth.
&gmac {
phy-supply = <&vcc_phy>;

Makefile:

diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 823d26a..3edd872 100644
--- a/drivers/power/Makefile
b/drivers/power/Makefile
@@ -77,4  77,8 @@ obj-$(CONFIG_CHARGER_TPS65090)    = tps65090-charger.o
obj-$(CONFIG_CHARGER_TPS65217)     = tps65217_charger.o
obj-$(CONFIG_POWER_RESET)  = reset/
obj-$(CONFIG_AXP288_FUEL_GAUGE)  = axp288_fuel_gauge.o
obj-$(CONFIG_AXP288_CHARGER)   = axp288_charger.o
#Kris, 180709, add pseudo battery driver.
obj-y   = eco_battery.o

電池驅動:

/* drivers/power/eco_battery.c
*
* Power supply driver for the eco_rk3399
*
* Copyright (C) 2008 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include<linux/timer.h>
#include <linux/slab.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/of.h>
#include <linux/of_device.h>
struct eco_rk3399_battery_data {
int status;
int health;
int present;
int capacity;
struct power_supply *battery;
};
static enum power_supply_property eco_rk3399_battery_props[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_CAPACITY,
};
static int eco_rk3399_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
struct eco_rk3399_battery_data *data = power_supply_get_drvdata(psy);
int ret = 0;
//printk("get property: %d \n",  psp);
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
val->intval = data->status;
break;
case POWER_SUPPLY_PROP_HEALTH:
val->intval = data->health ;
break;
case POWER_SUPPLY_PROP_PRESENT:
val->intval = data->present ;
break;
case POWER_SUPPLY_PROP_TECHNOLOGY:
val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
break;
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = data->capacity ;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static int eco_rk3399_battery_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{
struct eco_rk3399_battery_data *data = power_supply_get_drvdata(psy);
int ret = 0;
int value = val->intval;
//printk("[Battery]set property:%d val:%d\n", psp, value);
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
if (value <= POWER_SUPPLY_STATUS_FULL) {
data->status =value;
} else {
printk("Unreasonable value:%d\n", value);
ret = 1;
}
break;
case POWER_SUPPLY_PROP_HEALTH:
if (value <= POWER_SUPPLY_HEALTH_COLD) {
data->health = value;
} else {
printk("Unreasonable value:%d\n", value);
ret = 1;
}
break;
case POWER_SUPPLY_PROP_PRESENT:
data->present = value;
break;
case POWER_SUPPLY_PROP_CAPACITY:
//Capacity from 0 to 100.
if (value > 0 && value <= 100) {
data->capacity = value;
} else {
printk("Unreasonable value:%d\n", value);
ret = 1;
}
break;
default:
ret = -EINVAL;
break;
}
//Send uevent.
power_supply_changed(data->battery);
return ret;
}
static int eco_rk3399_battery_is_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
switch (psp) {
//Need to be written from medusa service.
case POWER_SUPPLY_PROP_CAPACITY:
case POWER_SUPPLY_PROP_STATUS:
case POWER_SUPPLY_PROP_PRESENT:
case POWER_SUPPLY_PROP_HEALTH:
return 1;
default:
break;
}
return 0;
}
struct power_supply_config psy_cfg;
struct power_supply_desc eco_bat_desc;
static int eco_rk3399_battery_probe(struct platform_device *pdev)
{
int ret;
struct eco_rk3399_battery_data *data;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL) {
ret = -ENOMEM;
goto err_data_alloc_failed;
}
eco_bat_desc.properties = eco_rk3399_battery_props;
eco_bat_desc.num_properties = ARRAY_SIZE(eco_rk3399_battery_props);
eco_bat_desc.get_property = eco_rk3399_battery_get_property;
eco_bat_desc.name = "battery";
eco_bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
eco_bat_desc.set_property = eco_rk3399_battery_set_property;
eco_bat_desc.property_is_writeable = eco_rk3399_battery_is_writeable;
data->present = 1;  //Present
data->status = POWER_SUPPLY_STATUS_UNKNOWN;
data->health = POWER_SUPPLY_HEALTH_GOOD;
data ->capacity = 1;
psy_cfg.drv_data = data;
data->battery= power_supply_register(&pdev->dev, &eco_bat_desc, &psy_cfg);
if (IS_ERR(data->battery))
goto err_battery_failed;
platform_set_drvdata(pdev, data);
return 0;
err_battery_failed:
kfree(data);
err_data_alloc_failed:
return ret;
}
static int eco_rk3399_battery_remove(struct platform_device *pdev)
{
struct eco_rk3399_battery_data *data = platform_get_drvdata(pdev);
power_supply_unregister(data->battery);
kfree(data);
return 0;
}
static const struct of_device_id eco_rk3399_battery[] = {
{ .compatible = "eco,battery" },
{ /* Sentinel */ }
};
static struct platform_driver eco_rk3399_battery_driver = {
.probe      = eco_rk3399_battery_probe,
.remove     = eco_rk3399_battery_remove,
.driver = {
.owner = THIS_MODULE,
.name = "eco-battery",
.of_match_table = of_match_ptr(eco_rk3399_battery),
}
};
static int __init eco_rk3399_battery_init(void)
{
return platform_driver_register(&eco_rk3399_battery_driver);
}
static void __exit eco_rk3399_battery_exit(void)
{
platform_driver_unregister(&eco_rk3399_battery_driver);
}
module_init(eco_rk3399_battery_init);
module_exit(eco_rk3399_battery_exit);
MODULE_AUTHOR("[email protected]");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Battery driver for RK3399");