static int stu300_await_event(struct stu300_dev *dev, enum stu300_event mr_event) { int ret; if (unlikely(irqs_disabled())) { dev_err(&dev->pdev->dev, "irqs are disabled on this " "system!\n"); return -EIO; } spin_lock_irq(&dev->cmd_issue_lock); dev->cmd_err = STU300_ERROR_NONE; dev->cmd_event = mr_event; init_completion(&dev->cmd_complete); stu300_irq_enable(dev); spin_unlock_irq(&dev->cmd_issue_lock); ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, STU300_TIMEOUT); if (ret < 0) { dev_err(&dev->pdev->dev, "wait_for_completion_interruptible_timeout()" "returned %d waiting for event %04x\n", ret, mr_event); return ret; } if (ret == 0) { if (mr_event != STU300_EVENT_6) { dev_err(&dev->pdev->dev, "controller " "timed out waiting for event %d, reinit " "hardware\n", mr_event); (void) stu300_init_hw(dev); } return -ETIMEDOUT; } if (dev->cmd_err != STU300_ERROR_NONE) { if (mr_event != STU300_EVENT_6) { dev_err(&dev->pdev->dev, "controller " "error (await_event) %d waiting for event %d, " "reinit hardware\n", dev->cmd_err, mr_event); (void) stu300_init_hw(dev); } return -EIO; } return 0; }
static int stu300_await_event(struct stu300_dev *dev, enum stu300_event mr_event) { int ret; if (unlikely(irqs_disabled())) { /* TODO: implement polling for this case if need be. */ dev_err(&dev->pdev->dev, "irqs are disabled on this " "system!\n"); return -EIO; } /* Is it already here? */ spin_lock_irq(&dev->cmd_issue_lock); dev->cmd_err = STU300_ERROR_NONE; dev->cmd_event = mr_event; init_completion(&dev->cmd_complete); /* Turn on the I2C interrupt for current operation */ stu300_irq_enable(dev); /* Unlock the command block and wait for the event to occur */ spin_unlock_irq(&dev->cmd_issue_lock); ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, STU300_TIMEOUT); if (ret < 0) { dev_err(&dev->pdev->dev, "wait_for_completion_interruptible_timeout()" "returned %d waiting for event %04x\n", ret, mr_event); return ret; } if (ret == 0) { if (mr_event != STU300_EVENT_6) { dev_err(&dev->pdev->dev, "controller " "timed out waiting for event %d, reinit " "hardware\n", mr_event); (void) stu300_init_hw(dev); } return -ETIMEDOUT; } if (dev->cmd_err != STU300_ERROR_NONE) { if (mr_event != STU300_EVENT_6) { dev_err(&dev->pdev->dev, "controller " "error (await_event) %d waiting for event %d, " "reinit hardware\n", dev->cmd_err, mr_event); (void) stu300_init_hw(dev); } return -EIO; } return 0; }
static int stu300_start_and_await_event(struct stu300_dev *dev, u8 cr_value, enum stu300_event mr_event) { int ret; if (unlikely(irqs_disabled())) { WARN(1, "irqs are disabled, cannot poll for event\n"); return -EIO; } spin_lock_irq(&dev->cmd_issue_lock); init_completion(&dev->cmd_complete); dev->cmd_err = STU300_ERROR_NONE; dev->cmd_event = mr_event; spin_unlock_irq(&dev->cmd_issue_lock); cr_value |= I2C_CR_INTERRUPT_ENABLE; stu300_wr8(cr_value, dev->virtbase + I2C_CR); ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, STU300_TIMEOUT); if (ret < 0) { dev_err(&dev->pdev->dev, "wait_for_completion_interruptible_timeout() " "returned %d waiting for event %04x\n", ret, mr_event); return ret; } if (ret == 0) { dev_err(&dev->pdev->dev, "controller timed out " "waiting for event %d, reinit hardware\n", mr_event); (void) stu300_init_hw(dev); return -ETIMEDOUT; } if (dev->cmd_err != STU300_ERROR_NONE) { dev_err(&dev->pdev->dev, "controller (start) " "error %d waiting for event %d, reinit hardware\n", dev->cmd_err, mr_event); (void) stu300_init_hw(dev); return -EIO; } return 0; }
static int stu300_wait_while_busy(struct stu300_dev *dev) { unsigned long timeout; int i; for (i = 0; i < BUSY_RELEASE_ATTEMPTS; i++) { timeout = jiffies + STU300_TIMEOUT; while (!time_after(jiffies, timeout)) { if ((stu300_r8(dev->virtbase + I2C_SR1) & I2C_SR1_BUSY_IND) == 0) return 0; msleep(1); } dev_err(&dev->pdev->dev, "transaction timed out " "waiting for device to be free (not busy). " "Attempt: %d\n", i+1); dev_err(&dev->pdev->dev, "base address = " "0x%08x, reinit hardware\n", (u32) dev->virtbase); (void) stu300_init_hw(dev); } dev_err(&dev->pdev->dev, "giving up after %d attempts " "to reset the bus.\n", BUSY_RELEASE_ATTEMPTS); return -ETIMEDOUT; }