diff mbox series

[U-Boot,1/2] misc: i2c_eeprom: add fixed partitions support

Message ID 20191028182906.5486-2-bob.beckett@collabora.com
State Accepted
Commit 1a59cb426d50082821df941146a9ec20decd118f
Delegated to: Heiko Schocher
Headers show
Series misc: i2c_eeprom: add paritioning and size query | expand

Commit Message

Robert Beckett Oct. 28, 2019, 6:29 p.m. UTC
Add ability to partition eeprom via devicetree bindings

Signed-off-by: Robert Beckett <bob.beckett@collabora.com>
---

 drivers/misc/i2c_eeprom.c | 98 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)

Comments

Heiko Schocher Nov. 20, 2019, 6:24 a.m. UTC | #1
Hello Robert,

Am 28.10.2019 um 19:29 schrieb Robert Beckett:
> Add ability to partition eeprom via devicetree bindings
> 
> Signed-off-by: Robert Beckett <bob.beckett@collabora.com>
> ---
> 
>   drivers/misc/i2c_eeprom.c | 98 +++++++++++++++++++++++++++++++++++++++
>   1 file changed, 98 insertions(+)

Reviewed-by: Heiko Schocher <hs@denx.de>

Remark:
I just wondering that there is no MTD support for i2c eeproms in
MTD (also not in linux) ... okay, flash has blocked base access,
while i2c eeprom can have byte accesses ... but does this really
is a show stopper for adding i2c eeproms to MTD layer?

You already use the MTD "fixed-partitions" property, which is fine.

May it s worth to look into using mtd layer also for i2c eeproms?

bye,
Heiko
Heiko Schocher Dec. 17, 2019, 11:59 a.m. UTC | #2
Hello Robert,

Am 28.10.2019 um 19:29 schrieb Robert Beckett:
> Add ability to partition eeprom via devicetree bindings
> 
> Signed-off-by: Robert Beckett <bob.beckett@collabora.com>
> ---
> 
>   drivers/misc/i2c_eeprom.c | 98 +++++++++++++++++++++++++++++++++++++++
>   1 file changed, 98 insertions(+)

Applied to u-boot-i2c next branch.

Thanks!

bye,
Heiko
diff mbox series

Patch

diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c
index 8f2349ad5a..7add8fcc0f 100644
--- a/drivers/misc/i2c_eeprom.c
+++ b/drivers/misc/i2c_eeprom.c
@@ -7,6 +7,7 @@ 
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <dm.h>
+#include <dm/device-internal.h>
 #include <i2c.h>
 #include <i2c_eeprom.h>
 
@@ -82,6 +83,29 @@  static int i2c_eeprom_std_ofdata_to_platdata(struct udevice *dev)
 	return 0;
 }
 
+static int i2c_eeprom_std_bind(struct udevice *dev)
+{
+	ofnode partitions = ofnode_find_subnode(dev_ofnode(dev), "partitions");
+	ofnode partition;
+	const char *name;
+
+	if (!ofnode_valid(partitions))
+		return 0;
+	if (!ofnode_device_is_compatible(partitions, "fixed-partitions"))
+		return -ENOTSUPP;
+
+	ofnode_for_each_subnode(partition, partitions) {
+		name = ofnode_get_name(partition);
+		if (!name)
+			continue;
+
+		device_bind_ofnode(dev, DM_GET_DRIVER(i2c_eeprom_partition),
+				   name, NULL, partition, NULL);
+	}
+
+	return 0;
+}
+
 static int i2c_eeprom_std_probe(struct udevice *dev)
 {
 	u8 test_byte;
@@ -117,12 +141,86 @@  U_BOOT_DRIVER(i2c_eeprom_std) = {
 	.name			= "i2c_eeprom",
 	.id			= UCLASS_I2C_EEPROM,
 	.of_match		= i2c_eeprom_std_ids,
+	.bind			= i2c_eeprom_std_bind,
 	.probe			= i2c_eeprom_std_probe,
 	.ofdata_to_platdata	= i2c_eeprom_std_ofdata_to_platdata,
 	.priv_auto_alloc_size	= sizeof(struct i2c_eeprom),
 	.ops			= &i2c_eeprom_std_ops,
 };
 
+struct i2c_eeprom_partition {
+	u32 offset;
+	u32 size;
+};
+
+static int i2c_eeprom_partition_probe(struct udevice *dev)
+{
+	return 0;
+}
+
+static int i2c_eeprom_partition_ofdata_to_platdata(struct udevice *dev)
+{
+	struct i2c_eeprom_partition *priv = dev_get_priv(dev);
+	u32 offset, size;
+	int ret;
+
+	ret = dev_read_u32(dev, "offset", &offset);
+	if (ret)
+		return ret;
+
+	ret = dev_read_u32(dev, "size", &size);
+	if (ret)
+		return ret;
+
+	priv->offset = offset;
+	priv->size = size;
+
+	return 0;
+}
+
+static int i2c_eeprom_partition_read(struct udevice *dev, int offset,
+				     u8 *buf, int size)
+{
+	struct i2c_eeprom_partition *priv = dev_get_priv(dev);
+	struct udevice *parent = dev_get_parent(dev);
+
+	if (!parent)
+		return -ENODEV;
+	if (offset + size > priv->size)
+		return -EINVAL;
+
+	return i2c_eeprom_read(parent, offset + priv->offset, buf, size);
+}
+
+static int i2c_eeprom_partition_write(struct udevice *dev, int offset,
+				      const u8 *buf, int size)
+{
+	struct i2c_eeprom_partition *priv = dev_get_priv(dev);
+	struct udevice *parent = dev_get_parent(dev);
+
+	if (!parent)
+		return -ENODEV;
+	if (offset + size > priv->size)
+		return -EINVAL;
+
+	return i2c_eeprom_write(parent, offset + priv->offset, (uint8_t *)buf,
+				size);
+}
+
+static const struct i2c_eeprom_ops i2c_eeprom_partition_ops = {
+	.read	= i2c_eeprom_partition_read,
+	.write	= i2c_eeprom_partition_write,
+};
+
+U_BOOT_DRIVER(i2c_eeprom_partition) = {
+	.name			= "i2c_eeprom_partition",
+	.id			= UCLASS_I2C_EEPROM,
+	.probe			= i2c_eeprom_partition_probe,
+	.ofdata_to_platdata	= i2c_eeprom_partition_ofdata_to_platdata,
+	.priv_auto_alloc_size	= sizeof(struct i2c_eeprom_partition),
+	.ops			= &i2c_eeprom_partition_ops,
+};
+
 UCLASS_DRIVER(i2c_eeprom) = {
 	.id		= UCLASS_I2C_EEPROM,
 	.name		= "i2c_eeprom",