i2c: Declare more i2c_adapter parent devices
[linux-drm-fsl-dcu.git] / drivers / i2c / busses / scx200_acb.c
index 22a3eda04166e3b7841d0fd5c897aa16851b20fa..0b082c5a01956d7e98b52329ad920b69693793e3 100644 (file)
@@ -184,21 +184,21 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
                break;
 
        case state_read:
-               /* Set ACK if receiving the last byte */
-               if (iface->len == 1)
+               /* Set ACK if _next_ byte will be the last one */
+               if (iface->len == 2)
                        outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1);
                else
                        outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1);
 
-               *iface->ptr++ = inb(ACBSDA);
-               --iface->len;
-
-               if (iface->len == 0) {
+               if (iface->len == 1) {
                        iface->result = 0;
                        iface->state = state_idle;
                        outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
                }
 
+               *iface->ptr++ = inb(ACBSDA);
+               --iface->len;
+
                break;
 
        case state_write:
@@ -232,7 +232,7 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
        unsigned long timeout;
 
        timeout = jiffies + POLL_TIMEOUT;
-       while (time_before(jiffies, timeout)) {
+       while (1) {
                status = inb(ACBST);
 
                /* Reset the status register to avoid the hang */
@@ -242,7 +242,10 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
                        scx200_acb_machine(iface, status);
                        return;
                }
-               yield();
+               if (time_after(jiffies, timeout))
+                       break;
+               cpu_relax();
+               cond_resched();
        }
 
        dev_err(&iface->adapter.dev, "timeout in state %s\n",
@@ -307,8 +310,12 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
                buffer = (u8 *)&cur_word;
                break;
 
-       case I2C_SMBUS_BLOCK_DATA:
+       case I2C_SMBUS_I2C_BLOCK_DATA:
+               if (rw == I2C_SMBUS_READ)
+                       data->block[0] = I2C_SMBUS_BLOCK_MAX; /* For now */
                len = data->block[0];
+               if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
+                       return -EINVAL;
                buffer = &data->block[1];
                break;
 
@@ -372,11 +379,11 @@ static u32 scx200_acb_func(struct i2c_adapter *adapter)
 {
        return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
               I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
-              I2C_FUNC_SMBUS_BLOCK_DATA;
+              I2C_FUNC_SMBUS_I2C_BLOCK;
 }
 
 /* For now, we only handle combined mode (smbus) */
-static struct i2c_algorithm scx200_acb_algorithm = {
+static const struct i2c_algorithm scx200_acb_algorithm = {
        .smbus_xfer     = scx200_acb_smbus_xfer,
        .functionality  = scx200_acb_func,
 };
@@ -421,7 +428,7 @@ static __init int scx200_acb_probe(struct scx200_acb_iface *iface)
 }
 
 static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
-               int index)
+               struct device *dev, int index)
 {
        struct scx200_acb_iface *iface;
        struct i2c_adapter *adapter;
@@ -439,6 +446,7 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
        adapter->id = I2C_HW_SMBUS_SCX200;
        adapter->algo = &scx200_acb_algorithm;
        adapter->class = I2C_CLASS_HWMON;
+       adapter->dev.parent = dev;
 
        mutex_init(&iface->mutex);
 
@@ -479,7 +487,7 @@ static __init int scx200_create_pci(const char *text, struct pci_dev *pdev,
        struct scx200_acb_iface *iface;
        int rc;
 
-       iface = scx200_create_iface(text, 0);
+       iface = scx200_create_iface(text, &pdev->dev, 0);
 
        if (iface == NULL)
                return -ENOMEM;
@@ -487,11 +495,12 @@ static __init int scx200_create_pci(const char *text, struct pci_dev *pdev,
        iface->pdev = pdev;
        iface->bar = bar;
 
-       pci_enable_device_bars(iface->pdev, 1 << iface->bar);
+       rc = pci_enable_device_bars(iface->pdev, 1 << iface->bar);
+       if (rc)
+               goto errout_free;
 
        rc = pci_request_region(iface->pdev, iface->bar, iface->adapter.name);
-
-       if (rc != 0) {
+       if (rc) {
                printk(KERN_ERR NAME ": can't allocate PCI BAR %d\n",
                                iface->bar);
                goto errout_free;
@@ -516,7 +525,7 @@ static int __init scx200_create_isa(const char *text, unsigned long base,
        struct scx200_acb_iface *iface;
        int rc;
 
-       iface = scx200_create_iface(text, index);
+       iface = scx200_create_iface(text, NULL, index);
 
        if (iface == NULL)
                return -ENOMEM;