[RK3399][Android7.1] 移植笔记 --- 伪电池驱动添加

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");

猜你喜欢

转载自blog.csdn.net/kris_fei/article/details/80981864