[U-Boot] [PATCH v4 0/4] dm: i2c: Convert cros_ec_i2c over to driver model

This series sits on top of Przemyslaw's recent driver model conversion for Exynos. It changes the cros_ec_i2c driver to use driver model.
Also a new device tree property is added to support offset length, a U-Boot I2C concept but a feature of the hardware.
Changes in v4: - Bring in the correct patch version - Add patches to support offset length in device tree - Rebase on top of exynos I2C series
Simon Glass (4): dm: i2c: dts: Support an offset-len device tree property dm: exynos: dts: Set the offset length for cros_ec dm: i2c: Add two more I2C init functions to the compatibility layer dm: cros_ec: Convert cros_ec_i2c over to driver model
arch/arm/dts/exynos5250-snow.dts | 1 + doc/device-tree-bindings/i2c/i2c.txt | 28 ++++++++++++ drivers/i2c/i2c-uclass-compat.c | 16 +++++-- drivers/i2c/i2c-uclass.c | 3 +- drivers/misc/cros_ec_i2c.c | 82 +++++++++++++----------------------- include/configs/snow.h | 1 + include/i2c.h | 17 +++++++- 7 files changed, 90 insertions(+), 58 deletions(-) create mode 100644 doc/device-tree-bindings/i2c/i2c.txt

Since U-Boot can support different offset lengths (0-4 bytes), add a device tree property to specify this. This avoids hard-coding it in the driver.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None
doc/device-tree-bindings/i2c/i2c.txt | 28 ++++++++++++++++++++++++++++ drivers/i2c/i2c-uclass.c | 3 ++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 doc/device-tree-bindings/i2c/i2c.txt
diff --git a/doc/device-tree-bindings/i2c/i2c.txt b/doc/device-tree-bindings/i2c/i2c.txt new file mode 100644 index 0000000..ea918dd --- /dev/null +++ b/doc/device-tree-bindings/i2c/i2c.txt @@ -0,0 +1,28 @@ +U-Boot I2C +---------- + +U-Boot's I2C model has the concept of an offset within a chip (I2C target +device). The offset can be up to 4 bytes long, but is normally 1 byte, +meaning that offsets from 0 to 255 are supported by the chip. This often +corresponds to register numbers. + +Apart from the controller-specific I2C bindings, U-Boot supports a special +property which allows the chip offset length to be selected. + +Optional properties: +- u-boot,i2c-offset-len - length of chip offset in bytes. If omitted the + default value of 1 is used. + + +Example +------- + +i2c4: i2c@12ca0000 { + cros-ec@1e { + reg = <0x1e>; + compatible = "google,cros-ec"; + i2c-max-frequency = <100000>; + u-boot,i2c-offset-len = <0>; + ec-interrupt = <&gpx1 6 GPIO_ACTIVE_LOW>; + }; +}; diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c index 393cd6f..eafa457 100644 --- a/drivers/i2c/i2c-uclass.c +++ b/drivers/i2c/i2c-uclass.c @@ -420,7 +420,8 @@ int i2c_deblock(struct udevice *bus) int i2c_chip_ofdata_to_platdata(const void *blob, int node, struct dm_i2c_chip *chip) { - chip->offset_len = 1; /* default */ + chip->offset_len = fdtdec_get_int(gd->fdt_blob, node, + "u-boot,i2c-offset-len", 1); chip->flags = 0; chip->chip_addr = fdtdec_get_int(gd->fdt_blob, node, "reg", -1); if (chip->chip_addr == -1) {

On 26 January 2015 at 20:29, Simon Glass sjg@chromium.org wrote:
Since U-Boot can support different offset lengths (0-4 bytes), add a device tree property to specify this. This avoids hard-coding it in the driver.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v4: None
doc/device-tree-bindings/i2c/i2c.txt | 28 ++++++++++++++++++++++++++++ drivers/i2c/i2c-uclass.c | 3 ++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 doc/device-tree-bindings/i2c/i2c.txt
Applied to u-boot-dm.

The EC has no concept of offset, so use a value of 0.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: None
arch/arm/dts/exynos5250-snow.dts | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm/dts/exynos5250-snow.dts b/arch/arm/dts/exynos5250-snow.dts index 649e4bd..7d8be69 100644 --- a/arch/arm/dts/exynos5250-snow.dts +++ b/arch/arm/dts/exynos5250-snow.dts @@ -44,6 +44,7 @@ reg = <0x1e>; compatible = "google,cros-ec"; i2c-max-frequency = <100000>; + u-boot,i2c-offset-len = <0>; ec-interrupt = <&gpx1 6 GPIO_ACTIVE_LOW>; };

On 26 January 2015 at 20:29, Simon Glass sjg@chromium.org wrote:
The EC has no concept of offset, so use a value of 0.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v4: None
arch/arm/dts/exynos5250-snow.dts | 1 + 1 file changed, 1 insertion(+)
Applied to u-boot-dm.

These functions are useful in case the board calls them. Also fix a missing parameter caused by applying the wrong patch (actually I failed to send v2 and applied v1 by mistake).
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: - Bring in the correct patch version
drivers/i2c/i2c-uclass-compat.c | 16 +++++++++++++--- include/i2c.h | 17 ++++++++++++++++- 2 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/drivers/i2c/i2c-uclass-compat.c b/drivers/i2c/i2c-uclass-compat.c index 11239da..223f238 100644 --- a/drivers/i2c/i2c-uclass-compat.c +++ b/drivers/i2c/i2c-uclass-compat.c @@ -17,13 +17,13 @@ static int i2c_compat_get_device(uint chip_addr, int alen, struct dm_i2c_chip *chip; int ret;
- ret = i2c_get_chip_for_busnum(cur_busnum, chip_addr, devp); + ret = i2c_get_chip_for_busnum(cur_busnum, chip_addr, alen, devp); if (ret) return ret; chip = dev_get_parent_platdata(*devp); if (chip->offset_len != alen) { - printf("Requested alen %d does not match chip offset_len %d\n", - alen, chip->offset_len); + printf("I2C chip %x: requested alen %d does not match chip offset_len %d\n", + chip_addr, alen, chip->offset_len); return -EADDRNOTAVAIL; }
@@ -96,3 +96,13 @@ int i2c_set_bus_num(unsigned int bus)
return 0; } + +void i2c_init(int speed, int slaveaddr) +{ + /* Nothing to do here - the init happens through driver model */ +} + +void board_i2c_init(const void *blob) +{ + /* Nothing to do here - the init happens through driver model */ +} diff --git a/include/i2c.h b/include/i2c.h index 95d6f28..27fe00f 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -225,7 +225,7 @@ int i2c_get_bus_num_fdt(int node); unsigned int i2c_get_bus_num(void);
/** - * i2c_set_bus_num(): Compatibility function for driver model + * i2c_set_bus_num() - Compatibility function for driver model * * Sets the 'current' bus */ @@ -241,6 +241,21 @@ static inline unsigned int I2C_GET_BUS(void) return i2c_get_bus_num(); }
+/** + * i2c_init() - Compatibility function for driver model + * + * This function does nothing. + */ +void i2c_init(int speed, int slaveaddr); + +/** + * board_i2c_init() - Compatibility function for driver model + * + * @param blob Device tree blbo + * @return the number of I2C bus + */ +void board_i2c_init(const void *blob); + #endif
/*

On 26 January 2015 at 20:29, Simon Glass sjg@chromium.org wrote:
These functions are useful in case the board calls them. Also fix a missing parameter caused by applying the wrong patch (actually I failed to send v2 and applied v1 by mistake).
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v4:
- Bring in the correct patch version
drivers/i2c/i2c-uclass-compat.c | 16 +++++++++++++--- include/i2c.h | 17 ++++++++++++++++- 2 files changed, 29 insertions(+), 4 deletions(-)
(Rebased on Przemyslaw's later patch since it was part of a series)
Applied to u-boot-dm.

Move this driver to use driver model and update the snow configuration to match.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v4: - Add patches to support offset length in device tree - Rebase on top of exynos I2C series
drivers/misc/cros_ec_i2c.c | 82 ++++++++++++++++------------------------------ include/configs/snow.h | 1 + 2 files changed, 30 insertions(+), 53 deletions(-)
diff --git a/drivers/misc/cros_ec_i2c.c b/drivers/misc/cros_ec_i2c.c index 513cdb1..f9bc975 100644 --- a/drivers/misc/cros_ec_i2c.c +++ b/drivers/misc/cros_ec_i2c.c @@ -14,6 +14,7 @@ */
#include <common.h> +#include <dm.h> #include <i2c.h> #include <cros_ec.h>
@@ -23,11 +24,11 @@ #define debug_trace(fmt, b...) #endif
-int cros_ec_i2c_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, - const uint8_t *dout, int dout_len, - uint8_t **dinp, int din_len) +static int cros_ec_i2c_command(struct udevice *udev, uint8_t cmd, + int cmd_version, const uint8_t *dout, + int dout_len, uint8_t **dinp, int din_len) { - int old_bus = 0; + struct cros_ec_dev *dev = udev->uclass_priv; /* version8, cmd8, arglen8, out8[dout_len], csum8 */ int out_bytes = dout_len + 4; /* response8, arglen8, in8[din_len], checksum8 */ @@ -37,8 +38,6 @@ int cros_ec_i2c_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, uint8_t *in_ptr; int len, csum, ret;
- old_bus = i2c_get_bus_num(); - /* * Sanity-check I/O sizes given transaction overhead in internal * buffers. @@ -86,36 +85,24 @@ int cros_ec_i2c_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, *ptr++ = (uint8_t) cros_ec_calc_checksum(dev->dout, dout_len + 3);
- /* Set to the proper i2c bus */ - if (i2c_set_bus_num(dev->bus_num)) { - debug("%s: Cannot change to I2C bus %d\n", __func__, - dev->bus_num); - return -1; - } - /* Send output data */ cros_ec_dump_data("out", -1, dev->dout, out_bytes); - ret = i2c_write(dev->addr, 0, 0, dev->dout, out_bytes); + ret = dm_i2c_write(udev, 0, dev->dout, out_bytes); if (ret) { - debug("%s: Cannot complete I2C write to 0x%x\n", - __func__, dev->addr); + debug("%s: Cannot complete I2C write to %s\n", __func__, + udev->name); ret = -1; }
if (!ret) { - ret = i2c_read(dev->addr, 0, 0, in_ptr, in_bytes); + ret = dm_i2c_read(udev, 0, in_ptr, in_bytes); if (ret) { - debug("%s: Cannot complete I2C read from 0x%x\n", - __func__, dev->addr); + debug("%s: Cannot complete I2C read from %s\n", + __func__, udev->name); ret = -1; } }
- /* Return to original bus number */ - i2c_set_bus_num(old_bus); - if (ret) - return ret; - if (*in_ptr != EC_RES_SUCCESS) { debug("%s: Received bad result code %d\n", __func__, *in_ptr); return -(int)*in_ptr; @@ -142,35 +129,24 @@ int cros_ec_i2c_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version, return din_len; }
-int cros_ec_i2c_decode_fdt(struct cros_ec_dev *dev, const void *blob) +static int cros_ec_probe(struct udevice *dev) { - /* Decode interface-specific FDT params */ - dev->max_frequency = fdtdec_get_int(blob, dev->node, - "i2c-max-frequency", 100000); - dev->bus_num = i2c_get_bus_num_fdt(dev->parent_node); - if (dev->bus_num == -1) { - debug("%s: Failed to read bus number\n", __func__); - return -1; - } - dev->addr = fdtdec_get_int(blob, dev->node, "reg", -1); - if (dev->addr == -1) { - debug("%s: Failed to read device address\n", __func__); - return -1; - } - - return 0; + return cros_ec_register(dev); }
-/** - * Initialize I2C protocol. - * - * @param dev CROS_EC device - * @param blob Device tree blob - * @return 0 if ok, -1 on error - */ -int cros_ec_i2c_init(struct cros_ec_dev *dev, const void *blob) -{ - i2c_init(dev->max_frequency, dev->addr); - - return 0; -} +static struct dm_cros_ec_ops cros_ec_ops = { + .command = cros_ec_i2c_command, +}; + +static const struct udevice_id cros_ec_ids[] = { + { .compatible = "google,cros-ec" }, + { } +}; + +U_BOOT_DRIVER(cros_ec_i2c) = { + .name = "cros_ec", + .id = UCLASS_CROS_EC, + .of_match = cros_ec_ids, + .probe = cros_ec_probe, + .ops = &cros_ec_ops, +}; diff --git a/include/configs/snow.h b/include/configs/snow.h index 7eaa586..ce6676e 100644 --- a/include/configs/snow.h +++ b/include/configs/snow.h @@ -22,6 +22,7 @@
#define CONFIG_CROS_EC_I2C /* Support CROS_EC over I2C */ #define CONFIG_POWER_TPS65090_I2C +#define CONFIG_DM_CROS_EC
#define CONFIG_BOARD_COMMON #define CONFIG_ARCH_EARLY_INIT_R

On 26 January 2015 at 20:29, Simon Glass sjg@chromium.org wrote:
Move this driver to use driver model and update the snow configuration to match.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v4:
- Add patches to support offset length in device tree
- Rebase on top of exynos I2C series
drivers/misc/cros_ec_i2c.c | 82 ++++++++++++++++------------------------------ include/configs/snow.h | 1 + 2 files changed, 30 insertions(+), 53 deletions(-)
Applied to u-boot-dm.
participants (1)
-
Simon Glass