* [PATCH v6 1/4] i2c-core-acpi : Add i2c_acpi_set_connection
@ 2017-12-25 15:57 Marc CAPDEVILLE
2017-12-25 15:57 ` [PATCH v6 2/4] i2c-smbus : Add client discovered ARA support Marc CAPDEVILLE
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Marc CAPDEVILLE @ 2017-12-25 15:57 UTC (permalink / raw)
To: Kevin Tsai
Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, Mika Westerberg, Wolfram Sang, linux-iio,
linux-i2c, linux-acpi, linux-kernel, Marc CAPDEVILLE
Add a methode to allow clients to change their connection address on
same adapter.
On ACPI enumerated device, when a device support smbus alert protocol,
there are two acpi serial bus connection description. The order in which
connection is given is not well defined and devices may be enumerated
with the wrong address (the first one). So let the driver detect the
unsupported address and request i2c acpi core to choose the second one
at probing time.
Signed-off-by: Marc CAPDEVILLE <m.capdeville@no-log.org>
---
drivers/i2c/i2c-core-acpi.c | 50 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/i2c.h | 10 +++++++++
2 files changed, 60 insertions(+)
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index a9126b3cda61..47bc0da12055 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -421,6 +421,56 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
}
EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
+int i2c_acpi_set_connection(struct i2c_client *client, int index)
+{
+ struct i2c_acpi_lookup lookup;
+ struct i2c_adapter *adapter;
+ struct acpi_device *adev;
+ struct i2c_board_info info;
+ LIST_HEAD(resource_list);
+ int ret;
+
+ if (!client)
+ return -ENODEV;
+
+ adev = ACPI_COMPANION(&client->dev);
+ if (!adev)
+ return -ENODEV;
+
+ memset(&info, 0, sizeof(info));
+ memset(&lookup, 0, sizeof(lookup));
+ lookup.info = &info;
+ lookup.device_handle = acpi_device_handle(adev);
+ lookup.index = index;
+
+ ret = acpi_dev_get_resources(adev, &resource_list,
+ i2c_acpi_fill_info, &lookup);
+ acpi_dev_free_resource_list(&resource_list);
+
+ adapter = i2c_acpi_find_adapter_by_handle(lookup.adapter_handle);
+
+ if (ret < 0 || !info.addr)
+ return -EINVAL;
+
+ /* Only accept connection on same adapter */
+ if (adapter != client->adapter)
+ return -EINVAL;
+
+ ret = i2c_check_addr_validity(info.addr, info.flags);
+ if (ret) {
+ dev_err(&client->dev, "Invalid %d-bit I2C address 0x%02hx\n",
+ info.flags & I2C_CLIENT_TEN ? 10 : 7, info.addr);
+ return -EINVAL;
+ }
+
+ /* Set new address and flags */
+ client->addr = info.addr;
+ client->flags = info.flags;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(i2c_acpi_set_connection);
+
#ifdef CONFIG_ACPI_I2C_OPREGION
static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
u8 cmd, u8 *data, u8 data_len)
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 0f774406fad0..618b453901da 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -595,6 +595,8 @@ struct i2c_adapter {
const struct i2c_adapter_quirks *quirks;
struct irq_domain *host_notify_domain;
+
+ struct i2c_client *smbus_ara; /* ARA for SMBUS if present */
};
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
@@ -839,16 +841,24 @@ static inline const struct of_device_id
u32 i2c_acpi_find_bus_speed(struct device *dev);
struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
struct i2c_board_info *info);
+
+int i2c_acpi_set_connection(struct i2c_client *client, int index);
#else
static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
{
return 0;
}
+
static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
int index, struct i2c_board_info *info)
{
return NULL;
}
+
+static inline int i2c_acpi_set_connection(struct i2c_client *client, int index)
+{
+ return -EINVAL;
+}
#endif /* CONFIG_ACPI */
#endif /* _LINUX_I2C_H */
--
2.11.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v6 2/4] i2c-smbus : Add client discovered ARA support
2017-12-25 15:57 [PATCH v6 1/4] i2c-core-acpi : Add i2c_acpi_set_connection Marc CAPDEVILLE
@ 2017-12-25 15:57 ` Marc CAPDEVILLE
[not found] ` <20171225155723.6338-2-m.capdeville-n+LsquliYkMdnm+yROfE0A@public.gmane.org>
2017-12-25 15:57 ` [PATCH v6 3/4] iio : Add cm3218 smbus ara and acpi support Marc CAPDEVILLE
` (2 subsequent siblings)
3 siblings, 1 reply; 12+ messages in thread
From: Marc CAPDEVILLE @ 2017-12-25 15:57 UTC (permalink / raw)
To: Kevin Tsai
Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, Mika Westerberg, Wolfram Sang, linux-iio,
linux-i2c, linux-acpi, linux-kernel, Marc CAPDEVILLE
This is from rfc by Alan Cox : https://patchwork.ozlabs.org/patch/381773
The idea is as follows (extract from above rfc) :
- If an adapter knows about its ARA and smbus alerts then the adapter
creates its own interrupt handler as before
- If a client knows it needs smbus alerts it calls
i2c_require_smbus_alert(). This ensures that there is an ARA handler
registered and tells the client whether the adapter is handling it
anyway or not.
- When the client learns that an ARA event has occurred it calls
i2c_smbus_alert_event() which uses the existing ARA mechanism to kick
things off.
Suggested-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Marc CAPDEVILLE <m.capdeville@no-log.org>
---
drivers/i2c/i2c-smbus.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/i2c-smbus.h | 15 +++++++++
2 files changed, 98 insertions(+)
diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c
index 5a1dd7f13bac..e97fbafd10ef 100644
--- a/drivers/i2c/i2c-smbus.c
+++ b/drivers/i2c/i2c-smbus.c
@@ -161,6 +161,9 @@ static int smbalert_probe(struct i2c_client *ara,
}
i2c_set_clientdata(ara, alert);
+
+ ara->adapter->smbus_ara = ara;
+
dev_info(&adapter->dev, "supports SMBALERT#\n");
return 0;
@@ -172,6 +175,9 @@ static int smbalert_remove(struct i2c_client *ara)
struct i2c_smbus_alert *alert = i2c_get_clientdata(ara);
cancel_work_sync(&alert->alert);
+
+ ara->adapter->smbus_ara = NULL;
+
return 0;
}
@@ -210,6 +216,83 @@ int i2c_handle_smbus_alert(struct i2c_client *ara)
}
EXPORT_SYMBOL_GPL(i2c_handle_smbus_alert);
+/*
+ * i2c_require_smbus_alert - Client discovered SMBus alert
+ * @c: client requiring ARA
+ *
+ * When a client needs an ARA it calls this method. If the bus adapter
+ * supports ARA and already knows how to do so then it will already have
+ * configured for ARA and this is a no-op. If not then we set up an ARA
+ * on the adapter.
+ *
+ * We *cannot* simply register a new IRQ handler for this because we might
+ * have multiple GPIO interrupts to devices all of which trigger an ARA.
+ *
+ * Return:
+ * 0 if ara support already registered
+ * 1 if call register a new smbus_alert device
+ * <0 on error
+ */
+int i2c_require_smbus_alert(struct i2c_client *client)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ struct i2c_smbus_alert_setup setup;
+ struct i2c_client *ara;
+
+ /* ARA is already known and handled by the adapter (ideal case)
+ * or another client has specified ARA is needed
+ */
+ if (adapter->smbus_ara)
+ return 0;
+
+ /* Client driven, do not set up a new IRQ handler */
+ setup.irq = 0;
+
+ ara = i2c_setup_smbus_alert(adapter, &setup);
+ if (!ara)
+ return -ENODEV;
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(i2c_require_smbus_alert);
+
+/*
+ * i2c_smbus_alert_event
+ * @client: the client who known of a probable ara event
+ * Context: can't sleep
+ *
+ * Helper function to be called from an I2C device driver's interrupt
+ * handler. It will schedule the alert work, in turn calling the
+ * corresponding I2C device driver's alert function.
+ *
+ * It is assumed that client is an i2c client who previously call
+ * i2c_require_smbus_alert().
+ */
+int i2c_smbus_alert_event(struct i2c_client *client)
+{
+ struct i2c_adapter *adapter;
+ struct i2c_client *ara;
+ struct i2c_smbus_alert *alert;
+
+ if (!client)
+ return -EINVAL;
+
+ adapter = client->adapter;
+ if (!adapter)
+ return -EINVAL;
+
+ ara = adapter->smbus_ara;
+ if (!ara)
+ return -EINVAL;
+
+ alert = i2c_get_clientdata(ara);
+ if (!alert)
+ return -EINVAL;
+
+ return schedule_work(&alert->alert);
+}
+EXPORT_SYMBOL_GPL(i2c_smbus_alert_event);
+
module_i2c_driver(smbalert_driver);
MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
diff --git a/include/linux/i2c-smbus.h b/include/linux/i2c-smbus.h
index fb0e040b1abb..49f362fa6ac5 100644
--- a/include/linux/i2c-smbus.h
+++ b/include/linux/i2c-smbus.h
@@ -58,4 +58,19 @@ static inline int of_i2c_setup_smbus_alert(struct i2c_adapter *adap)
}
#endif
+#if IS_ENABLED(CONFIG_I2C_SMBUS)
+int i2c_require_smbus_alert(struct i2c_client *client);
+int i2c_smbus_alert_event(struct i2c_client *client);
+#else
+static inline int i2c_require_smbus_alert(struct i2c_client *client)
+{
+ return NULL;
+}
+
+static inline int i2c_smbus_alert_event(struct i2c_client *client)
+{
+ return NULL;
+}
+#endif
+
#endif /* _LINUX_I2C_SMBUS_H */
--
2.11.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v6 3/4] iio : Add cm3218 smbus ara and acpi support
2017-12-25 15:57 [PATCH v6 1/4] i2c-core-acpi : Add i2c_acpi_set_connection Marc CAPDEVILLE
2017-12-25 15:57 ` [PATCH v6 2/4] i2c-smbus : Add client discovered ARA support Marc CAPDEVILLE
@ 2017-12-25 15:57 ` Marc CAPDEVILLE
[not found] ` <20171225155723.6338-3-m.capdeville-n+LsquliYkMdnm+yROfE0A@public.gmane.org>
2017-12-29 12:53 ` Jonathan Cameron
2017-12-25 15:57 ` [PATCH v6 4/4] iio : cm32181 : cosmetic cleanup Marc CAPDEVILLE
2017-12-28 1:04 ` [PATCH v6 1/4] i2c-core-acpi : Add i2c_acpi_set_connection Rafael J. Wysocki
3 siblings, 2 replies; 12+ messages in thread
From: Marc CAPDEVILLE @ 2017-12-25 15:57 UTC (permalink / raw)
To: Kevin Tsai
Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, Mika Westerberg, Wolfram Sang, linux-iio,
linux-i2c, linux-acpi, linux-kernel, Marc CAPDEVILLE
On asus T100, Capella cm3218 chip is implemented as ambiant light
sensor. This chip expose an smbus ARA protocol device on standard
address 0x0c. The chip is not functional before all alerts are
acknowledged.
On asus T100, this device is enumerated on ACPI bus and the description
give two I2C connection. The first is the connection to the ARA device
and the second gives the real address of the device.
So, on device probe,If the i2c address is the ARA address and the
device is enumerated via acpi, we change address of the device for
the one in the second acpi serial bus connection.
This free the ara address so we can register with the smbus_alert
driver.
If an interrupt resource is given, and a smbus_alert device was
found on the adapter, we request a treaded interrupt to
call i2c_smbus_alert_event to handle the alert.
In somme case, the treaded interrupt is not schedule before the driver
try to initialize chip registers. So if first registers access fail, we
call i2c_smbus_alert_event() to acknowledge initial alert, then retry
register access.
Signed-off-by: Marc CAPDEVILLE <m.capdeville@no-log.org>
---
drivers/iio/light/cm32181.c | 120 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 115 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
index aebf7dd071af..96c08755e6e3 100644
--- a/drivers/iio/light/cm32181.c
+++ b/drivers/iio/light/cm32181.c
@@ -18,6 +18,9 @@
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
#include <linux/init.h>
+#include <linux/i2c-smbus.h>
+#include <linux/acpi.h>
+#include <linux/of_device.h>
/* Registers Address */
#define CM32181_REG_ADDR_CMD 0x00
@@ -47,6 +50,11 @@
#define CM32181_CALIBSCALE_RESOLUTION 1000
#define MLUX_PER_LUX 1000
+#define CM32181_ID 0x81
+#define CM3218_ID 0x18
+
+#define SMBUS_ARA_ADDR 0x0c
+
static const u8 cm32181_reg[CM32181_CONF_REG_NUM] = {
CM32181_REG_ADDR_CMD,
};
@@ -57,6 +65,7 @@ static const int als_it_value[] = {25000, 50000, 100000, 200000, 400000,
struct cm32181_chip {
struct i2c_client *client;
+ int chip_id;
struct mutex lock;
u16 conf_regs[CM32181_CONF_REG_NUM];
int calibscale;
@@ -77,11 +86,22 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181)
s32 ret;
ret = i2c_smbus_read_word_data(client, CM32181_REG_ADDR_ID);
- if (ret < 0)
- return ret;
+ if (ret < 0) {
+ if (cm32181->chip_id == CM3218_ID) {
+ /*
+ * On cm3218, smbus alert trigger after probing,
+ * so poll for first alert here, then retry.
+ */
+ i2c_smbus_alert_event(client);
+ ret = i2c_smbus_read_word_data(client,
+ CM32181_REG_ADDR_ID);
+ } else {
+ return ret;
+ }
+ }
/* check device ID */
- if ((ret & 0xFF) != 0x81)
+ if ((ret & 0xFF) != cm32181->chip_id)
return -ENODEV;
/* Default Values */
@@ -297,12 +317,36 @@ static const struct iio_info cm32181_info = {
.attrs = &cm32181_attribute_group,
};
+static void cm3218_alert(struct i2c_client *client,
+ enum i2c_alert_protocol type,
+ unsigned int data)
+{
+ /*
+ * nothing to do for now.
+ * This is just here to acknownledge the cm3218 alert.
+ */
+}
+
+static irqreturn_t cm32181_irq(int irq, void *d)
+{
+ struct cm32181_chip *cm32181 = d;
+
+ if (cm32181->chip_id == CM3218_ID) {
+ /* This is cm3218 chip irq, so handle the smbus alert */
+ i2c_smbus_alert_event(cm32181->client);
+ }
+
+ return IRQ_HANDLED;
+}
+
static int cm32181_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct cm32181_chip *cm32181;
struct iio_dev *indio_dev;
int ret;
+ const struct of_device_id *of_id;
+ const struct acpi_device_id *acpi_id;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*cm32181));
if (!indio_dev) {
@@ -322,6 +366,61 @@ static int cm32181_probe(struct i2c_client *client,
indio_dev->name = id->name;
indio_dev->modes = INDIO_DIRECT_MODE;
+ /* Lookup for chip ID from platform, acpi or of device table */
+ if (id) {
+ cm32181->chip_id = id->driver_data;
+ } else if (ACPI_COMPANION(&client->dev)) {
+ acpi_id = acpi_match_device(client->dev.driver->acpi_match_table,
+ &client->dev);
+ if (!acpi_id)
+ return -ENODEV;
+
+ cm32181->chip_id = (kernel_ulong_t)acpi_id->driver_data;
+ } else if (client->dev.of_node) {
+ of_id = of_match_device(client->dev.driver->of_match_table,
+ &client->dev);
+ if (!of_id)
+ return -ENODEV;
+
+ cm32181->chip_id = (kernel_ulong_t)of_id->data;
+ } else {
+ return -ENODEV;
+ }
+
+ if (cm32181->chip_id == CM3218_ID) {
+ if (ACPI_COMPANION(&client->dev) &&
+ client->addr == SMBUS_ARA_ADDR) {
+ /*
+ * In case this device as been enumerated by acpi
+ * with the reserved smbus ARA address (first acpi
+ * connection), request change of address to the second
+ * connection.
+ */
+ ret = i2c_acpi_set_connection(client, 1);
+ if (ret)
+ return ret;
+ }
+
+ /* cm3218 chip require an ara device on his adapter */
+ ret = i2c_require_smbus_alert(client);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * If irq is given, request a threaded irq handler to manage
+ * smbus alert.
+ */
+ if (client->irq > 0) {
+ ret = devm_request_threaded_irq(&client->dev,
+ client->irq,
+ NULL, cm32181_irq,
+ IRQF_ONESHOT,
+ "cm32181", cm32181);
+ if (ret)
+ return ret;
+ }
+ }
+
ret = cm32181_reg_init(cm32181);
if (ret) {
dev_err(&client->dev,
@@ -342,25 +441,36 @@ static int cm32181_probe(struct i2c_client *client,
}
static const struct i2c_device_id cm32181_id[] = {
- { "cm32181", 0 },
+ { "cm32181", CM32181_ID },
+ { "cm3218", CM3218_ID },
{ }
};
MODULE_DEVICE_TABLE(i2c, cm32181_id);
static const struct of_device_id cm32181_of_match[] = {
- { .compatible = "capella,cm32181" },
+ { .compatible = "capella,cm32181", (void *)CM32181_ID },
+ { .compatible = "capella,cm3218", (void *)CM3218_ID },
{ }
};
MODULE_DEVICE_TABLE(of, cm32181_of_match);
+static const struct acpi_device_id cm32181_acpi_match[] = {
+ { "CPLM3218", CM3218_ID },
+ { }
+};
+
+MODULE_DEVICE_TABLE(acpi, cm32181_acpi_match);
+
static struct i2c_driver cm32181_driver = {
.driver = {
.name = "cm32181",
.of_match_table = of_match_ptr(cm32181_of_match),
+ .acpi_match_table = ACPI_PTR(cm32181_acpi_match),
},
.id_table = cm32181_id,
.probe = cm32181_probe,
+ .alert = cm3218_alert,
};
module_i2c_driver(cm32181_driver);
--
2.11.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v6 4/4] iio : cm32181 : cosmetic cleanup
2017-12-25 15:57 [PATCH v6 1/4] i2c-core-acpi : Add i2c_acpi_set_connection Marc CAPDEVILLE
2017-12-25 15:57 ` [PATCH v6 2/4] i2c-smbus : Add client discovered ARA support Marc CAPDEVILLE
2017-12-25 15:57 ` [PATCH v6 3/4] iio : Add cm3218 smbus ara and acpi support Marc CAPDEVILLE
@ 2017-12-25 15:57 ` Marc CAPDEVILLE
2017-12-29 12:56 ` Jonathan Cameron
2017-12-28 1:04 ` [PATCH v6 1/4] i2c-core-acpi : Add i2c_acpi_set_connection Rafael J. Wysocki
3 siblings, 1 reply; 12+ messages in thread
From: Marc CAPDEVILLE @ 2017-12-25 15:57 UTC (permalink / raw)
To: Kevin Tsai
Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, Mika Westerberg, Wolfram Sang, linux-iio,
linux-i2c, linux-acpi, linux-kernel, Marc CAPDEVILLE
Somme cosmetic cleanup suggested by Peter Meerwald-Stadler.
Macro name :
MLUX_PER_LUX => CM32181_MLUX_PER_LUX
Constante name :
als_it_bits => cm32181_als_it_bits
als_it_value => cm32181_als_it_value
Comment :
Registers Address => Register Addresses
Suggested-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Signed-off-by: Marc CAPDEVILLE <m.capdeville@no-log.org>
---
drivers/iio/light/cm32181.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
index 96c08755e6e3..3e6b244d5cd1 100644
--- a/drivers/iio/light/cm32181.c
+++ b/drivers/iio/light/cm32181.c
@@ -22,7 +22,7 @@
#include <linux/acpi.h>
#include <linux/of_device.h>
-/* Registers Address */
+/* Register Addresses */
#define CM32181_REG_ADDR_CMD 0x00
#define CM32181_REG_ADDR_ALS 0x04
#define CM32181_REG_ADDR_STATUS 0x06
@@ -48,7 +48,7 @@
#define CM32181_MLUX_PER_BIT_BASE_IT 800000 /* Based on IT=800ms */
#define CM32181_CALIBSCALE_DEFAULT 1000
#define CM32181_CALIBSCALE_RESOLUTION 1000
-#define MLUX_PER_LUX 1000
+#define CM32181_MLUX_PER_LUX 1000
#define CM32181_ID 0x81
#define CM3218_ID 0x18
@@ -59,8 +59,8 @@ static const u8 cm32181_reg[CM32181_CONF_REG_NUM] = {
CM32181_REG_ADDR_CMD,
};
-static const int als_it_bits[] = {12, 8, 0, 1, 2, 3};
-static const int als_it_value[] = {25000, 50000, 100000, 200000, 400000,
+static const int cm32181_als_it_bits[] = {12, 8, 0, 1, 2, 3};
+static const int cm32181_als_it_value[] = {25000, 50000, 100000, 200000, 400000,
800000};
struct cm32181_chip {
@@ -137,9 +137,9 @@ static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2)
als_it = cm32181->conf_regs[CM32181_REG_ADDR_CMD];
als_it &= CM32181_CMD_ALS_IT_MASK;
als_it >>= CM32181_CMD_ALS_IT_SHIFT;
- for (i = 0; i < ARRAY_SIZE(als_it_bits); i++) {
- if (als_it == als_it_bits[i]) {
- *val2 = als_it_value[i];
+ for (i = 0; i < ARRAY_SIZE(cm32181_als_it_bits); i++) {
+ if (als_it == cm32181_als_it_bits[i]) {
+ *val2 = cm32181_als_it_value[i];
return IIO_VAL_INT_PLUS_MICRO;
}
}
@@ -162,14 +162,14 @@ static int cm32181_write_als_it(struct cm32181_chip *cm32181, int val)
u16 als_it;
int ret, i, n;
- n = ARRAY_SIZE(als_it_value);
+ n = ARRAY_SIZE(cm32181_als_it_value);
for (i = 0; i < n; i++)
- if (val <= als_it_value[i])
+ if (val <= cm32181_als_it_value[i])
break;
if (i >= n)
i = n - 1;
- als_it = als_it_bits[i];
+ als_it = cm32181_als_it_bits[i];
als_it <<= CM32181_CMD_ALS_IT_SHIFT;
mutex_lock(&cm32181->lock);
@@ -215,7 +215,7 @@ static int cm32181_get_lux(struct cm32181_chip *cm32181)
lux *= ret;
lux *= cm32181->calibscale;
lux /= CM32181_CALIBSCALE_RESOLUTION;
- lux /= MLUX_PER_LUX;
+ lux /= CM32181_MLUX_PER_LUX;
if (lux > 0xFFFF)
lux = 0xFFFF;
@@ -283,9 +283,9 @@ static ssize_t cm32181_get_it_available(struct device *dev,
{
int i, n, len;
- n = ARRAY_SIZE(als_it_value);
+ n = ARRAY_SIZE(cm32181_als_it_value);
for (i = 0, len = 0; i < n; i++)
- len += sprintf(buf + len, "0.%06u ", als_it_value[i]);
+ len += sprintf(buf + len, "0.%06u ", cm32181_als_it_value[i]);
return len + sprintf(buf + len, "\n");
}
--
2.11.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v6 2/4] i2c-smbus : Add client discovered ARA support
[not found] ` <20171225155723.6338-2-m.capdeville-n+LsquliYkMdnm+yROfE0A@public.gmane.org>
@ 2017-12-26 1:43 ` kbuild test robot
2017-12-29 13:04 ` Jonathan Cameron
1 sibling, 0 replies; 12+ messages in thread
From: kbuild test robot @ 2017-12-26 1:43 UTC (permalink / raw)
Cc: kbuild-all-JC7UmRfGjtg, Kevin Tsai, Jonathan Cameron,
Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
Mika Westerberg, Wolfram Sang, linux-iio-u79uwXL29TY76Z2rM5mHXA,
linux-i2c-u79uwXL29TY76Z2rM5mHXA,
linux-acpi-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Marc CAPDEVILLE
[-- Attachment #1: Type: text/plain, Size: 2338 bytes --]
Hi Marc,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on wsa/i2c/for-next]
[also build test WARNING on v4.15-rc5 next-20171222]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Marc-CAPDEVILLE/i2c-core-acpi-Add-i2c_acpi_set_connection/20171226-083729
base: https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
config: ia64-defconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=ia64
All warnings (new ones prefixed by >>):
In file included from include/uapi/linux/posix_types.h:5:0,
from include/uapi/linux/types.h:14,
from include/linux/compiler.h:164,
from include/linux/ioport.h:13,
from include/linux/acpi.h:25,
from drivers//i2c/i2c-core-base.c:24:
include/linux/i2c-smbus.h: In function 'i2c_require_smbus_alert':
>> include/linux/stddef.h:8:14: warning: return makes integer from pointer without a cast [-Wint-conversion]
#define NULL ((void *)0)
^
>> include/linux/i2c-smbus.h:67:9: note: in expansion of macro 'NULL'
return NULL;
^~~~
include/linux/i2c-smbus.h: In function 'i2c_smbus_alert_event':
>> include/linux/stddef.h:8:14: warning: return makes integer from pointer without a cast [-Wint-conversion]
#define NULL ((void *)0)
^
include/linux/i2c-smbus.h:72:9: note: in expansion of macro 'NULL'
return NULL;
^~~~
vim +/NULL +67 include/linux/i2c-smbus.h
60
61 #if IS_ENABLED(CONFIG_I2C_SMBUS)
62 int i2c_require_smbus_alert(struct i2c_client *client);
63 int i2c_smbus_alert_event(struct i2c_client *client);
64 #else
65 static inline int i2c_require_smbus_alert(struct i2c_client *client)
66 {
> 67 return NULL;
68 }
69
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 18935 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 3/4] iio : Add cm3218 smbus ara and acpi support
[not found] ` <20171225155723.6338-3-m.capdeville-n+LsquliYkMdnm+yROfE0A@public.gmane.org>
@ 2017-12-26 6:34 ` kbuild test robot
2017-12-28 1:19 ` Rafael J. Wysocki
1 sibling, 0 replies; 12+ messages in thread
From: kbuild test robot @ 2017-12-26 6:34 UTC (permalink / raw)
Cc: kbuild-all-JC7UmRfGjtg, Kevin Tsai, Jonathan Cameron,
Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
Mika Westerberg, Wolfram Sang, linux-iio-u79uwXL29TY76Z2rM5mHXA,
linux-i2c-u79uwXL29TY76Z2rM5mHXA,
linux-acpi-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Marc CAPDEVILLE
[-- Attachment #1: Type: text/plain, Size: 4861 bytes --]
Hi Marc,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR on v4.15-rc5 next-20171222]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Marc-CAPDEVILLE/i2c-core-acpi-Add-i2c_acpi_set_connection/20171226-083729
base: https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
config: i386-randconfig-c0-12261310 (attached as .config)
compiler: gcc-7 (Debian 7.2.0-12) 7.2.1 20171025
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All errors (new ones prefixed by >>):
drivers/iio/light/cm32181.o: In function `cm32181_irq':
>> drivers/iio/light/cm32181.c:336: undefined reference to `i2c_smbus_alert_event'
drivers/iio/light/cm32181.o: In function `cm32181_probe':
>> drivers/iio/light/cm32181.c:405: undefined reference to `i2c_require_smbus_alert'
drivers/iio/light/cm32181.o: In function `cm32181_reg_init':
drivers/iio/light/cm32181.c:95: undefined reference to `i2c_smbus_alert_event'
vim +336 drivers/iio/light/cm32181.c
329
330 static irqreturn_t cm32181_irq(int irq, void *d)
331 {
332 struct cm32181_chip *cm32181 = d;
333
334 if (cm32181->chip_id == CM3218_ID) {
335 /* This is cm3218 chip irq, so handle the smbus alert */
> 336 i2c_smbus_alert_event(cm32181->client);
337 }
338
339 return IRQ_HANDLED;
340 }
341
342 static int cm32181_probe(struct i2c_client *client,
343 const struct i2c_device_id *id)
344 {
345 struct cm32181_chip *cm32181;
346 struct iio_dev *indio_dev;
347 int ret;
348 const struct of_device_id *of_id;
349 const struct acpi_device_id *acpi_id;
350
351 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*cm32181));
352 if (!indio_dev) {
353 dev_err(&client->dev, "devm_iio_device_alloc failed\n");
354 return -ENOMEM;
355 }
356
357 cm32181 = iio_priv(indio_dev);
358 i2c_set_clientdata(client, indio_dev);
359 cm32181->client = client;
360
361 mutex_init(&cm32181->lock);
362 indio_dev->dev.parent = &client->dev;
363 indio_dev->channels = cm32181_channels;
364 indio_dev->num_channels = ARRAY_SIZE(cm32181_channels);
365 indio_dev->info = &cm32181_info;
366 indio_dev->name = id->name;
367 indio_dev->modes = INDIO_DIRECT_MODE;
368
369 /* Lookup for chip ID from platform, acpi or of device table */
370 if (id) {
371 cm32181->chip_id = id->driver_data;
372 } else if (ACPI_COMPANION(&client->dev)) {
373 acpi_id = acpi_match_device(client->dev.driver->acpi_match_table,
374 &client->dev);
375 if (!acpi_id)
376 return -ENODEV;
377
378 cm32181->chip_id = (kernel_ulong_t)acpi_id->driver_data;
379 } else if (client->dev.of_node) {
380 of_id = of_match_device(client->dev.driver->of_match_table,
381 &client->dev);
382 if (!of_id)
383 return -ENODEV;
384
385 cm32181->chip_id = (kernel_ulong_t)of_id->data;
386 } else {
387 return -ENODEV;
388 }
389
390 if (cm32181->chip_id == CM3218_ID) {
391 if (ACPI_COMPANION(&client->dev) &&
392 client->addr == SMBUS_ARA_ADDR) {
393 /*
394 * In case this device as been enumerated by acpi
395 * with the reserved smbus ARA address (first acpi
396 * connection), request change of address to the second
397 * connection.
398 */
399 ret = i2c_acpi_set_connection(client, 1);
400 if (ret)
401 return ret;
402 }
403
404 /* cm3218 chip require an ara device on his adapter */
> 405 ret = i2c_require_smbus_alert(client);
406 if (ret < 0)
407 return ret;
408
409 /*
410 * If irq is given, request a threaded irq handler to manage
411 * smbus alert.
412 */
413 if (client->irq > 0) {
414 ret = devm_request_threaded_irq(&client->dev,
415 client->irq,
416 NULL, cm32181_irq,
417 IRQF_ONESHOT,
418 "cm32181", cm32181);
419 if (ret)
420 return ret;
421 }
422 }
423
424 ret = cm32181_reg_init(cm32181);
425 if (ret) {
426 dev_err(&client->dev,
427 "%s: register init failed\n",
428 __func__);
429 return ret;
430 }
431
432 ret = devm_iio_device_register(&client->dev, indio_dev);
433 if (ret) {
434 dev_err(&client->dev,
435 "%s: regist device failed\n",
436 __func__);
437 return ret;
438 }
439
440 return 0;
441 }
442
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 21676 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/4] i2c-core-acpi : Add i2c_acpi_set_connection
2017-12-25 15:57 [PATCH v6 1/4] i2c-core-acpi : Add i2c_acpi_set_connection Marc CAPDEVILLE
` (2 preceding siblings ...)
2017-12-25 15:57 ` [PATCH v6 4/4] iio : cm32181 : cosmetic cleanup Marc CAPDEVILLE
@ 2017-12-28 1:04 ` Rafael J. Wysocki
3 siblings, 0 replies; 12+ messages in thread
From: Rafael J. Wysocki @ 2017-12-28 1:04 UTC (permalink / raw)
To: Marc CAPDEVILLE
Cc: Kevin Tsai, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, Mika Westerberg, Wolfram Sang, linux-iio,
linux-i2c, linux-acpi, linux-kernel
On Monday, December 25, 2017 4:57:20 PM CET Marc CAPDEVILLE wrote:
> Add a methode to allow clients to change their connection address on
> same adapter.
>
> On ACPI enumerated device, when a device support smbus alert protocol,
> there are two acpi serial bus connection description. The order in which
> connection is given is not well defined and devices may be enumerated
> with the wrong address (the first one). So let the driver detect the
> unsupported address and request i2c acpi core to choose the second one
> at probing time.
By convention, the ordering of resources in _CRS is meaningful, but it is
a contract between AML and an OS driver written to work with it.
> Signed-off-by: Marc CAPDEVILLE <m.capdeville@no-log.org>
> ---
> drivers/i2c/i2c-core-acpi.c | 50 +++++++++++++++++++++++++++++++++++++++++++++
> include/linux/i2c.h | 10 +++++++++
> 2 files changed, 60 insertions(+)
>
> diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
> index a9126b3cda61..47bc0da12055 100644
> --- a/drivers/i2c/i2c-core-acpi.c
> +++ b/drivers/i2c/i2c-core-acpi.c
> @@ -421,6 +421,56 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
> }
> EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
>
Please add a kerneldoc description of this function.
It is exported and needs to be documented properly.
> +int i2c_acpi_set_connection(struct i2c_client *client, int index)
> +{
> + struct i2c_acpi_lookup lookup;
> + struct i2c_adapter *adapter;
> + struct acpi_device *adev;
> + struct i2c_board_info info;
> + LIST_HEAD(resource_list);
> + int ret;
> +
> + if (!client)
> + return -ENODEV;
> +
> + adev = ACPI_COMPANION(&client->dev);
> + if (!adev)
> + return -ENODEV;
> +
> + memset(&info, 0, sizeof(info));
> + memset(&lookup, 0, sizeof(lookup));
> + lookup.info = &info;
> + lookup.device_handle = acpi_device_handle(adev);
> + lookup.index = index;
> +
> + ret = acpi_dev_get_resources(adev, &resource_list,
> + i2c_acpi_fill_info, &lookup);
> + acpi_dev_free_resource_list(&resource_list);
> +
> + adapter = i2c_acpi_find_adapter_by_handle(lookup.adapter_handle);
> +
> + if (ret < 0 || !info.addr)
> + return -EINVAL;
Why do you make this check after calling i2c_acpi_find_adapter_by_handle()?
> +
> + /* Only accept connection on same adapter */
> + if (adapter != client->adapter)
> + return -EINVAL;
> +
> + ret = i2c_check_addr_validity(info.addr, info.flags);
> + if (ret) {
> + dev_err(&client->dev, "Invalid %d-bit I2C address 0x%02hx\n",
> + info.flags & I2C_CLIENT_TEN ? 10 : 7, info.addr);
> + return -EINVAL;
> + }
> +
> + /* Set new address and flags */
> + client->addr = info.addr;
> + client->flags = info.flags;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(i2c_acpi_set_connection);
> +
> #ifdef CONFIG_ACPI_I2C_OPREGION
> static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
> u8 cmd, u8 *data, u8 data_len)
> diff --git a/include/linux/i2c.h b/include/linux/i2c.h
> index 0f774406fad0..618b453901da 100644
> --- a/include/linux/i2c.h
> +++ b/include/linux/i2c.h
> @@ -595,6 +595,8 @@ struct i2c_adapter {
> const struct i2c_adapter_quirks *quirks;
>
> struct irq_domain *host_notify_domain;
> +
> + struct i2c_client *smbus_ara; /* ARA for SMBUS if present */
Not used in this patch and how is it related to the other changes here?
> };
> #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
>
> @@ -839,16 +841,24 @@ static inline const struct of_device_id
> u32 i2c_acpi_find_bus_speed(struct device *dev);
> struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
> struct i2c_board_info *info);
> +
> +int i2c_acpi_set_connection(struct i2c_client *client, int index);
> #else
> static inline u32 i2c_acpi_find_bus_speed(struct device *dev)
> {
> return 0;
> }
> +
> static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
> int index, struct i2c_board_info *info)
> {
> return NULL;
> }
> +
> +static inline int i2c_acpi_set_connection(struct i2c_client *client, int index)
> +{
> + return -EINVAL;
> +}
> #endif /* CONFIG_ACPI */
>
> #endif /* _LINUX_I2C_H */
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 3/4] iio : Add cm3218 smbus ara and acpi support
[not found] ` <20171225155723.6338-3-m.capdeville-n+LsquliYkMdnm+yROfE0A@public.gmane.org>
2017-12-26 6:34 ` kbuild test robot
@ 2017-12-28 1:19 ` Rafael J. Wysocki
2017-12-29 12:54 ` Jonathan Cameron
1 sibling, 1 reply; 12+ messages in thread
From: Rafael J. Wysocki @ 2017-12-28 1:19 UTC (permalink / raw)
To: Marc CAPDEVILLE
Cc: Kevin Tsai, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, Mika Westerberg, Wolfram Sang,
linux-iio-u79uwXL29TY76Z2rM5mHXA,
linux-i2c-u79uwXL29TY76Z2rM5mHXA,
linux-acpi-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Monday, December 25, 2017 4:57:22 PM CET Marc CAPDEVILLE wrote:
> On asus T100, Capella cm3218 chip is implemented as ambiant light
> sensor. This chip expose an smbus ARA protocol device on standard
> address 0x0c. The chip is not functional before all alerts are
> acknowledged.
> On asus T100, this device is enumerated on ACPI bus and the description
> give two I2C connection. The first is the connection to the ARA device
> and the second gives the real address of the device.
>
> So, on device probe,If the i2c address is the ARA address and the
> device is enumerated via acpi, we change address of the device for
> the one in the second acpi serial bus connection.
> This free the ara address so we can register with the smbus_alert
> driver.
>
> If an interrupt resource is given, and a smbus_alert device was
> found on the adapter, we request a treaded interrupt to
> call i2c_smbus_alert_event to handle the alert.
>
> In somme case, the treaded interrupt is not schedule before the driver
> try to initialize chip registers. So if first registers access fail, we
> call i2c_smbus_alert_event() to acknowledge initial alert, then retry
> register access.
>
> Signed-off-by: Marc CAPDEVILLE <m.capdeville-n+LsquliYkMdnm+yROfE0A@public.gmane.org>
> ---
> drivers/iio/light/cm32181.c | 120 ++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 115 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
> index aebf7dd071af..96c08755e6e3 100644
> --- a/drivers/iio/light/cm32181.c
> +++ b/drivers/iio/light/cm32181.c
> @@ -18,6 +18,9 @@
> #include <linux/iio/sysfs.h>
> #include <linux/iio/events.h>
> #include <linux/init.h>
> +#include <linux/i2c-smbus.h>
> +#include <linux/acpi.h>
> +#include <linux/of_device.h>
>
> /* Registers Address */
> #define CM32181_REG_ADDR_CMD 0x00
> @@ -47,6 +50,11 @@
> #define CM32181_CALIBSCALE_RESOLUTION 1000
> #define MLUX_PER_LUX 1000
>
> +#define CM32181_ID 0x81
> +#define CM3218_ID 0x18
> +
> +#define SMBUS_ARA_ADDR 0x0c
> +
> static const u8 cm32181_reg[CM32181_CONF_REG_NUM] = {
> CM32181_REG_ADDR_CMD,
> };
> @@ -57,6 +65,7 @@ static const int als_it_value[] = {25000, 50000, 100000, 200000, 400000,
>
> struct cm32181_chip {
> struct i2c_client *client;
> + int chip_id;
> struct mutex lock;
> u16 conf_regs[CM32181_CONF_REG_NUM];
> int calibscale;
> @@ -77,11 +86,22 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181)
> s32 ret;
>
> ret = i2c_smbus_read_word_data(client, CM32181_REG_ADDR_ID);
> - if (ret < 0)
> - return ret;
> + if (ret < 0) {
> + if (cm32181->chip_id == CM3218_ID) {
> + /*
> + * On cm3218, smbus alert trigger after probing,
> + * so poll for first alert here, then retry.
> + */
> + i2c_smbus_alert_event(client);
> + ret = i2c_smbus_read_word_data(client,
> + CM32181_REG_ADDR_ID);
> + } else {
> + return ret;
> + }
> + }
>
> /* check device ID */
> - if ((ret & 0xFF) != 0x81)
> + if ((ret & 0xFF) != cm32181->chip_id)
> return -ENODEV;
>
> /* Default Values */
> @@ -297,12 +317,36 @@ static const struct iio_info cm32181_info = {
> .attrs = &cm32181_attribute_group,
> };
>
> +static void cm3218_alert(struct i2c_client *client,
> + enum i2c_alert_protocol type,
> + unsigned int data)
> +{
> + /*
> + * nothing to do for now.
> + * This is just here to acknownledge the cm3218 alert.
> + */
> +}
> +
> +static irqreturn_t cm32181_irq(int irq, void *d)
> +{
> + struct cm32181_chip *cm32181 = d;
> +
> + if (cm32181->chip_id == CM3218_ID) {
> + /* This is cm3218 chip irq, so handle the smbus alert */
> + i2c_smbus_alert_event(cm32181->client);
> + }
> +
> + return IRQ_HANDLED;
> +}
> +
> static int cm32181_probe(struct i2c_client *client,
> const struct i2c_device_id *id)
> {
> struct cm32181_chip *cm32181;
> struct iio_dev *indio_dev;
> int ret;
> + const struct of_device_id *of_id;
> + const struct acpi_device_id *acpi_id;
>
> indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*cm32181));
> if (!indio_dev) {
> @@ -322,6 +366,61 @@ static int cm32181_probe(struct i2c_client *client,
> indio_dev->name = id->name;
> indio_dev->modes = INDIO_DIRECT_MODE;
>
> + /* Lookup for chip ID from platform, acpi or of device table */
> + if (id) {
> + cm32181->chip_id = id->driver_data;
> + } else if (ACPI_COMPANION(&client->dev)) {
> + acpi_id = acpi_match_device(client->dev.driver->acpi_match_table,
> + &client->dev);
> + if (!acpi_id)
> + return -ENODEV;
> +
> + cm32181->chip_id = (kernel_ulong_t)acpi_id->driver_data;
> + } else if (client->dev.of_node) {
> + of_id = of_match_device(client->dev.driver->of_match_table,
> + &client->dev);
> + if (!of_id)
> + return -ENODEV;
> +
> + cm32181->chip_id = (kernel_ulong_t)of_id->data;
> + } else {
> + return -ENODEV;
> + }
> +
> + if (cm32181->chip_id == CM3218_ID) {
> + if (ACPI_COMPANION(&client->dev) &&
> + client->addr == SMBUS_ARA_ADDR) {
> + /*
> + * In case this device as been enumerated by acpi
> + * with the reserved smbus ARA address (first acpi
> + * connection), request change of address to the second
> + * connection.
> + */
> + ret = i2c_acpi_set_connection(client, 1);
> + if (ret)
> + return ret;
This looks super-fragile to me.
What about making the enumeration aware of the SMBUS_ARA thing and avoid
using resources corresponding to that at all?
BTW, in comments and similar always spell ACPI in capitals.
Thanks,
Rafael
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 3/4] iio : Add cm3218 smbus ara and acpi support
2017-12-25 15:57 ` [PATCH v6 3/4] iio : Add cm3218 smbus ara and acpi support Marc CAPDEVILLE
[not found] ` <20171225155723.6338-3-m.capdeville-n+LsquliYkMdnm+yROfE0A@public.gmane.org>
@ 2017-12-29 12:53 ` Jonathan Cameron
1 sibling, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2017-12-29 12:53 UTC (permalink / raw)
To: Marc CAPDEVILLE
Cc: Kevin Tsai, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, Mika Westerberg, Wolfram Sang, linux-iio,
linux-i2c, linux-acpi, linux-kernel
On Mon, 25 Dec 2017 16:57:22 +0100
Marc CAPDEVILLE <m.capdeville@no-log.org> wrote:
> On asus T100, Capella cm3218 chip is implemented as ambiant light
ambient
> sensor. This chip expose an smbus ARA protocol device on standard
> address 0x0c. The chip is not functional before all alerts are
> acknowledged.
> On asus T100, this device is enumerated on ACPI bus and the description
> give two I2C connection. The first is the connection to the ARA device
> and the second gives the real address of the device.
>
> So, on device probe,If the i2c address is the ARA address and the
if
> device is enumerated via acpi, we change address of the device for
> the one in the second acpi serial bus connection.
> This free the ara address so we can register with the smbus_alert
> driver.
>
> If an interrupt resource is given, and a smbus_alert device was
> found on the adapter, we request a treaded interrupt to
threaded
> call i2c_smbus_alert_event to handle the alert.
>
> In somme case, the treaded interrupt is not schedule before the driver
threaded
> try to initialize chip registers. So if first registers access fail, we
> call i2c_smbus_alert_event() to acknowledge initial alert, then retry
> register access.
>
> Signed-off-by: Marc CAPDEVILLE <m.capdeville@no-log.org>
The main thing that bothers me about this is it is putting a non trivial
burden on each individual driver. Perhaps we let it go like this
for now, and see how common this is. It would be possible (I think)
to do it in a fashion invisible to the client drivers, but I appreciate
that would be more complex than this. The multiple devices sharing a bus
with individual interrupt lines would need to be handled.
Minor comments inline.
Jonathan
> ---
> drivers/iio/light/cm32181.c | 120 ++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 115 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
> index aebf7dd071af..96c08755e6e3 100644
> --- a/drivers/iio/light/cm32181.c
> +++ b/drivers/iio/light/cm32181.c
> @@ -18,6 +18,9 @@
> #include <linux/iio/sysfs.h>
> #include <linux/iio/events.h>
> #include <linux/init.h>
> +#include <linux/i2c-smbus.h>
> +#include <linux/acpi.h>
> +#include <linux/of_device.h>
>
> /* Registers Address */
> #define CM32181_REG_ADDR_CMD 0x00
> @@ -47,6 +50,11 @@
> #define CM32181_CALIBSCALE_RESOLUTION 1000
> #define MLUX_PER_LUX 1000
>
> +#define CM32181_ID 0x81
> +#define CM3218_ID 0x18
> +
> +#define SMBUS_ARA_ADDR 0x0c
This isn't driver specific - to my mind belongs in the smbus header.
> +
> static const u8 cm32181_reg[CM32181_CONF_REG_NUM] = {
> CM32181_REG_ADDR_CMD,
> };
> @@ -57,6 +65,7 @@ static const int als_it_value[] = {25000, 50000, 100000, 200000, 400000,
>
> struct cm32181_chip {
> struct i2c_client *client;
> + int chip_id;
> struct mutex lock;
> u16 conf_regs[CM32181_CONF_REG_NUM];
> int calibscale;
> @@ -77,11 +86,22 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181)
> s32 ret;
>
> ret = i2c_smbus_read_word_data(client, CM32181_REG_ADDR_ID);
> - if (ret < 0)
> - return ret;
> + if (ret < 0) {
> + if (cm32181->chip_id == CM3218_ID) {
> + /*
> + * On cm3218, smbus alert trigger after probing,
> + * so poll for first alert here, then retry.
Is it a level interrupt? I'd have thought we could leave this out and let
the interrupt handler pick it up if so.
The check on the ID is rather paranoid anyway so I wouldn't worry about
it failing here.
Or are we blocked from finishing configuring the device until this is done?
> + */
> + i2c_smbus_alert_event(client);
> + ret = i2c_smbus_read_word_data(client,
> + CM32181_REG_ADDR_ID);
> + } else {
> + return ret;
> + }
> + }
>
> /* check device ID */
> - if ((ret & 0xFF) != 0x81)
> + if ((ret & 0xFF) != cm32181->chip_id)
> return -ENODEV;
>
> /* Default Values */
> @@ -297,12 +317,36 @@ static const struct iio_info cm32181_info = {
> .attrs = &cm32181_attribute_group,
> };
>
> +static void cm3218_alert(struct i2c_client *client,
> + enum i2c_alert_protocol type,
> + unsigned int data)
> +{
> + /*
> + * nothing to do for now.
> + * This is just here to acknownledge the cm3218 alert.
> + */
> +}
> +
> +static irqreturn_t cm32181_irq(int irq, void *d)
> +{
> + struct cm32181_chip *cm32181 = d;
> +
> + if (cm32181->chip_id == CM3218_ID) {
I'd move the check out and only register this handler if the chip supports
ARA in the first place. That then makes this handler
generic to any ARA device. Not sure there is a generic handler available,
but it would make sense to add one if there isn't in the smbus code.
> + /* This is cm3218 chip irq, so handle the smbus alert */
> + i2c_smbus_alert_event(cm32181->client);
> + }
The 32181 also has interrupt support - just looks like it isn't
ARA.
I guess support for that can be added here at some later date.
> +
> + return IRQ_HANDLED;
> +}
> +
> static int cm32181_probe(struct i2c_client *client,
> const struct i2c_device_id *id)
> {
> struct cm32181_chip *cm32181;
> struct iio_dev *indio_dev;
> int ret;
> + const struct of_device_id *of_id;
> + const struct acpi_device_id *acpi_id;
>
> indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*cm32181));
> if (!indio_dev) {
> @@ -322,6 +366,61 @@ static int cm32181_probe(struct i2c_client *client,
> indio_dev->name = id->name;
> indio_dev->modes = INDIO_DIRECT_MODE;
>
> + /* Lookup for chip ID from platform, acpi or of device table */
> + if (id) {
> + cm32181->chip_id = id->driver_data;
> + } else if (ACPI_COMPANION(&client->dev)) {
> + acpi_id = acpi_match_device(client->dev.driver->acpi_match_table,
> + &client->dev);
> + if (!acpi_id)
> + return -ENODEV;
> +
> + cm32181->chip_id = (kernel_ulong_t)acpi_id->driver_data;
> + } else if (client->dev.of_node) {
> + of_id = of_match_device(client->dev.driver->of_match_table,
> + &client->dev);
> + if (!of_id)
> + return -ENODEV;
> +
> + cm32181->chip_id = (kernel_ulong_t)of_id->data;
of_device_get_match_data perhaps?
I thought something similar had been proposed for acpi as well to
avoid this boiler plate, but can't find it right now so maybe that
never went anywhere.
> + } else {
> + return -ENODEV;
> + }
> +
> + if (cm32181->chip_id == CM3218_ID) {
> + if (ACPI_COMPANION(&client->dev) &&
> + client->addr == SMBUS_ARA_ADDR) {
> + /*
> + * In case this device as been enumerated by acpi
> + * with the reserved smbus ARA address (first acpi
> + * connection), request change of address to the second
> + * connection.
> + */
> + ret = i2c_acpi_set_connection(client, 1);
> + if (ret)
> + return ret;
> + }
> +
> + /* cm3218 chip require an ara device on his adapter */
> + ret = i2c_require_smbus_alert(client);
> + if (ret < 0)
> + return ret;
> +
> + /*
> + * If irq is given, request a threaded irq handler to manage
> + * smbus alert.
> + */
> + if (client->irq > 0) {
If we have a chip that needs ara and no IRQ isn't it a probe failure case?
The device won't work as I understand it.
> + ret = devm_request_threaded_irq(&client->dev,
> + client->irq,
> + NULL, cm32181_irq,
> + IRQF_ONESHOT,
> + "cm32181", cm32181);
> + if (ret)
> + return ret;
> + }
> + }
> +
> ret = cm32181_reg_init(cm32181);
> if (ret) {
> dev_err(&client->dev,
> @@ -342,25 +441,36 @@ static int cm32181_probe(struct i2c_client *client,
> }
>
> static const struct i2c_device_id cm32181_id[] = {
> - { "cm32181", 0 },
> + { "cm32181", CM32181_ID },
> + { "cm3218", CM3218_ID },
> { }
> };
>
> MODULE_DEVICE_TABLE(i2c, cm32181_id);
>
> static const struct of_device_id cm32181_of_match[] = {
> - { .compatible = "capella,cm32181" },
> + { .compatible = "capella,cm32181", (void *)CM32181_ID },
> + { .compatible = "capella,cm3218", (void *)CM3218_ID },
> { }
> };
> MODULE_DEVICE_TABLE(of, cm32181_of_match);
>
> +static const struct acpi_device_id cm32181_acpi_match[] = {
> + { "CPLM3218", CM3218_ID },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(acpi, cm32181_acpi_match);
> +
> static struct i2c_driver cm32181_driver = {
> .driver = {
> .name = "cm32181",
> .of_match_table = of_match_ptr(cm32181_of_match),
> + .acpi_match_table = ACPI_PTR(cm32181_acpi_match),
> },
> .id_table = cm32181_id,
> .probe = cm32181_probe,
> + .alert = cm3218_alert,
It's a bit ugly - I'm not sure we wouldn't be better registering
two separate i2c drivers so as not to specify the alert for devices
that don't handle it.
> };
>
> module_i2c_driver(cm32181_driver);
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 3/4] iio : Add cm3218 smbus ara and acpi support
2017-12-28 1:19 ` Rafael J. Wysocki
@ 2017-12-29 12:54 ` Jonathan Cameron
0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2017-12-29 12:54 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Marc CAPDEVILLE, Kevin Tsai, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, Mika Westerberg, Wolfram Sang, linux-iio,
linux-i2c, linux-acpi, linux-kernel
On Thu, 28 Dec 2017 02:19:55 +0100
"Rafael J. Wysocki" <rjw@rjwysocki.net> wrote:
> On Monday, December 25, 2017 4:57:22 PM CET Marc CAPDEVILLE wrote:
> > On asus T100, Capella cm3218 chip is implemented as ambiant light
> > sensor. This chip expose an smbus ARA protocol device on standard
> > address 0x0c. The chip is not functional before all alerts are
> > acknowledged.
> > On asus T100, this device is enumerated on ACPI bus and the description
> > give two I2C connection. The first is the connection to the ARA device
> > and the second gives the real address of the device.
> >
> > So, on device probe,If the i2c address is the ARA address and the
> > device is enumerated via acpi, we change address of the device for
> > the one in the second acpi serial bus connection.
> > This free the ara address so we can register with the smbus_alert
> > driver.
> >
> > If an interrupt resource is given, and a smbus_alert device was
> > found on the adapter, we request a treaded interrupt to
> > call i2c_smbus_alert_event to handle the alert.
> >
> > In somme case, the treaded interrupt is not schedule before the driver
> > try to initialize chip registers. So if first registers access fail, we
> > call i2c_smbus_alert_event() to acknowledge initial alert, then retry
> > register access.
> >
> > Signed-off-by: Marc CAPDEVILLE <m.capdeville@no-log.org>
> > ---
> > drivers/iio/light/cm32181.c | 120 ++++++++++++++++++++++++++++++++++++++++++--
> > 1 file changed, 115 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
> > index aebf7dd071af..96c08755e6e3 100644
> > --- a/drivers/iio/light/cm32181.c
> > +++ b/drivers/iio/light/cm32181.c
> > @@ -18,6 +18,9 @@
> > #include <linux/iio/sysfs.h>
> > #include <linux/iio/events.h>
> > #include <linux/init.h>
> > +#include <linux/i2c-smbus.h>
> > +#include <linux/acpi.h>
> > +#include <linux/of_device.h>
> >
> > /* Registers Address */
> > #define CM32181_REG_ADDR_CMD 0x00
> > @@ -47,6 +50,11 @@
> > #define CM32181_CALIBSCALE_RESOLUTION 1000
> > #define MLUX_PER_LUX 1000
> >
> > +#define CM32181_ID 0x81
> > +#define CM3218_ID 0x18
> > +
> > +#define SMBUS_ARA_ADDR 0x0c
> > +
> > static const u8 cm32181_reg[CM32181_CONF_REG_NUM] = {
> > CM32181_REG_ADDR_CMD,
> > };
> > @@ -57,6 +65,7 @@ static const int als_it_value[] = {25000, 50000, 100000, 200000, 400000,
> >
> > struct cm32181_chip {
> > struct i2c_client *client;
> > + int chip_id;
> > struct mutex lock;
> > u16 conf_regs[CM32181_CONF_REG_NUM];
> > int calibscale;
> > @@ -77,11 +86,22 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181)
> > s32 ret;
> >
> > ret = i2c_smbus_read_word_data(client, CM32181_REG_ADDR_ID);
> > - if (ret < 0)
> > - return ret;
> > + if (ret < 0) {
> > + if (cm32181->chip_id == CM3218_ID) {
> > + /*
> > + * On cm3218, smbus alert trigger after probing,
> > + * so poll for first alert here, then retry.
> > + */
> > + i2c_smbus_alert_event(client);
> > + ret = i2c_smbus_read_word_data(client,
> > + CM32181_REG_ADDR_ID);
> > + } else {
> > + return ret;
> > + }
> > + }
> >
> > /* check device ID */
> > - if ((ret & 0xFF) != 0x81)
> > + if ((ret & 0xFF) != cm32181->chip_id)
> > return -ENODEV;
> >
> > /* Default Values */
> > @@ -297,12 +317,36 @@ static const struct iio_info cm32181_info = {
> > .attrs = &cm32181_attribute_group,
> > };
> >
> > +static void cm3218_alert(struct i2c_client *client,
> > + enum i2c_alert_protocol type,
> > + unsigned int data)
> > +{
> > + /*
> > + * nothing to do for now.
> > + * This is just here to acknownledge the cm3218 alert.
> > + */
> > +}
> > +
> > +static irqreturn_t cm32181_irq(int irq, void *d)
> > +{
> > + struct cm32181_chip *cm32181 = d;
> > +
> > + if (cm32181->chip_id == CM3218_ID) {
> > + /* This is cm3218 chip irq, so handle the smbus alert */
> > + i2c_smbus_alert_event(cm32181->client);
> > + }
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > static int cm32181_probe(struct i2c_client *client,
> > const struct i2c_device_id *id)
> > {
> > struct cm32181_chip *cm32181;
> > struct iio_dev *indio_dev;
> > int ret;
> > + const struct of_device_id *of_id;
> > + const struct acpi_device_id *acpi_id;
> >
> > indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*cm32181));
> > if (!indio_dev) {
> > @@ -322,6 +366,61 @@ static int cm32181_probe(struct i2c_client *client,
> > indio_dev->name = id->name;
> > indio_dev->modes = INDIO_DIRECT_MODE;
> >
> > + /* Lookup for chip ID from platform, acpi or of device table */
> > + if (id) {
> > + cm32181->chip_id = id->driver_data;
> > + } else if (ACPI_COMPANION(&client->dev)) {
> > + acpi_id = acpi_match_device(client->dev.driver->acpi_match_table,
> > + &client->dev);
> > + if (!acpi_id)
> > + return -ENODEV;
> > +
> > + cm32181->chip_id = (kernel_ulong_t)acpi_id->driver_data;
> > + } else if (client->dev.of_node) {
> > + of_id = of_match_device(client->dev.driver->of_match_table,
> > + &client->dev);
> > + if (!of_id)
> > + return -ENODEV;
> > +
> > + cm32181->chip_id = (kernel_ulong_t)of_id->data;
> > + } else {
> > + return -ENODEV;
> > + }
> > +
> > + if (cm32181->chip_id == CM3218_ID) {
> > + if (ACPI_COMPANION(&client->dev) &&
> > + client->addr == SMBUS_ARA_ADDR) {
> > + /*
> > + * In case this device as been enumerated by acpi
> > + * with the reserved smbus ARA address (first acpi
> > + * connection), request change of address to the second
> > + * connection.
> > + */
> > + ret = i2c_acpi_set_connection(client, 1);
> > + if (ret)
> > + return ret;
>
> This looks super-fragile to me.
>
> What about making the enumeration aware of the SMBUS_ARA thing and avoid
> using resources corresponding to that at all?
I agree, if it can be done reasonably cleanly that would be preferable.
>
> BTW, in comments and similar always spell ACPI in capitals.
>
> Thanks,
> Rafael
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 4/4] iio : cm32181 : cosmetic cleanup
2017-12-25 15:57 ` [PATCH v6 4/4] iio : cm32181 : cosmetic cleanup Marc CAPDEVILLE
@ 2017-12-29 12:56 ` Jonathan Cameron
0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2017-12-29 12:56 UTC (permalink / raw)
To: Marc CAPDEVILLE
Cc: Kevin Tsai, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, Mika Westerberg, Wolfram Sang, linux-iio,
linux-i2c, linux-acpi, linux-kernel
On Mon, 25 Dec 2017 16:57:23 +0100
Marc CAPDEVILLE <m.capdeville@no-log.org> wrote:
> Somme cosmetic cleanup suggested by Peter Meerwald-Stadler.
>
> Macro name :
> MLUX_PER_LUX => CM32181_MLUX_PER_LUX
>
> Constante name :
> als_it_bits => cm32181_als_it_bits
> als_it_value => cm32181_als_it_value
>
> Comment :
> Registers Address => Register Addresses
>
> Suggested-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> Signed-off-by: Marc CAPDEVILLE <m.capdeville@no-log.org>
This is all fine. For my reference please add
Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
> drivers/iio/light/cm32181.c | 26 +++++++++++++-------------
> 1 file changed, 13 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
> index 96c08755e6e3..3e6b244d5cd1 100644
> --- a/drivers/iio/light/cm32181.c
> +++ b/drivers/iio/light/cm32181.c
> @@ -22,7 +22,7 @@
> #include <linux/acpi.h>
> #include <linux/of_device.h>
>
> -/* Registers Address */
> +/* Register Addresses */
> #define CM32181_REG_ADDR_CMD 0x00
> #define CM32181_REG_ADDR_ALS 0x04
> #define CM32181_REG_ADDR_STATUS 0x06
> @@ -48,7 +48,7 @@
> #define CM32181_MLUX_PER_BIT_BASE_IT 800000 /* Based on IT=800ms */
> #define CM32181_CALIBSCALE_DEFAULT 1000
> #define CM32181_CALIBSCALE_RESOLUTION 1000
> -#define MLUX_PER_LUX 1000
> +#define CM32181_MLUX_PER_LUX 1000
>
> #define CM32181_ID 0x81
> #define CM3218_ID 0x18
> @@ -59,8 +59,8 @@ static const u8 cm32181_reg[CM32181_CONF_REG_NUM] = {
> CM32181_REG_ADDR_CMD,
> };
>
> -static const int als_it_bits[] = {12, 8, 0, 1, 2, 3};
> -static const int als_it_value[] = {25000, 50000, 100000, 200000, 400000,
> +static const int cm32181_als_it_bits[] = {12, 8, 0, 1, 2, 3};
> +static const int cm32181_als_it_value[] = {25000, 50000, 100000, 200000, 400000,
> 800000};
>
> struct cm32181_chip {
> @@ -137,9 +137,9 @@ static int cm32181_read_als_it(struct cm32181_chip *cm32181, int *val2)
> als_it = cm32181->conf_regs[CM32181_REG_ADDR_CMD];
> als_it &= CM32181_CMD_ALS_IT_MASK;
> als_it >>= CM32181_CMD_ALS_IT_SHIFT;
> - for (i = 0; i < ARRAY_SIZE(als_it_bits); i++) {
> - if (als_it == als_it_bits[i]) {
> - *val2 = als_it_value[i];
> + for (i = 0; i < ARRAY_SIZE(cm32181_als_it_bits); i++) {
> + if (als_it == cm32181_als_it_bits[i]) {
> + *val2 = cm32181_als_it_value[i];
> return IIO_VAL_INT_PLUS_MICRO;
> }
> }
> @@ -162,14 +162,14 @@ static int cm32181_write_als_it(struct cm32181_chip *cm32181, int val)
> u16 als_it;
> int ret, i, n;
>
> - n = ARRAY_SIZE(als_it_value);
> + n = ARRAY_SIZE(cm32181_als_it_value);
> for (i = 0; i < n; i++)
> - if (val <= als_it_value[i])
> + if (val <= cm32181_als_it_value[i])
> break;
> if (i >= n)
> i = n - 1;
>
> - als_it = als_it_bits[i];
> + als_it = cm32181_als_it_bits[i];
> als_it <<= CM32181_CMD_ALS_IT_SHIFT;
>
> mutex_lock(&cm32181->lock);
> @@ -215,7 +215,7 @@ static int cm32181_get_lux(struct cm32181_chip *cm32181)
> lux *= ret;
> lux *= cm32181->calibscale;
> lux /= CM32181_CALIBSCALE_RESOLUTION;
> - lux /= MLUX_PER_LUX;
> + lux /= CM32181_MLUX_PER_LUX;
>
> if (lux > 0xFFFF)
> lux = 0xFFFF;
> @@ -283,9 +283,9 @@ static ssize_t cm32181_get_it_available(struct device *dev,
> {
> int i, n, len;
>
> - n = ARRAY_SIZE(als_it_value);
> + n = ARRAY_SIZE(cm32181_als_it_value);
> for (i = 0, len = 0; i < n; i++)
> - len += sprintf(buf + len, "0.%06u ", als_it_value[i]);
> + len += sprintf(buf + len, "0.%06u ", cm32181_als_it_value[i]);
> return len + sprintf(buf + len, "\n");
> }
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 2/4] i2c-smbus : Add client discovered ARA support
[not found] ` <20171225155723.6338-2-m.capdeville-n+LsquliYkMdnm+yROfE0A@public.gmane.org>
2017-12-26 1:43 ` kbuild test robot
@ 2017-12-29 13:04 ` Jonathan Cameron
1 sibling, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2017-12-29 13:04 UTC (permalink / raw)
To: Marc CAPDEVILLE
Cc: Kevin Tsai, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, Mika Westerberg, Wolfram Sang,
linux-iio-u79uwXL29TY76Z2rM5mHXA,
linux-i2c-u79uwXL29TY76Z2rM5mHXA,
linux-acpi-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Mon, 25 Dec 2017 16:57:21 +0100
Marc CAPDEVILLE <m.capdeville-n+LsquliYkMdnm+yROfE0A@public.gmane.org> wrote:
> This is from rfc by Alan Cox : https://patchwork.ozlabs.org/patch/381773
>
> The idea is as follows (extract from above rfc) :
> - If an adapter knows about its ARA and smbus alerts then the adapter
> creates its own interrupt handler as before
>
> - If a client knows it needs smbus alerts it calls
> i2c_require_smbus_alert(). This ensures that there is an ARA handler
> registered and tells the client whether the adapter is handling it
> anyway or not.
>
> - When the client learns that an ARA event has occurred it calls
> i2c_smbus_alert_event() which uses the existing ARA mechanism to kick
> things off.
A few minor things inline. I'm not sure the balance between what is
done in driver and what is in the core is quite right yet.
Jonathan
>
> Suggested-by: Alan Cox <alan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> Signed-off-by: Marc CAPDEVILLE <m.capdeville-n+LsquliYkMdnm+yROfE0A@public.gmane.org>
> ---
> drivers/i2c/i2c-smbus.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/i2c-smbus.h | 15 +++++++++
> 2 files changed, 98 insertions(+)
>
> diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c
> index 5a1dd7f13bac..e97fbafd10ef 100644
> --- a/drivers/i2c/i2c-smbus.c
> +++ b/drivers/i2c/i2c-smbus.c
> @@ -161,6 +161,9 @@ static int smbalert_probe(struct i2c_client *ara,
> }
>
> i2c_set_clientdata(ara, alert);
> +
> + ara->adapter->smbus_ara = ara;
> +
> dev_info(&adapter->dev, "supports SMBALERT#\n");
>
> return 0;
> @@ -172,6 +175,9 @@ static int smbalert_remove(struct i2c_client *ara)
> struct i2c_smbus_alert *alert = i2c_get_clientdata(ara);
>
> cancel_work_sync(&alert->alert);
> +
> + ara->adapter->smbus_ara = NULL;
> +
> return 0;
> }
>
> @@ -210,6 +216,83 @@ int i2c_handle_smbus_alert(struct i2c_client *ara)
> }
> EXPORT_SYMBOL_GPL(i2c_handle_smbus_alert);
>
> +/*
/** It looks like kernel doc to me.
> + * i2c_require_smbus_alert - Client discovered SMBus alert
> + * @c: client requiring ARA
> + *
> + * When a client needs an ARA it calls this method. If the bus adapter
> + * supports ARA and already knows how to do so then it will already have
> + * configured for ARA and this is a no-op. If not then we set up an ARA
> + * on the adapter.
> + *
> + * We *cannot* simply register a new IRQ handler for this because we might
> + * have multiple GPIO interrupts to devices all of which trigger an ARA.
I'm a little confused by this comment. Do you mean:
1. Same gpio irq is provided as as shared irq to a number of devices?
(In this case we are just aiming not to register the same IRQ multiple times
as each driver may have already done it?) If it is this case, I think we
should be pushing the irq register and checking logic to the smbus core which
can then verify if it is the same interrupt or not? (could be case 2 below
in which case we need to register another handler).
2. Different gpio irqs provided to a number of devices on same bus with
each acting as ARA interrupt? (this is hideous so I hope not - but
I would be surprised if we never see a board doing this)
> + *
> + * Return:
> + * 0 if ara support already registered
> + * 1 if call register a new smbus_alert device
> + * <0 on error
> + */
> +int i2c_require_smbus_alert(struct i2c_client *client)
> +{
> + struct i2c_adapter *adapter = client->adapter;
> + struct i2c_smbus_alert_setup setup;
> + struct i2c_client *ara;
> +
> + /* ARA is already known and handled by the adapter (ideal case)
/*
* ARA
> + * or another client has specified ARA is needed
> + */
> + if (adapter->smbus_ara)
> + return 0;
> +
> + /* Client driven, do not set up a new IRQ handler */
> + setup.irq = 0;
> +
> + ara = i2c_setup_smbus_alert(adapter, &setup);
> + if (!ara)
> + return -ENODEV;
> +
> + return 1;
> +}
> +EXPORT_SYMBOL_GPL(i2c_require_smbus_alert);
> +
> +/*
Fix this up (needs a short description) and make it kernel-doc /**
> + * i2c_smbus_alert_event
> + * @client: the client who known of a probable ara event
> + * Context: can't sleep
> + *
> + * Helper function to be called from an I2C device driver's interrupt
> + * handler. It will schedule the alert work, in turn calling the
> + * corresponding I2C device driver's alert function.
> + *
> + * It is assumed that client is an i2c client who previously call
> + * i2c_require_smbus_alert().
> + */
> +int i2c_smbus_alert_event(struct i2c_client *client)
> +{
> + struct i2c_adapter *adapter;
> + struct i2c_client *ara;
> + struct i2c_smbus_alert *alert;
> +
> + if (!client)
> + return -EINVAL;
> +
> + adapter = client->adapter;
> + if (!adapter)
> + return -EINVAL;
> +
> + ara = adapter->smbus_ara;
> + if (!ara)
> + return -EINVAL;
> +
> + alert = i2c_get_clientdata(ara);
> + if (!alert)
> + return -EINVAL;
> +
> + return schedule_work(&alert->alert);
> +}
> +EXPORT_SYMBOL_GPL(i2c_smbus_alert_event);
> +
> module_i2c_driver(smbalert_driver);
>
> MODULE_AUTHOR("Jean Delvare <jdelvare-l3A5Bk7waGM@public.gmane.org>");
> diff --git a/include/linux/i2c-smbus.h b/include/linux/i2c-smbus.h
> index fb0e040b1abb..49f362fa6ac5 100644
> --- a/include/linux/i2c-smbus.h
> +++ b/include/linux/i2c-smbus.h
> @@ -58,4 +58,19 @@ static inline int of_i2c_setup_smbus_alert(struct i2c_adapter *adap)
> }
> #endif
>
> +#if IS_ENABLED(CONFIG_I2C_SMBUS)
> +int i2c_require_smbus_alert(struct i2c_client *client);
> +int i2c_smbus_alert_event(struct i2c_client *client);
> +#else
> +static inline int i2c_require_smbus_alert(struct i2c_client *client)
> +{
> + return NULL;
> +}
> +
> +static inline int i2c_smbus_alert_event(struct i2c_client *client)
> +{
> + return NULL;
> +}
> +#endif
> +
> #endif /* _LINUX_I2C_SMBUS_H */
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2017-12-29 13:04 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-12-25 15:57 [PATCH v6 1/4] i2c-core-acpi : Add i2c_acpi_set_connection Marc CAPDEVILLE
2017-12-25 15:57 ` [PATCH v6 2/4] i2c-smbus : Add client discovered ARA support Marc CAPDEVILLE
[not found] ` <20171225155723.6338-2-m.capdeville-n+LsquliYkMdnm+yROfE0A@public.gmane.org>
2017-12-26 1:43 ` kbuild test robot
2017-12-29 13:04 ` Jonathan Cameron
2017-12-25 15:57 ` [PATCH v6 3/4] iio : Add cm3218 smbus ara and acpi support Marc CAPDEVILLE
[not found] ` <20171225155723.6338-3-m.capdeville-n+LsquliYkMdnm+yROfE0A@public.gmane.org>
2017-12-26 6:34 ` kbuild test robot
2017-12-28 1:19 ` Rafael J. Wysocki
2017-12-29 12:54 ` Jonathan Cameron
2017-12-29 12:53 ` Jonathan Cameron
2017-12-25 15:57 ` [PATCH v6 4/4] iio : cm32181 : cosmetic cleanup Marc CAPDEVILLE
2017-12-29 12:56 ` Jonathan Cameron
2017-12-28 1:04 ` [PATCH v6 1/4] i2c-core-acpi : Add i2c_acpi_set_connection Rafael J. Wysocki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).