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
[url=home.php?mod=space&uid=1999721]@@[/url] -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("kris_fei@126.com");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Battery driver for RK3399");
原作者:KrisFei
更多回帖