mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
While being less compact, using named initializers allows to more easily see which members of the structs are assigned which value without having to lookup the declaration of the struct. And it's also more robust against changes to the struct definition. The mentioned robustness is relevant for a planned change to struct i2c_device_id that replaces .driver_data by an anonymous union. While touching all these arrays, unify indention and usage of commas. This patch doesn't modify the compiled arrays, only their representation in source form benefits. The former was confirmed with x86 and arm64 builds. Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com> Link: https://lore.kernel.org/r/65b77bcd452752c36d866069cc5790b26d2bf8dc.1778688803.git.u.kleine-koenig@baylibre.com Signed-off-by: Guenter Roeck <linux@roeck-us.net>
102 lines
2.6 KiB
C
102 lines
2.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Hardware monitoring driver for Maxim MAX15301
|
|
*
|
|
* Copyright (c) 2021 Flextronics International Sweden AB
|
|
*
|
|
* Even though the specification does not specifically mention it,
|
|
* extensive empirical testing has revealed that auto-detection of
|
|
* limit-registers will fail in a random fashion unless the delay
|
|
* parameter is set to above about 80us. The default delay is set
|
|
* to 100us to include some safety margin.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/err.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/ktime.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/pmbus.h>
|
|
#include "pmbus.h"
|
|
|
|
static const struct i2c_device_id max15301_id[] = {
|
|
{ .name = "bmr461" },
|
|
{ .name = "max15301" },
|
|
{ .name = "max15303" },
|
|
{ }
|
|
};
|
|
MODULE_DEVICE_TABLE(i2c, max15301_id);
|
|
|
|
struct max15301_data {
|
|
int id;
|
|
struct pmbus_driver_info info;
|
|
};
|
|
|
|
#define to_max15301_data(x) container_of(x, struct max15301_data, info)
|
|
|
|
#define MAX15301_WAIT_TIME 100 /* us */
|
|
|
|
static ushort delay = MAX15301_WAIT_TIME;
|
|
module_param(delay, ushort, 0644);
|
|
MODULE_PARM_DESC(delay, "Delay between chip accesses in us");
|
|
|
|
static struct max15301_data max15301_data = {
|
|
.info = {
|
|
.pages = 1,
|
|
.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
|
|
| PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
|
|
| PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2
|
|
| PMBUS_HAVE_STATUS_TEMP
|
|
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
|
|
}
|
|
};
|
|
|
|
static int max15301_probe(struct i2c_client *client)
|
|
{
|
|
int status;
|
|
u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
|
|
const struct i2c_device_id *mid;
|
|
struct pmbus_driver_info *info = &max15301_data.info;
|
|
|
|
if (!i2c_check_functionality(client->adapter,
|
|
I2C_FUNC_SMBUS_READ_BYTE_DATA
|
|
| I2C_FUNC_SMBUS_BLOCK_DATA))
|
|
return -ENODEV;
|
|
|
|
status = i2c_smbus_read_block_data(client, PMBUS_IC_DEVICE_ID, device_id);
|
|
if (status < 0) {
|
|
dev_err(&client->dev, "Failed to read Device Id\n");
|
|
return status;
|
|
}
|
|
for (mid = max15301_id; mid->name[0]; mid++) {
|
|
if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
|
|
break;
|
|
}
|
|
if (!mid->name[0]) {
|
|
dev_err(&client->dev, "Unsupported device\n");
|
|
return -ENODEV;
|
|
}
|
|
|
|
info->access_delay = delay;
|
|
|
|
return pmbus_do_probe(client, info);
|
|
}
|
|
|
|
static struct i2c_driver max15301_driver = {
|
|
.driver = {
|
|
.name = "max15301",
|
|
},
|
|
.probe = max15301_probe,
|
|
.id_table = max15301_id,
|
|
};
|
|
|
|
module_i2c_driver(max15301_driver);
|
|
|
|
MODULE_AUTHOR("Erik Rosen <erik.rosen@metormote.com>");
|
|
MODULE_DESCRIPTION("PMBus driver for Maxim MAX15301");
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_IMPORT_NS("PMBUS");
|