From: Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
To: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>,
Ben Dooks <ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org>,
Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
Subject: [PATCH RESEND] i2c: Add support for device-tree based chip initialization
Date: Sun, 25 Nov 2012 20:53:56 -0800 [thread overview]
Message-ID: <1353905636-6697-1-git-send-email-linux@roeck-us.net> (raw)
Some I2C devices are not or not correctly initialized by the firmware.
Configuration would be possible via platform data, but that would require
per-driver platform data and a lot of code, and changing it would not be
possible without re-compiling the kernel. It is more elegant to do it
generically via devicetree properties.
Add a generic I2C devicetree property named "reg-init". This property provides
a sequence of device initialization commands to be executed prior to calling
the probe function for a given device.
Signed-off-by: Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
---
Any comments / feedback ?
.../devicetree/bindings/i2c/trivial-devices.txt | 24 +++++++
drivers/i2c/i2c-core.c | 68 ++++++++++++++++++++
2 files changed, 92 insertions(+)
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index 2f5322b..33b694e 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -2,6 +2,30 @@ This is a list of trivial i2c devices that have simple device tree
bindings, consisting only of a compatible field, an address and
possibly an interrupt line.
+Device initialization is supported with an optional reg-init property.
+This property contains a sequence of commands to be written into the chip.
+Each command consists of four values: Register, command type, mask, and data.
+ Register:
+ Register or command address
+ Command type:
+ 0: SMBus write byte
+ 1: SMBus write byte data
+ 2: SMBus write word data
+ Mask:
+ If set, the register is read and masked with this value.
+ Data:
+ Data to be written (or with original data and mask if set)
+
+Example:
+ max6696@1a {
+ compatible = "maxim,max6696";
+ reg = <0x1a>;
+ reg-init = <
+ 0x09 1 0x00 0x24
+ 0x21 1 0x00 0x05
+ >;
+ };
+
If a device needs more specific bindings, such as properties to
describe some aspect of it, there needs to be a specific binding
document for it just like any other devices.
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index a7edf98..49f8b74 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -104,6 +104,69 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
#define i2c_device_uevent NULL
#endif /* CONFIG_HOTPLUG */
+static int i2c_dev_of_init(struct i2c_client *client, struct device *dev)
+{
+ const u32 *reg_init;
+ int rlen;
+ int val;
+ u32 reg, access, mask, data;
+
+ reg_init = of_get_property(dev->of_node, "reg-init", &rlen);
+ if (!reg_init)
+ return 0;
+
+ if (!rlen || rlen % 4)
+ return -EINVAL;
+
+ while (rlen >= 4) {
+ reg = reg_init[0];
+ access = reg_init[1];
+ mask = reg_init[2];
+ data = reg_init[3];
+
+ if (reg > 0xff)
+ return -EINVAL;
+
+ switch (access) {
+ default:
+ return -EINVAL;
+ case 0:
+ val = 0;
+ break;
+ case 1:
+ val = mask ? i2c_smbus_read_byte_data(client, reg) : 0;
+ break;
+ case 2:
+ val = mask ? i2c_smbus_read_word_data(client, reg) : 0;
+ break;
+ }
+ if (val < 0)
+ return val;
+
+ val &= mask;
+ val |= data;
+
+ switch (access) {
+ default:
+ case 0:
+ val = i2c_smbus_write_byte(client, reg);
+ break;
+ case 1:
+ val = i2c_smbus_write_byte_data(client, reg, val);
+ break;
+ case 2:
+ val = i2c_smbus_write_word_data(client, reg, val);
+ break;
+ }
+ if (val < 0)
+ return val;
+
+ reg_init += 4;
+ rlen -= 4 * sizeof(u32);
+ }
+ return 0;
+}
+
static int i2c_device_probe(struct device *dev)
{
struct i2c_client *client = i2c_verify_client(dev);
@@ -122,7 +185,12 @@ static int i2c_device_probe(struct device *dev)
client->flags & I2C_CLIENT_WAKE);
dev_dbg(dev, "probe\n");
+ status = i2c_dev_of_init(client, dev);
+ if (status)
+ goto error;
+
status = driver->probe(client, i2c_match_id(driver->id_table, client));
+error:
if (status) {
client->driver = NULL;
i2c_set_clientdata(client, NULL);
--
1.7.9.7
next reply other threads:[~2012-11-26 4:53 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-11-26 4:53 Guenter Roeck [this message]
[not found] ` <1353905636-6697-1-git-send-email-linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
2012-11-26 16:43 ` [PATCH RESEND] i2c: Add support for device-tree based chip initialization Rob Herring
[not found] ` <50B39C3A.5080600-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2012-11-26 20:19 ` Guenter Roeck
[not found] ` <20121126201954.GA14617-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
2012-11-26 22:37 ` Rob Herring
[not found] ` <50B3EF21.9020201-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2012-11-26 22:58 ` Mitch Bradley
[not found] ` <50B3F41E.3020805-D5eQfiDGL7eakBO8gow8eQ@public.gmane.org>
2012-11-27 3:40 ` Guenter Roeck
2012-11-26 20:13 ` Grant Likely
2012-11-27 0:26 ` David Daney
[not found] ` <50B408BF.8050508-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2012-11-27 0:41 ` Guenter Roeck
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1353905636-6697-1-git-send-email-linux@roeck-us.net \
--to=linux-0h96xk9xttrk1umjsbkqmq@public.gmane.org \
--cc=ben-linux-elnMNo+KYs3YtjvyW6yDsg@public.gmane.org \
--cc=devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org \
--cc=khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org \
--cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).