File Index
Files and directories
Sign in
FILE

bq27xxx_battery_hdq.c

File preview with syntax highlighting.

linux-6.19.14/drivers/power/supply/bq27xxx_battery_hdq.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * BQ27xxx battery monitor HDQ/1-wire driver
  4 *
  5 * Copyright (C) 2007-2017 Texas Instruments Incorporated - https://www.ti.com/
  6 *
  7 */
  8
  9#include <linux/kernel.h>
 10#include <linux/module.h>
 11#include <linux/device.h>
 12#include <linux/types.h>
 13#include <linux/platform_device.h>
 14#include <linux/mutex.h>
 15#include <linux/power/bq27xxx_battery.h>
 16
 17#include <linux/w1.h>
 18
 19#define W1_FAMILY_BQ27000	0x01
 20
 21#define HDQ_CMD_READ	(0 << 7)
 22#define HDQ_CMD_WRITE	(1 << 7)
 23
 24static int F_ID;
 25module_param(F_ID, int, S_IRUSR);
 26MODULE_PARM_DESC(F_ID, "1-wire slave FID for BQ27xxx device");
 27
 28static int w1_bq27000_read(struct w1_slave *sl, unsigned int reg)
 29{
 30	u8 val;
 31
 32	mutex_lock(&sl->master->bus_mutex);
 33	w1_write_8(sl->master, HDQ_CMD_READ | reg);
 34	val = w1_read_8(sl->master);
 35	mutex_unlock(&sl->master->bus_mutex);
 36
 37	return val;
 38}
 39
 40static int bq27xxx_battery_hdq_read(struct bq27xxx_device_info *di, u8 reg,
 41				    bool single)
 42{
 43	struct w1_slave *sl = dev_to_w1_slave(di->dev);
 44	unsigned int timeout = 3;
 45	int upper, lower;
 46	int temp;
 47
 48	if (!single) {
 49		/*
 50		 * Make sure the value has not changed in between reading the
 51		 * lower and the upper part
 52		 */
 53		upper = w1_bq27000_read(sl, reg + 1);
 54		do {
 55			temp = upper;
 56			if (upper < 0)
 57				return upper;
 58
 59			lower = w1_bq27000_read(sl, reg);
 60			if (lower < 0)
 61				return lower;
 62
 63			upper = w1_bq27000_read(sl, reg + 1);
 64		} while (temp != upper && --timeout);
 65
 66		if (timeout == 0)
 67			return -EIO;
 68
 69		return (upper << 8) | lower;
 70	}
 71
 72	return w1_bq27000_read(sl, reg);
 73}
 74
 75static int bq27xxx_battery_hdq_add_slave(struct w1_slave *sl)
 76{
 77	struct bq27xxx_device_info *di;
 78
 79	di = devm_kzalloc(&sl->dev, sizeof(*di), GFP_KERNEL);
 80	if (!di)
 81		return -ENOMEM;
 82
 83	dev_set_drvdata(&sl->dev, di);
 84
 85	di->dev = &sl->dev;
 86	di->chip = BQ27000;
 87	di->name = "bq27000-battery";
 88	di->bus.read = bq27xxx_battery_hdq_read;
 89
 90	return bq27xxx_battery_setup(di);
 91}
 92
 93static void bq27xxx_battery_hdq_remove_slave(struct w1_slave *sl)
 94{
 95	struct bq27xxx_device_info *di = dev_get_drvdata(&sl->dev);
 96
 97	bq27xxx_battery_teardown(di);
 98}
 99
100static const struct w1_family_ops bq27xxx_battery_hdq_fops = {
101	.add_slave	= bq27xxx_battery_hdq_add_slave,
102	.remove_slave	= bq27xxx_battery_hdq_remove_slave,
103};
104
105static struct w1_family bq27xxx_battery_hdq_family = {
106	.fid = W1_FAMILY_BQ27000,
107	.fops = &bq27xxx_battery_hdq_fops,
108};
109
110static int __init bq27xxx_battery_hdq_init(void)
111{
112	if (F_ID)
113		bq27xxx_battery_hdq_family.fid = F_ID;
114
115	return w1_register_family(&bq27xxx_battery_hdq_family);
116}
117module_init(bq27xxx_battery_hdq_init);
118
119static void __exit bq27xxx_battery_hdq_exit(void)
120{
121	w1_unregister_family(&bq27xxx_battery_hdq_family);
122}
123module_exit(bq27xxx_battery_hdq_exit);
124
125MODULE_AUTHOR("Texas Instruments Ltd");
126MODULE_DESCRIPTION("BQ27xxx battery monitor HDQ/1-wire driver");
127MODULE_LICENSE("GPL");
128MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_BQ27000));
~/ Read-only file preview.