linux 电源管理驱动编写

2019-07-13 22:14发布

执行流程






驱动结构


1) 内核提供的接口


struct power_supply 在文件 includelinuxpower_supply.h 中


2) 提供给用户的接口


sys/class/power_supply


通过 driverspowerpower_supply_core.c 中的


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


来创建.


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


当电源变化时,调用:driverspowerpower_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 ", __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 ", __func__, vol);


level = battary_level(vol);


dev_info(dev,"%s, level = %d ", __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);


}