2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-15 08:44:14 +08:00

rtc: isl1208: Support more chip variations

Add more support in the driver for dealing with differences in is1208
compatible chips.  Put the 1208, 1209, 1218, and 1219 in the list and
encode information about nvram size, tamper, and timestamp features.

This adds support for the isl1209, which has a tamper detect but no
timestamp feature.

Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Trent Piepho <tpiepho@impinj.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
This commit is contained in:
Trent Piepho 2019-02-12 02:34:04 +00:00 committed by Alexandre Belloni
parent ed3c52a075
commit 5909b87db8

View File

@ -13,6 +13,7 @@
#include <linux/bcd.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/rtc.h>
@ -73,15 +74,49 @@
static struct i2c_driver isl1208_driver;
/* ISL1208 various variants */
enum {
enum isl1208_id {
TYPE_ISL1208 = 0,
TYPE_ISL1209,
TYPE_ISL1218,
TYPE_ISL1219,
ISL_LAST_ID
};
/* Chip capabilities table */
static const struct isl1208_config {
const char name[8];
unsigned int nvmem_length;
unsigned has_tamper:1;
unsigned has_timestamp:1;
} isl1208_configs[] = {
[TYPE_ISL1208] = { "isl1208", 2, false, false },
[TYPE_ISL1209] = { "isl1209", 2, true, false },
[TYPE_ISL1218] = { "isl1218", 8, false, false },
[TYPE_ISL1219] = { "isl1219", 2, true, true },
};
static const struct i2c_device_id isl1208_id[] = {
{ "isl1208", TYPE_ISL1208 },
{ "isl1209", TYPE_ISL1209 },
{ "isl1218", TYPE_ISL1218 },
{ "isl1219", TYPE_ISL1219 },
{ }
};
MODULE_DEVICE_TABLE(i2c, isl1208_id);
static const struct of_device_id isl1208_of_match[] = {
{ .compatible = "isil,isl1208", .data = &isl1208_configs[TYPE_ISL1208] },
{ .compatible = "isil,isl1209", .data = &isl1208_configs[TYPE_ISL1209] },
{ .compatible = "isil,isl1218", .data = &isl1208_configs[TYPE_ISL1218] },
{ .compatible = "isil,isl1219", .data = &isl1208_configs[TYPE_ISL1219] },
{ }
};
MODULE_DEVICE_TABLE(of, isl1208_of_match);
/* Device state */
struct isl1208_state {
struct rtc_device *rtc;
const struct isl1208_config *config;
};
/* block read */
@ -602,11 +637,12 @@ isl1208_rtc_interrupt(int irq, void *data)
return err;
}
if (sr & ISL1208_REG_SR_EVT) {
sysfs_notify(&isl1208->rtc->dev.kobj, NULL,
dev_attr_timestamp0.attr.name);
if (isl1208->config->has_tamper && (sr & ISL1208_REG_SR_EVT)) {
dev_warn(&client->dev, "event detected");
handled = 1;
if (isl1208->config->has_timestamp)
sysfs_notify(&isl1208->rtc->dev.kobj, NULL,
dev_attr_timestamp0.attr.name);
}
return handled ? IRQ_HANDLED : IRQ_NONE;
@ -743,6 +779,17 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
return -ENOMEM;
i2c_set_clientdata(client, isl1208);
/* Determine which chip we have */
if (client->dev.of_node) {
isl1208->config = of_device_get_match_data(&client->dev);
if (!isl1208->config)
return -ENODEV;
} else {
if (id->driver_data >= ISL_LAST_ID)
return -ENODEV;
isl1208->config = &isl1208_configs[id->driver_data];
}
isl1208->rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(isl1208->rtc))
return PTR_ERR(isl1208->rtc);
@ -759,7 +806,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
dev_warn(&client->dev, "rtc power failure detected, "
"please set clock.\n");
if (id->driver_data == TYPE_ISL1219) {
if (isl1208->config->has_tamper) {
struct device_node *np = client->dev.of_node;
u32 evienb;
@ -780,10 +827,12 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
dev_err(&client->dev, "could not enable tamper detection\n");
return rc;
}
evdet_irq = of_irq_get_byname(np, "evdet");
}
if (isl1208->config->has_timestamp) {
rc = rtc_add_group(isl1208->rtc, &isl1219_rtc_sysfs_files);
if (rc)
return rc;
evdet_irq = of_irq_get_byname(np, "evdet");
}
rc = rtc_add_group(isl1208->rtc, &isl1208_rtc_sysfs_files);
@ -803,22 +852,6 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
return rtc_register_device(isl1208->rtc);
}
static const struct i2c_device_id isl1208_id[] = {
{ "isl1208", TYPE_ISL1208 },
{ "isl1218", TYPE_ISL1218 },
{ "isl1219", TYPE_ISL1219 },
{ }
};
MODULE_DEVICE_TABLE(i2c, isl1208_id);
static const struct of_device_id isl1208_of_match[] = {
{ .compatible = "isil,isl1208" },
{ .compatible = "isil,isl1218" },
{ .compatible = "isil,isl1219" },
{ }
};
MODULE_DEVICE_TABLE(of, isl1208_of_match);
static struct i2c_driver isl1208_driver = {
.driver = {
.name = "rtc-isl1208",