dm: i2c: Move slave details to child platdata

At present we go through various contortions to store the I2C's chip
address in its private data. This only exists when the chip is active so
must be set up when it is probed. Until the device is probed we don't
actually record what address it will appear on.

However, now that we can support per-child platform data, we can use that
instead. This allows us to set up the address when the child is bound,
and avoid the messy contortions.

Unfortunately this is a fairly large change and it seems to be difficult to
break it down further.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
This commit is contained in:
Simon Glass 2015-01-25 08:27:13 -07:00
parent d0cff03e18
commit e6f66ec0e7
7 changed files with 41 additions and 89 deletions

View file

@ -20,7 +20,7 @@ static int i2c_compat_get_device(uint chip_addr, int alen,
ret = i2c_get_chip_for_busnum(cur_busnum, chip_addr, devp);
if (ret)
return ret;
chip = dev_get_parentdata(*devp);
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);

View file

@ -50,7 +50,7 @@ static int i2c_setup_offset(struct dm_i2c_chip *chip, uint offset,
static int i2c_read_bytewise(struct udevice *dev, uint offset,
uint8_t *buffer, int len)
{
struct dm_i2c_chip *chip = dev_get_parentdata(dev);
struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
struct udevice *bus = dev_get_parent(dev);
struct dm_i2c_ops *ops = i2c_get_ops(bus);
struct i2c_msg msg[2], *ptr;
@ -79,7 +79,7 @@ static int i2c_read_bytewise(struct udevice *dev, uint offset,
static int i2c_write_bytewise(struct udevice *dev, uint offset,
const uint8_t *buffer, int len)
{
struct dm_i2c_chip *chip = dev_get_parentdata(dev);
struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
struct udevice *bus = dev_get_parent(dev);
struct dm_i2c_ops *ops = i2c_get_ops(bus);
struct i2c_msg msg[1];
@ -102,7 +102,7 @@ static int i2c_write_bytewise(struct udevice *dev, uint offset,
int dm_i2c_read(struct udevice *dev, uint offset, uint8_t *buffer, int len)
{
struct dm_i2c_chip *chip = dev_get_parentdata(dev);
struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
struct udevice *bus = dev_get_parent(dev);
struct dm_i2c_ops *ops = i2c_get_ops(bus);
struct i2c_msg msg[2], *ptr;
@ -133,7 +133,7 @@ int dm_i2c_read(struct udevice *dev, uint offset, uint8_t *buffer, int len)
int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer,
int len)
{
struct dm_i2c_chip *chip = dev_get_parentdata(dev);
struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
struct udevice *bus = dev_get_parent(dev);
struct dm_i2c_ops *ops = i2c_get_ops(bus);
struct i2c_msg msg[1];
@ -223,7 +223,7 @@ static int i2c_probe_chip(struct udevice *bus, uint chip_addr,
static int i2c_bind_driver(struct udevice *bus, uint chip_addr, uint offset_len,
struct udevice **devp)
{
struct dm_i2c_chip chip;
struct dm_i2c_chip *chip;
char name[30], *str;
struct udevice *dev;
int ret;
@ -236,11 +236,11 @@ static int i2c_bind_driver(struct udevice *bus, uint chip_addr, uint offset_len,
goto err_bind;
/* Tell the device what we know about it */
memset(&chip, '\0', sizeof(chip));
chip.chip_addr = chip_addr;
chip.offset_len = offset_len;
ret = device_probe_child(dev, &chip);
debug("%s: device_probe_child: ret=%d\n", __func__, ret);
chip = dev_get_parent_platdata(dev);
chip->chip_addr = chip_addr;
chip->offset_len = offset_len;
ret = device_probe(dev);
debug("%s: device_probe: ret=%d\n", __func__, ret);
if (ret)
goto err_probe;
@ -248,6 +248,10 @@ static int i2c_bind_driver(struct udevice *bus, uint chip_addr, uint offset_len,
return 0;
err_probe:
/*
* If the device failed to probe, unbind it. There is nothing there
* on the bus so we don't want to leave it lying around
*/
device_unbind(dev);
err_bind:
free(str);
@ -263,15 +267,9 @@ int i2c_get_chip(struct udevice *bus, uint chip_addr, uint offset_len,
bus->name, chip_addr);
for (device_find_first_child(bus, &dev); dev;
device_find_next_child(&dev)) {
struct dm_i2c_chip store;
struct dm_i2c_chip *chip = dev_get_parentdata(dev);
struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
int ret;
if (!chip) {
chip = &store;
i2c_chip_ofdata_to_platdata(gd->fdt_blob,
dev->of_offset, chip);
}
if (chip->chip_addr == chip_addr) {
ret = device_probe(dev);
debug("found, ret=%d\n", ret);
@ -367,7 +365,7 @@ int i2c_get_bus_speed(struct udevice *bus)
int i2c_set_chip_flags(struct udevice *dev, uint flags)
{
struct udevice *bus = dev->parent;
struct dm_i2c_chip *chip = dev_get_parentdata(dev);
struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
struct dm_i2c_ops *ops = i2c_get_ops(bus);
int ret;
@ -383,7 +381,7 @@ int i2c_set_chip_flags(struct udevice *dev, uint flags)
int i2c_get_chip_flags(struct udevice *dev, uint *flagsp)
{
struct dm_i2c_chip *chip = dev_get_parentdata(dev);
struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
*flagsp = chip->flags;
@ -392,7 +390,7 @@ int i2c_get_chip_flags(struct udevice *dev, uint *flagsp)
int i2c_set_chip_offset_len(struct udevice *dev, uint offset_len)
{
struct dm_i2c_chip *chip = dev_get_parentdata(dev);
struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
if (offset_len > I2C_MAX_OFFSET_LEN)
return -EINVAL;
@ -444,19 +442,31 @@ static int i2c_post_probe(struct udevice *dev)
return i2c_set_bus_speed(dev, i2c->speed_hz);
}
int i2c_post_bind(struct udevice *dev)
static int i2c_post_bind(struct udevice *dev)
{
/* Scan the bus for devices */
return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
}
static int i2c_child_post_bind(struct udevice *dev)
{
struct dm_i2c_chip *plat = dev_get_parent_platdata(dev);
if (dev->of_offset == -1)
return 0;
return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, plat);
}
UCLASS_DRIVER(i2c) = {
.id = UCLASS_I2C,
.name = "i2c",
.flags = DM_UC_FLAG_SEQ_ALIAS,
.per_device_auto_alloc_size = sizeof(struct dm_i2c_bus),
.post_bind = i2c_post_bind,
.post_probe = i2c_post_probe,
.per_device_auto_alloc_size = sizeof(struct dm_i2c_bus),
.per_child_platdata_auto_alloc_size = sizeof(struct dm_i2c_chip),
.child_post_bind = i2c_child_post_bind,
};
UCLASS_DRIVER(i2c_generic) = {

View file

@ -145,16 +145,6 @@ static int uniphier_fi2c_remove(struct udevice *dev)
return 0;
}
static int uniphier_fi2c_child_pre_probe(struct udevice *dev)
{
struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
if (dev->of_offset == -1)
return 0;
return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
i2c_chip);
}
static int wait_for_irq(struct uniphier_fi2c_dev *dev, u32 flags,
bool *stop)
{
@ -372,8 +362,6 @@ U_BOOT_DRIVER(uniphier_fi2c) = {
.of_match = uniphier_fi2c_of_match,
.probe = uniphier_fi2c_probe,
.remove = uniphier_fi2c_remove,
.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
.child_pre_probe = uniphier_fi2c_child_pre_probe,
.priv_auto_alloc_size = sizeof(struct uniphier_fi2c_dev),
.ops = &uniphier_fi2c_ops,
};

View file

@ -75,16 +75,6 @@ static int uniphier_i2c_remove(struct udevice *dev)
return 0;
}
static int uniphier_i2c_child_pre_probe(struct udevice *dev)
{
struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
if (dev->of_offset == -1)
return 0;
return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
i2c_chip);
}
static int send_and_recv_byte(struct uniphier_i2c_dev *dev, u32 dtrm)
{
writel(dtrm, &dev->regs->dtrm);
@ -232,8 +222,6 @@ U_BOOT_DRIVER(uniphier_i2c) = {
.of_match = uniphier_i2c_of_match,
.probe = uniphier_i2c_probe,
.remove = uniphier_i2c_remove,
.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
.child_pre_probe = uniphier_i2c_child_pre_probe,
.priv_auto_alloc_size = sizeof(struct uniphier_i2c_dev),
.ops = &uniphier_i2c_ops,
};

View file

@ -25,24 +25,24 @@ struct dm_sandbox_i2c_emul_priv {
static int get_emul(struct udevice *dev, struct udevice **devp,
struct dm_i2c_ops **opsp)
{
struct dm_i2c_chip *priv;
struct dm_i2c_chip *plat;
int ret;
*devp = NULL;
*opsp = NULL;
priv = dev_get_parentdata(dev);
if (!priv->emul) {
plat = dev_get_parent_platdata(dev);
if (!plat->emul) {
ret = dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset,
false);
if (ret)
return ret;
ret = device_get_child(dev, 0, &priv->emul);
ret = device_get_child(dev, 0, &plat->emul);
if (ret)
return ret;
}
*devp = priv->emul;
*opsp = i2c_get_ops(priv->emul);
*devp = plat->emul;
*opsp = i2c_get_ops(plat->emul);
return 0;
}
@ -82,20 +82,6 @@ static const struct dm_i2c_ops sandbox_i2c_ops = {
.xfer = sandbox_i2c_xfer,
};
static int sandbox_i2c_child_pre_probe(struct udevice *dev)
{
struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
/* Ignore our test address */
if (i2c_chip->chip_addr == SANDBOX_I2C_TEST_ADDR)
return 0;
if (dev->of_offset == -1)
return 0;
return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
i2c_chip);
}
static const struct udevice_id sandbox_i2c_ids[] = {
{ .compatible = "sandbox,i2c" },
{ }
@ -105,7 +91,5 @@ U_BOOT_DRIVER(i2c_sandbox) = {
.name = "i2c_sandbox",
.id = UCLASS_I2C,
.of_match = sandbox_i2c_ids,
.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
.child_pre_probe = sandbox_i2c_child_pre_probe,
.ops = &sandbox_i2c_ops,
};

View file

@ -484,21 +484,6 @@ static const struct dm_i2c_ops tegra_i2c_ops = {
.set_bus_speed = tegra_i2c_set_bus_speed,
};
static int tegra_i2c_child_pre_probe(struct udevice *dev)
{
struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
if (dev->of_offset == -1)
return 0;
return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
i2c_chip);
}
static int tegra_i2c_ofdata_to_platdata(struct udevice *dev)
{
return 0;
}
static const struct udevice_id tegra_i2c_ids[] = {
{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
{ .compatible = "nvidia,tegra20-i2c", .data = TYPE_STD },
@ -510,10 +495,7 @@ U_BOOT_DRIVER(i2c_tegra) = {
.name = "i2c_tegra",
.id = UCLASS_I2C,
.of_match = tegra_i2c_ids,
.ofdata_to_platdata = tegra_i2c_ofdata_to_platdata,
.probe = tegra_i2c_probe,
.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
.child_pre_probe = tegra_i2c_child_pre_probe,
.priv_auto_alloc_size = sizeof(struct i2c_bus),
.ops = &tegra_i2c_ops,
};

View file

@ -39,8 +39,8 @@ enum dm_i2c_chip_flags {
* An I2C chip is a device on the I2C bus. It sits at a particular address
* and normally supports 7-bit or 10-bit addressing.
*
* To obtain this structure, use dev_get_parentdata(dev) where dev is the
* chip to examine.
* To obtain this structure, use dev_get_parent_platdata(dev) where dev is
* the chip to examine.
*
* @chip_addr: Chip address on bus
* @offset_len: Length of offset in bytes. A single byte offset can