int i2c_dw_resume(struct dw_i2c_dev *dev, bool runtime) { if (!dev->shared_host) i2c_dw_init(dev); if (!runtime) { dev->status |= STATUS_POWERON; up(&dev->lock); } return 0; }
static ssize_t store_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct dw_i2c_dev *i2c = dev_get_drvdata(dev); int ret = 0; char mode[MODE_NAME_SIZE]; if (sscanf(buf, "%9s", mode) != 1) { dev_err(dev, "input I2C speed mode: std/fast\n"); return -EINVAL; } down(&i2c->lock); pm_runtime_get_sync(i2c->dev); if (!strncmp("std", mode, MODE_NAME_SIZE)) { i2c->master_cfg &= ~DW_IC_SPEED_MASK; i2c->master_cfg |= DW_IC_CON_SPEED_STD; } else if (!strncmp("fast", mode, MODE_NAME_SIZE)) { i2c->fast_plus = 0; i2c->master_cfg &= ~DW_IC_SPEED_MASK; i2c->master_cfg |= DW_IC_CON_SPEED_FAST; } else if (!strncmp("fast+", mode, MODE_NAME_SIZE)) { i2c->fast_plus = 1; i2c->master_cfg &= ~DW_IC_SPEED_MASK; i2c->master_cfg |= DW_IC_CON_SPEED_FAST; } else if (!strncmp("high", mode, MODE_NAME_SIZE)) { i2c->master_cfg &= ~DW_IC_SPEED_MASK; i2c->master_cfg |= DW_IC_CON_SPEED_HIGH; } else { ret = -EINVAL; goto out; } /* init to configure the i2c master */ i2c_dw_init(i2c); dev_info(dev, "I2C speed mode changed to %s\n", mode); out: pm_runtime_mark_last_busy(i2c->dev); pm_runtime_put_autosuspend(i2c->dev); up(&i2c->lock); return (ret < 0) ? ret : size; }
if (!dev->sda_hold_time && ht) { u32 ic_clk = dev->get_clk_rate_khz(dev); dev->sda_hold_time = div_u64((u64)ic_clk * ht + 500000, 1000000); } if (!dev->tx_fifo_depth) { u32 param1 = i2c_dw_read_comp_param(dev); dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1; dev->rx_fifo_depth = ((param1 >> 8) & 0xff) + 1; dev->adapter.nr = pdev->id; } r = i2c_dw_init(dev); if (r) return r; i2c_dw_disable_int(dev); r = devm_request_irq(&pdev->dev, dev->irq, i2c_dw_isr, IRQF_SHARED, pdev->name, dev); if (r) { dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); return r; } adap = &dev->adapter; i2c_set_adapdata(adap, dev); adap->owner = THIS_MODULE; adap->class = I2C_CLASS_DEPRECATED;
/* * Prepare controller for a transaction and call i2c_dw_xfer_msg */ int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) { struct dw_i2c_dev *dev = i2c_get_adapdata(adap); int ret; dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); mutex_lock(&dev->lock); pm_runtime_get_sync(dev->dev); INIT_COMPLETION(dev->cmd_complete); dev->msgs = msgs; dev->msgs_num = num; dev->cmd_err = 0; dev->msg_write_idx = 0; dev->msg_read_idx = 0; dev->msg_err = 0; dev->status = STATUS_IDLE; dev->abort_source = 0; ret = i2c_dw_wait_bus_not_busy(dev); if (ret < 0) goto done; /* start the transfers */ i2c_dw_xfer_init(dev); /* wait for tx to complete */ // ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ); ret = wait_for_completion_timeout(&dev->cmd_complete, HZ); if (ret == 0) { dev_err(dev->dev, "controller timed out\n"); i2c_dw_init(dev); ret = -ETIMEDOUT; goto done; } else if (ret < 0) goto done; if (dev->msg_err) { ret = dev->msg_err; goto done; } /* no error */ if (likely(!dev->cmd_err)) { /* Disable the adapter */ dw_writel(dev, 0, DW_IC_ENABLE); ret = num; goto done; } /* We have an error */ if (dev->cmd_err == DW_IC_ERR_TX_ABRT) { ret = i2c_dw_handle_tx_abort(dev); goto done; } ret = -EIO; done: pm_runtime_put(dev->dev); mutex_unlock(&dev->lock); return ret; }