i2c: designware: Detect the FIFO size in the common code
The problem with detecting the FIFO depth in the platform driver is that in order to implement this we have to access the controller IC_COMP_PARAM_1 register. Currently it's done before the i2c_dw_set_reg_access() method execution, which is errors prone since the method determines the registers endianness and access mode and we can't use dw_readl/dw_writel accessors before this information is retrieved. We also can't move the i2c_dw_set_reg_access() function invocation to after the master/slave probe functions call (when endianness and access mode are determined), since the FIFO depth information is used by them for initializations. So in order to fix the problem we have no choice but to move the FIFO size detection methods to the common code and call it at the probe stage. Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru> Signed-off-by: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
This commit is contained in:
parent
1413ef638a
commit
1f1a714658
|
@ -344,6 +344,28 @@ int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
void i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
|
||||
{
|
||||
u32 param, tx_fifo_depth, rx_fifo_depth;
|
||||
|
||||
/*
|
||||
* Try to detect the FIFO depth if not set by interface driver,
|
||||
* the depth could be from 2 to 256 from HW spec.
|
||||
*/
|
||||
param = dw_readl(dev, DW_IC_COMP_PARAM_1);
|
||||
tx_fifo_depth = ((param >> 16) & 0xff) + 1;
|
||||
rx_fifo_depth = ((param >> 8) & 0xff) + 1;
|
||||
if (!dev->tx_fifo_depth) {
|
||||
dev->tx_fifo_depth = tx_fifo_depth;
|
||||
dev->rx_fifo_depth = rx_fifo_depth;
|
||||
} else if (tx_fifo_depth >= 2) {
|
||||
dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth,
|
||||
tx_fifo_depth);
|
||||
dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth,
|
||||
rx_fifo_depth);
|
||||
}
|
||||
}
|
||||
|
||||
u32 i2c_dw_func(struct i2c_adapter *adap)
|
||||
{
|
||||
struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
|
||||
|
|
|
@ -297,6 +297,7 @@ int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
|
|||
void i2c_dw_release_lock(struct dw_i2c_dev *dev);
|
||||
int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev);
|
||||
int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev);
|
||||
void i2c_dw_set_fifo_size(struct dw_i2c_dev *dev);
|
||||
u32 i2c_dw_func(struct i2c_adapter *adap);
|
||||
void i2c_dw_disable(struct dw_i2c_dev *dev);
|
||||
void i2c_dw_disable_int(struct dw_i2c_dev *dev);
|
||||
|
|
|
@ -698,6 +698,8 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
i2c_dw_set_fifo_size(dev);
|
||||
|
||||
ret = dev->init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -219,28 +219,6 @@ static void i2c_dw_configure_slave(struct dw_i2c_dev *dev)
|
|||
dev->mode = DW_IC_SLAVE;
|
||||
}
|
||||
|
||||
static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev)
|
||||
{
|
||||
u32 param, tx_fifo_depth, rx_fifo_depth;
|
||||
|
||||
/*
|
||||
* Try to detect the FIFO depth if not set by interface driver,
|
||||
* the depth could be from 2 to 256 from HW spec.
|
||||
*/
|
||||
param = i2c_dw_read_comp_param(dev);
|
||||
tx_fifo_depth = ((param >> 16) & 0xff) + 1;
|
||||
rx_fifo_depth = ((param >> 8) & 0xff) + 1;
|
||||
if (!dev->tx_fifo_depth) {
|
||||
dev->tx_fifo_depth = tx_fifo_depth;
|
||||
dev->rx_fifo_depth = rx_fifo_depth;
|
||||
} else if (tx_fifo_depth >= 2) {
|
||||
dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth,
|
||||
tx_fifo_depth);
|
||||
dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth,
|
||||
rx_fifo_depth);
|
||||
}
|
||||
}
|
||||
|
||||
static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev *dev)
|
||||
{
|
||||
pm_runtime_disable(dev->dev);
|
||||
|
@ -362,8 +340,6 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
|
|||
div_u64(clk_khz * t->sda_hold_ns + 500000, 1000000);
|
||||
}
|
||||
|
||||
dw_i2c_set_fifo_size(dev);
|
||||
|
||||
adap = &dev->adapter;
|
||||
adap->owner = THIS_MODULE;
|
||||
adap->class = I2C_CLASS_DEPRECATED;
|
||||
|
|
|
@ -260,6 +260,8 @@ int i2c_dw_probe_slave(struct dw_i2c_dev *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
i2c_dw_set_fifo_size(dev);
|
||||
|
||||
ret = dev->init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
Loading…
Reference in New Issue