cregit-Linux how code gets into the kernel

Release 4.7 drivers/power/z2_battery.c

Directory: drivers/power
/*
 * Battery measurement code for Zipit Z2
 *
 * Copyright (C) 2009 Peter Edwards <sweetlilmre@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */

#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/power_supply.h>
#include <linux/slab.h>
#include <linux/z2_battery.h>


#define	Z2_DEFAULT_NAME	"Z2"


struct z2_charger {
	
struct z2_battery_info		*info;
	
int				bat_status;
	
struct i2c_client		*client;
	
struct power_supply		*batt_ps;
	
struct power_supply_desc	batt_ps_desc;
	
struct mutex			work_lock;
	
struct work_struct		bat_work;
};


static unsigned long z2_read_bat(struct z2_charger *charger) { int data; data = i2c_smbus_read_byte_data(charger->client, charger->info->batt_I2C_reg); if (data < 0) return 0; return data * charger->info->batt_mult / charger->info->batt_div; }

Contributors

PersonTokensPropCommitsCommitProp
marek vasutmarek vasut54100.00%1100.00%
Total54100.00%1100.00%


static int z2_batt_get_property(struct power_supply *batt_ps, enum power_supply_property psp, union power_supply_propval *val) { struct z2_charger *charger = power_supply_get_drvdata(batt_ps); struct z2_battery_info *info = charger->info; switch (psp) { case POWER_SUPPLY_PROP_STATUS: val->intval = charger->bat_status; break; case POWER_SUPPLY_PROP_TECHNOLOGY: val->intval = info->batt_tech; break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: if (info->batt_I2C_reg >= 0) val->intval = z2_read_bat(charger); else return -EINVAL; break; case POWER_SUPPLY_PROP_VOLTAGE_MAX: if (info->max_voltage >= 0) val->intval = info->max_voltage; else return -EINVAL; break; case POWER_SUPPLY_PROP_VOLTAGE_MIN: if (info->min_voltage >= 0) val->intval = info->min_voltage; else return -EINVAL; break; case POWER_SUPPLY_PROP_PRESENT: val->intval = 1; break; default: return -EINVAL; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
marek vasutmarek vasut16299.39%150.00%
krzysztof kozlowskikrzysztof kozlowski10.61%150.00%
Total163100.00%2100.00%


static void z2_batt_ext_power_changed(struct power_supply *batt_ps) { struct z2_charger *charger = power_supply_get_drvdata(batt_ps); schedule_work(&charger->bat_work); }

Contributors

PersonTokensPropCommitsCommitProp
marek vasutmarek vasut2896.55%150.00%
krzysztof kozlowskikrzysztof kozlowski13.45%150.00%
Total29100.00%2100.00%


static void z2_batt_update(struct z2_charger *charger) { int old_status = charger->bat_status; struct z2_battery_info *info; info = charger->info; mutex_lock(&charger->work_lock); charger->bat_status = (info->charge_gpio >= 0) ? (gpio_get_value(info->charge_gpio) ? POWER_SUPPLY_STATUS_CHARGING : POWER_SUPPLY_STATUS_DISCHARGING) : POWER_SUPPLY_STATUS_UNKNOWN; if (old_status != charger->bat_status) { pr_debug("%s: %i -> %i\n", charger->batt_ps->desc->name, old_status, charger->bat_status); power_supply_changed(charger->batt_ps); } mutex_unlock(&charger->work_lock); }

Contributors

PersonTokensPropCommitsCommitProp
marek vasutmarek vasut10597.22%150.00%
krzysztof kozlowskikrzysztof kozlowski32.78%150.00%
Total108100.00%2100.00%


static void z2_batt_work(struct work_struct *work) { struct z2_charger *charger; charger = container_of(work, struct z2_charger, bat_work); z2_batt_update(charger); }

Contributors

PersonTokensPropCommitsCommitProp
marek vasutmarek vasut33100.00%1100.00%
Total33100.00%1100.00%


static irqreturn_t z2_charge_switch_irq(int irq, void *devid) { struct z2_charger *charger = devid; schedule_work(&charger->bat_work); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
marek vasutmarek vasut31100.00%1100.00%
Total31100.00%1100.00%


static int z2_batt_ps_init(struct z2_charger *charger, int props) { int i = 0; enum power_supply_property *prop; struct z2_battery_info *info = charger->info; if (info->charge_gpio >= 0) props++; /* POWER_SUPPLY_PROP_STATUS */ if (info->batt_tech >= 0) props++; /* POWER_SUPPLY_PROP_TECHNOLOGY */ if (info->batt_I2C_reg >= 0) props++; /* POWER_SUPPLY_PROP_VOLTAGE_NOW */ if (info->max_voltage >= 0) props++; /* POWER_SUPPLY_PROP_VOLTAGE_MAX */ if (info->min_voltage >= 0) props++; /* POWER_SUPPLY_PROP_VOLTAGE_MIN */ prop = kzalloc(props * sizeof(*prop), GFP_KERNEL); if (!prop) return -ENOMEM; prop[i++] = POWER_SUPPLY_PROP_PRESENT; if (info->charge_gpio >= 0) prop[i++] = POWER_SUPPLY_PROP_STATUS; if (info->batt_tech >= 0) prop[i++] = POWER_SUPPLY_PROP_TECHNOLOGY; if (info->batt_I2C_reg >= 0) prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_NOW; if (info->max_voltage >= 0) prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_MAX; if (info->min_voltage >= 0) prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_MIN; if (!info->batt_name) { dev_info(&charger->client->dev, "Please consider setting proper battery " "name in platform definition file, falling " "back to name \" Z2_DEFAULT_NAME \"\n"); charger->batt_ps_desc.name = Z2_DEFAULT_NAME; } else charger->batt_ps_desc.name = info->batt_name; charger->batt_ps_desc.properties = prop; charger->batt_ps_desc.num_properties = props; charger->batt_ps_desc.type = POWER_SUPPLY_TYPE_BATTERY; charger->batt_ps_desc.get_property = z2_batt_get_property; charger->batt_ps_desc.external_power_changed = z2_batt_ext_power_changed; charger->batt_ps_desc.use_for_apm = 1; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
marek vasutmarek vasut27893.29%133.33%
vasily khoruzhickvasily khoruzhick124.03%133.33%
krzysztof kozlowskikrzysztof kozlowski82.68%133.33%
Total298100.00%3100.00%


static int z2_batt_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = 0; int props = 1; /* POWER_SUPPLY_PROP_PRESENT */ struct z2_charger *charger; struct z2_battery_info *info = client->dev.platform_data; struct power_supply_config psy_cfg = {}; if (info == NULL) { dev_err(&client->dev, "Please set platform device platform_data" " to a valid z2_battery_info pointer!\n"); return -EINVAL; } charger = kzalloc(sizeof(*charger), GFP_KERNEL); if (charger == NULL) return -ENOMEM; charger->bat_status = POWER_SUPPLY_STATUS_UNKNOWN; charger->info = info; charger->client = client; i2c_set_clientdata(client, charger); psy_cfg.drv_data = charger; mutex_init(&charger->work_lock); if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio)) { ret = gpio_request(info->charge_gpio, "BATT CHRG"); if (ret) goto err; ret = gpio_direction_input(info->charge_gpio); if (ret) goto err2; irq_set_irq_type(gpio_to_irq(info->charge_gpio), IRQ_TYPE_EDGE_BOTH); ret = request_irq(gpio_to_irq(info->charge_gpio), z2_charge_switch_irq, 0, "AC Detect", charger); if (ret) goto err3; } ret = z2_batt_ps_init(charger, props); if (ret) goto err3; INIT_WORK(&charger->bat_work, z2_batt_work); charger->batt_ps = power_supply_register(&client->dev, &charger->batt_ps_desc, &psy_cfg); if (IS_ERR(charger->batt_ps)) { ret = PTR_ERR(charger->batt_ps); goto err4; } schedule_work(&charger->bat_work); return 0; err4: kfree(charger->batt_ps_desc.properties); err3: if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio)) free_irq(gpio_to_irq(info->charge_gpio), charger); err2: if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio)) gpio_free(info->charge_gpio); err: kfree(charger); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
marek vasutmarek vasut34089.71%120.00%
krzysztof kozlowskikrzysztof kozlowski379.76%240.00%
yong zhangyong zhang10.26%120.00%
thomas gleixnerthomas gleixner10.26%120.00%
Total379100.00%5100.00%


static int z2_batt_remove(struct i2c_client *client) { struct z2_charger *charger = i2c_get_clientdata(client); struct z2_battery_info *info = charger->info; cancel_work_sync(&charger->bat_work); power_supply_unregister(charger->batt_ps); kfree(charger->batt_ps_desc.properties); if (info->charge_gpio >= 0 && gpio_is_valid(info->charge_gpio)) { free_irq(gpio_to_irq(info->charge_gpio), charger); gpio_free(info->charge_gpio); } kfree(charger); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
marek vasutmarek vasut9091.84%133.33%
tejun heotejun heo77.14%133.33%
krzysztof kozlowskikrzysztof kozlowski11.02%133.33%
Total98100.00%3100.00%

#ifdef CONFIG_PM
static int z2_batt_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct z2_charger *charger = i2c_get_clientdata(client); flush_work(&charger->bat_work); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
marek vasutmarek vasut2559.52%250.00%
tejun heotejun heo1740.48%250.00%
Total42100.00%4100.00%


static int z2_batt_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct z2_charger *charger = i2c_get_clientdata(client); schedule_work(&charger->bat_work); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
marek vasutmarek vasut42100.00%2100.00%
Total42100.00%2100.00%

static const struct dev_pm_ops z2_battery_pm_ops = { .suspend = z2_batt_suspend, .resume = z2_batt_resume, }; #define Z2_BATTERY_PM_OPS (&z2_battery_pm_ops) #else #define Z2_BATTERY_PM_OPS (NULL) #endif static const struct i2c_device_id z2_batt_id[] = { { "aer915", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, z2_batt_id); static struct i2c_driver z2_batt_driver = { .driver = { .name = "z2-battery", .owner = THIS_MODULE, .pm = Z2_BATTERY_PM_OPS }, .probe = z2_batt_probe, .remove = z2_batt_remove, .id_table = z2_batt_id, }; module_i2c_driver(z2_batt_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Peter Edwards <sweetlilmre@gmail.com>"); MODULE_DESCRIPTION("Zipit Z2 battery driver");

Overall Contributors

PersonTokensPropCommitsCommitProp
marek vasutmarek vasut135792.95%325.00%
krzysztof kozlowskikrzysztof kozlowski563.84%216.67%
tejun heotejun heo241.64%216.67%
vasily khoruzhickvasily khoruzhick120.82%18.33%
axel linaxel lin90.62%216.67%
yong zhangyong zhang10.07%18.33%
thomas gleixnerthomas gleixner10.07%18.33%
Total1460100.00%12100.00%
Directory: drivers/power
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}