Separate out I2C functionality into a module. This fixes several small issues and simplifies the driver initialization. Signed-off-by: Andrew F. Davis <afd@ti.com> Signed-off-by: Sebastian Reichel <sre@kernel.org>tirimbino
parent
1f94b2563a
commit
703df6c097
@ -0,0 +1,150 @@ |
||||
/*
|
||||
* SCI Reset driver for Keystone based devices |
||||
* |
||||
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Andrew F. Davis <afd@ti.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. |
||||
* |
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any |
||||
* kind, whether express or implied; without even the implied warranty |
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
*/ |
||||
|
||||
#include <linux/i2c.h> |
||||
#include <linux/interrupt.h> |
||||
#include <linux/module.h> |
||||
#include <asm/unaligned.h> |
||||
|
||||
#include <linux/power/bq27xxx_battery.h> |
||||
|
||||
static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data) |
||||
{ |
||||
struct bq27xxx_device_info *di = data; |
||||
|
||||
bq27xxx_battery_update(di); |
||||
|
||||
return IRQ_HANDLED; |
||||
} |
||||
|
||||
static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg, |
||||
bool single) |
||||
{ |
||||
struct i2c_client *client = to_i2c_client(di->dev); |
||||
struct i2c_msg msg[2]; |
||||
unsigned char data[2]; |
||||
int ret; |
||||
|
||||
if (!client->adapter) |
||||
return -ENODEV; |
||||
|
||||
msg[0].addr = client->addr; |
||||
msg[0].flags = 0; |
||||
msg[0].buf = ® |
||||
msg[0].len = sizeof(reg); |
||||
msg[1].addr = client->addr; |
||||
msg[1].flags = I2C_M_RD; |
||||
msg[1].buf = data; |
||||
if (single) |
||||
msg[1].len = 1; |
||||
else |
||||
msg[1].len = 2; |
||||
|
||||
ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); |
||||
if (ret < 0) |
||||
return ret; |
||||
|
||||
if (!single) |
||||
ret = get_unaligned_le16(data); |
||||
else |
||||
ret = data[0]; |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
static int bq27xxx_battery_i2c_probe(struct i2c_client *client, |
||||
const struct i2c_device_id *id) |
||||
{ |
||||
struct bq27xxx_device_info *di; |
||||
int ret; |
||||
|
||||
di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL); |
||||
if (!di) |
||||
return -ENOMEM; |
||||
|
||||
di->dev = &client->dev; |
||||
di->chip = id->driver_data; |
||||
di->name = id->name; |
||||
di->bus.read = bq27xxx_battery_i2c_read; |
||||
|
||||
ret = bq27xxx_battery_setup(di); |
||||
if (ret) |
||||
return ret; |
||||
|
||||
/* Schedule a polling after about 1 min */ |
||||
schedule_delayed_work(&di->work, 60 * HZ); |
||||
|
||||
i2c_set_clientdata(client, di); |
||||
|
||||
if (client->irq) { |
||||
ret = devm_request_threaded_irq(&client->dev, client->irq, |
||||
NULL, bq27xxx_battery_irq_handler_thread, |
||||
IRQF_ONESHOT, |
||||
di->name, di); |
||||
if (ret) { |
||||
dev_err(&client->dev, |
||||
"Unable to register IRQ %d error %d\n", |
||||
client->irq, ret); |
||||
return ret; |
||||
} |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int bq27xxx_battery_i2c_remove(struct i2c_client *client) |
||||
{ |
||||
struct bq27xxx_device_info *di = i2c_get_clientdata(client); |
||||
|
||||
bq27xxx_battery_teardown(di); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static const struct i2c_device_id bq27xxx_i2c_id_table[] = { |
||||
{ "bq27200", BQ27000 }, |
||||
{ "bq27210", BQ27010 }, |
||||
{ "bq27500", BQ27500 }, |
||||
{ "bq27510", BQ27500 }, |
||||
{ "bq27520", BQ27500 }, |
||||
{ "bq27530", BQ27530 }, |
||||
{ "bq27531", BQ27530 }, |
||||
{ "bq27541", BQ27541 }, |
||||
{ "bq27542", BQ27541 }, |
||||
{ "bq27546", BQ27541 }, |
||||
{ "bq27742", BQ27541 }, |
||||
{ "bq27545", BQ27545 }, |
||||
{ "bq27421", BQ27421 }, |
||||
{ "bq27425", BQ27421 }, |
||||
{ "bq27441", BQ27421 }, |
||||
{ "bq27621", BQ27421 }, |
||||
{}, |
||||
}; |
||||
MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table); |
||||
|
||||
static struct i2c_driver bq27xxx_battery_i2c_driver = { |
||||
.driver = { |
||||
.name = "bq27xxx-battery", |
||||
}, |
||||
.probe = bq27xxx_battery_i2c_probe, |
||||
.remove = bq27xxx_battery_i2c_remove, |
||||
.id_table = bq27xxx_i2c_id_table, |
||||
}; |
||||
module_i2c_driver(bq27xxx_battery_i2c_driver); |
||||
|
||||
MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); |
||||
MODULE_DESCRIPTION("BQ27xxx battery monitor i2c driver"); |
||||
MODULE_LICENSE("GPL"); |
Loading…
Reference in new issue