linux 电源管理驱动编写

执行流程

驱动结构

1) 内核提供的接口

struct power_supply 在文件 include\linux\power_supply.h 中

2) 提供给用户的接口

sys/class/power_supply

通过 drivers\power\power_supply_core.c 中的

int power_supply_register(struct device *parent,struct power_supply *psy)

来创建.

power_supply_register() 在 K:\linux学习资料\bible\驱动程序开发\电源电池管理\电源电池管理.pdf中介绍

当电源变化时,调用:drivers\power\power_supply_core.c 中的

power_supply_changed()更新sysfs文件系统中的信息.

把握以上两点!


1. 填充 struct power_supply

路径include/linux/power_supply.h

1.) 结构体含义

struct power_supply {

const char *name;               // 名字,例如"usb", "battary", "ac" 

enum power_supply_type type;    // 电源类型,power_supply.h定义,分为usb,battery,ups,mains四种

enum power_supply_property *properties;  // 电源属性,比较多,常用的在后面介绍.枚举类型数组

size_t num_properties;            // 属性数量,假设为3,则回调get_property()3

char **supplied_to;

size_t num_supplicants;

int (*get_property)(struct power_supply *psy,        // 回调函数,执行power_supply_changed()后被

    enum power_supply_property psp,     // 调用,调用次数由num_properties决定

    union power_supply_propval *val);

int (*set_property)(struct power_supply *psy,

    enum power_supply_property psp,

    const union power_supply_propval *val);

int (*property_is_writeable)(struct power_supply *psy,

     enum power_supply_property psp);

void (*external_power_changed)(struct power_supply *psy);

void (*set_charged)(struct power_supply *psy);

/* For APM emulation, think legacy userspace. */

int use_for_apm;

/* private */

struct device *dev;

struct work_struct changed_work;    // 工作队列,相当于一个线程,由它发起power_supply_changed()

spinlock_t changed_lock;

bool changed;

struct wake_lock work_wake_lock;

#ifdef CONFIG_LEDS_TRIGGERS

struct led_trigger *charging_full_trig;

char *charging_full_trig_name;

struct led_trigger *charging_trig;

char *charging_trig_name;

struct led_trigger *full_trig;

char *full_trig_name;

struct led_trigger *online_trig;

char *online_trig_name;

#endif

};

2) 常用的power_supply_propety

android下用到的:

# cat /sys/class/power_supply/ac/type

Mains

# cat /sys/class/power_supply/ac/online

1

# cd /sys/class/power_supply/battery/

# cat type status health present technology capacity

Battery

Charging

Good

1

Li-ion

50

这些宏已经定义过:

enum { // 对应 POWER_SUPPLY_PROP_STATUS

       POWER_SUPPLY_STATUS_UNKNOWN = 0,

       POWER_SUPPLY_STATUS_CHARGING,

       POWER_SUPPLY_STATUS_DISCHARGING,

       POWER_SUPPLY_STATUS_NOT_CHARGING,

       POWER_SUPPLY_STATUS_FULL,

};

enum {   // 对应 POWER_SUPPLY_PROP_CHARGE_TYPE

       POWER_SUPPLY_CHARGE_TYPE_UNKNOWN = 0,

       POWER_SUPPLY_CHARGE_TYPE_NONE,

       POWER_SUPPLY_CHARGE_TYPE_TRICKLE,

       POWER_SUPPLY_CHARGE_TYPE_FAST,

};

enum { // 对应 POWER_SUPPLY_PROP_HEALTH

       POWER_SUPPLY_HEALTH_UNKNOWN = 0,

       POWER_SUPPLY_HEALTH_GOOD,

       POWER_SUPPLY_HEALTH_OVERHEAT,

       POWER_SUPPLY_HEALTH_DEAD,

       POWER_SUPPLY_HEALTH_OVERVOLTAGE,

       POWER_SUPPLY_HEALTH_UNSPEC_FAILURE,

       POWER_SUPPLY_HEALTH_COLD,

};

enum {  // 对应 POWER_SUPPLY_PROP_TECHNOLOGY

       POWER_SUPPLY_TECHNOLOGY_UNKNOWN = 0,

       POWER_SUPPLY_TECHNOLOGY_NiMH,

       POWER_SUPPLY_TECHNOLOGY_LION,

       POWER_SUPPLY_TECHNOLOGY_LIPO,

       POWER_SUPPLY_TECHNOLOGY_LiFe,

       POWER_SUPPLY_TECHNOLOGY_NiCd,

       POWER_SUPPLY_TECHNOLOGY_LiMn,

};

enum { // 对应 POWER_SUPPLY_PROP_CAPACITY_LEVEL 

       POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN = 0,

       POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL,

       POWER_SUPPLY_CAPACITY_LEVEL_LOW,

       POWER_SUPPLY_CAPACITY_LEVEL_NORMAL,

       POWER_SUPPLY_CAPACITY_LEVEL_HIGH,

       POWER_SUPPLY_CAPACITY_LEVEL_FULL,

};

一个struct power_supply的例子:

struct max17040_chip {

        struct power_supply             battery;      // 三种供电方式

        struct power_supply             ac;

        struct power_supply             usb;

        struct timespec         next_update_time;

        struct delayed_work             work;     // 两个队列

struct delayed_work battary_vol_state_wq;

        /* State Of Connect */

        int online;

        /* battery voltage */

        int vcell;

        /* battery capacity */

        int soc;

        /* State Of Charge */

        int status;

        /* usb online */

        int usb_online;

};

struct max17040_chip *chip;

初始化:

        chip->battery.name              = "battery";

        chip->battery.type              = POWER_SUPPLY_TYPE_BATTERY; 

        chip->battery.get_property      = max17040_get_property;  // 回调函数,执行power_supply_changed()后被调用,调用次数由battery.num_properties决定, 函数内容在下面.

        chip->battery.properties        = max17040_battery_props;  // 内容在下面

        chip->battery.num_properties    = ARRAY_SIZE(max17040_battery_props);

        chip->battery.external_power_changed = NULL;

        chip->ac.name           = "ac";

        chip->ac.type           = POWER_SUPPLY_TYPE_MAINS;

        chip->ac.get_property   = adapter_get_property;

        chip->ac.properties     = adapter_get_props;

        chip->ac.num_properties = ARRAY_SIZE(adapter_get_props);

        chip->ac.external_power_changed = NULL;

        chip->usb.name          = "usb";

        chip->usb.type          = POWER_SUPPLY_TYPE_USB;

        chip->usb.get_property  = usb_get_property;

        chip->usb.properties    = usb_get_props;

        chip->usb.num_properties        = ARRAY_SIZE(usb_get_props);

        chip->usb.external_power_changed = NULL;

// 两个队列

        INIT_DELAYED_WORK_DEFERRABLE(&chip->work, work_max17040);

        INIT_DELAYED_WORK_DEFERRABLE(&chip->battary_vol_state_wq, work_battary_vol_sample);

        schedule_delayed_work(&chip->work, MAX17040_DELAY);

        schedule_delayed_work(&chip->battary_vol_state_wq, POLLING_BATTARY_VOL_MSEC);

max17040_battery_props[] 枚举类型数组内容

static enum power_supply_property max17040_battery_props[] = {   // 一共有7,

                                           // 意味着max17040_get_property()将被回调7

        POWER_SUPPLY_PROP_PRESENT,

        POWER_SUPPLY_PROP_STATUS,

        /*POWER_SUPPLY_PROP_ONLINE,*/

        POWER_SUPPLY_PROP_VOLTAGE_NOW,

        POWER_SUPPLY_PROP_CAPACITY,

        POWER_SUPPLY_PROP_TECHNOLOGY,

        POWER_SUPPLY_PROP_HEALTH,

        POWER_SUPPLY_PROP_TEMP,

};

max17040_get_property() 函数:

static int max17040_get_property(struct power_supply *psy,

                            enum power_supply_property psp,

                            union power_supply_propval *val)

{

  dev_info(dev,"%s \n", __func__);

  

        switch (psp) {       // 一共有7, 将被回调7执行power_supply_changed()后被回调.                   

        case POWER_SUPPLY_PROP_STATUS:

                val->intval = chip->status;

                break;

        case POWER_SUPPLY_PROP_ONLINE:

                val->intval = 1;

                break;

        case POWER_SUPPLY_PROP_VOLTAGE_NOW:

        case POWER_SUPPLY_PROP_PRESENT:

                val->intval = 3800;//chip->vcell;

                if(psp  == POWER_SUPPLY_PROP_PRESENT)

                        val->intval = 1; /* You must never run Odrioid1 without Battery. */

                break;

        case POWER_SUPPLY_PROP_CAPACITY:

                val->intval = 80;//chip->soc;

                break;

         case POWER_SUPPLY_PROP_TECHNOLOGY:

                val->intval = POWER_SUPPLY_TECHNOLOGY_LION;

                break;

         case POWER_SUPPLY_PROP_HEALTH:

//              if(chip->vcell  < 2850)

//                      val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;

//              else

                         val->intval = POWER_SUPPLY_HEALTH_GOOD;

                break;

        case POWER_SUPPLY_PROP_TEMP:

                break;

        default:

                return -EINVAL;

        }

        return 0;

}

work_queue队列

static void work_max17040(struct work_struct *work)

{

        int old_usb_online, old_online, old_vcell, old_soc;

int vol, level;

        old_online = chip->online;

        old_usb_online = chip->usb_online;

        old_vcell = chip->vcell;

        old_soc = chip->soc;

        max17040_update_values();

vol = battary_vol_average();

printk("+++ %s: vol = %d \n", __func__, vol);

level = battary_level(vol);

dev_info(dev,"%s, level = %d \n", __func__, level);

//      s3c_get_bat_level();

/*

        if((old_vcell != chip->vcell) || (old_soc != chip->soc))

                power_supply_changed(&chip->battery);

        if(old_usb_online != chip->usb_online)

                power_supply_changed(&chip->usb);

        if(old_online != chip->online)

                power_supply_changed(&chip->ac);

*/

        power_supply_changed(&chip->ac);    // 回调ac 中的get_property()

// for test

power_supply_changed(&chip->battery);  // 回调battery中的get_property()

power_supply_changed(&chip->usb);  // 回调usb中的get_property()

//

        schedule_delayed_work(&chip->work, MAX17040_DELAY);

}


你可能感兴趣的:(linux)