Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c fixes from Wolfram Sang: "Some driver bugfixes and an old API removal now that all users are gone" * 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: tegra: Synchronize DMA before termination i2c: tegra: Better handle case where CPU0 is busy for a long time i2c: remove i2c_new_probed_device API i2c: altera: use proper variable to hold errno i2c: designware: platdrv: Remove DPM_FLAG_SMART_SUSPEND flag on BYT and CHT
This commit is contained in:
commit
b484f3c3c6
|
@ -384,7 +384,6 @@ static int altr_i2c_probe(struct platform_device *pdev)
|
||||||
struct altr_i2c_dev *idev = NULL;
|
struct altr_i2c_dev *idev = NULL;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
int irq, ret;
|
int irq, ret;
|
||||||
u32 val;
|
|
||||||
|
|
||||||
idev = devm_kzalloc(&pdev->dev, sizeof(*idev), GFP_KERNEL);
|
idev = devm_kzalloc(&pdev->dev, sizeof(*idev), GFP_KERNEL);
|
||||||
if (!idev)
|
if (!idev)
|
||||||
|
@ -411,17 +410,17 @@ static int altr_i2c_probe(struct platform_device *pdev)
|
||||||
init_completion(&idev->msg_complete);
|
init_completion(&idev->msg_complete);
|
||||||
spin_lock_init(&idev->lock);
|
spin_lock_init(&idev->lock);
|
||||||
|
|
||||||
val = device_property_read_u32(idev->dev, "fifo-size",
|
ret = device_property_read_u32(idev->dev, "fifo-size",
|
||||||
&idev->fifo_size);
|
&idev->fifo_size);
|
||||||
if (val) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "FIFO size set to default of %d\n",
|
dev_err(&pdev->dev, "FIFO size set to default of %d\n",
|
||||||
ALTR_I2C_DFLT_FIFO_SZ);
|
ALTR_I2C_DFLT_FIFO_SZ);
|
||||||
idev->fifo_size = ALTR_I2C_DFLT_FIFO_SZ;
|
idev->fifo_size = ALTR_I2C_DFLT_FIFO_SZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
val = device_property_read_u32(idev->dev, "clock-frequency",
|
ret = device_property_read_u32(idev->dev, "clock-frequency",
|
||||||
&idev->bus_clk_rate);
|
&idev->bus_clk_rate);
|
||||||
if (val) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "Default to 100kHz\n");
|
dev_err(&pdev->dev, "Default to 100kHz\n");
|
||||||
idev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ; /* default clock rate */
|
idev->bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ; /* default clock rate */
|
||||||
}
|
}
|
||||||
|
|
|
@ -354,10 +354,16 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
|
||||||
adap->dev.of_node = pdev->dev.of_node;
|
adap->dev.of_node = pdev->dev.of_node;
|
||||||
adap->nr = -1;
|
adap->nr = -1;
|
||||||
|
|
||||||
|
if (dev->flags & ACCESS_NO_IRQ_SUSPEND) {
|
||||||
|
dev_pm_set_driver_flags(&pdev->dev,
|
||||||
|
DPM_FLAG_SMART_PREPARE |
|
||||||
|
DPM_FLAG_LEAVE_SUSPENDED);
|
||||||
|
} else {
|
||||||
dev_pm_set_driver_flags(&pdev->dev,
|
dev_pm_set_driver_flags(&pdev->dev,
|
||||||
DPM_FLAG_SMART_PREPARE |
|
DPM_FLAG_SMART_PREPARE |
|
||||||
DPM_FLAG_SMART_SUSPEND |
|
DPM_FLAG_SMART_SUSPEND |
|
||||||
DPM_FLAG_LEAVE_SUSPENDED);
|
DPM_FLAG_LEAVE_SUSPENDED);
|
||||||
|
}
|
||||||
|
|
||||||
/* The code below assumes runtime PM to be disabled. */
|
/* The code below assumes runtime PM to be disabled. */
|
||||||
WARN_ON(pm_runtime_enabled(&pdev->dev));
|
WARN_ON(pm_runtime_enabled(&pdev->dev));
|
||||||
|
|
|
@ -996,7 +996,7 @@ tegra_i2c_poll_completion_timeout(struct tegra_i2c_dev *i2c_dev,
|
||||||
do {
|
do {
|
||||||
u32 status = i2c_readl(i2c_dev, I2C_INT_STATUS);
|
u32 status = i2c_readl(i2c_dev, I2C_INT_STATUS);
|
||||||
|
|
||||||
if (status) {
|
if (status)
|
||||||
tegra_i2c_isr(i2c_dev->irq, i2c_dev);
|
tegra_i2c_isr(i2c_dev->irq, i2c_dev);
|
||||||
|
|
||||||
if (completion_done(complete)) {
|
if (completion_done(complete)) {
|
||||||
|
@ -1004,7 +1004,6 @@ tegra_i2c_poll_completion_timeout(struct tegra_i2c_dev *i2c_dev,
|
||||||
|
|
||||||
return msecs_to_jiffies(delta) ?: 1;
|
return msecs_to_jiffies(delta) ?: 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ktime = ktime_get();
|
ktime = ktime_get();
|
||||||
|
|
||||||
|
@ -1030,14 +1029,18 @@ tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev,
|
||||||
disable_irq(i2c_dev->irq);
|
disable_irq(i2c_dev->irq);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There is a chance that completion may happen after IRQ
|
* Under some rare circumstances (like running KASAN +
|
||||||
* synchronization, which is done by disable_irq().
|
* NFS root) CPU, which handles interrupt, may stuck in
|
||||||
|
* uninterruptible state for a significant time. In this
|
||||||
|
* case we will get timeout if I2C transfer is running on
|
||||||
|
* a sibling CPU, despite of IRQ being raised.
|
||||||
|
*
|
||||||
|
* In order to handle this rare condition, the IRQ status
|
||||||
|
* needs to be checked after timeout.
|
||||||
*/
|
*/
|
||||||
if (ret == 0 && completion_done(complete)) {
|
if (ret == 0)
|
||||||
dev_warn(i2c_dev->dev,
|
ret = tegra_i2c_poll_completion_timeout(i2c_dev,
|
||||||
"completion done after timeout\n");
|
complete, 0);
|
||||||
ret = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1216,6 +1219,15 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
|
||||||
time_left = tegra_i2c_wait_completion_timeout(
|
time_left = tegra_i2c_wait_completion_timeout(
|
||||||
i2c_dev, &i2c_dev->dma_complete, xfer_time);
|
i2c_dev, &i2c_dev->dma_complete, xfer_time);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Synchronize DMA first, since dmaengine_terminate_sync()
|
||||||
|
* performs synchronization after the transfer's termination
|
||||||
|
* and we want to get a completion if transfer succeeded.
|
||||||
|
*/
|
||||||
|
dmaengine_synchronize(i2c_dev->msg_read ?
|
||||||
|
i2c_dev->rx_dma_chan :
|
||||||
|
i2c_dev->tx_dma_chan);
|
||||||
|
|
||||||
dmaengine_terminate_sync(i2c_dev->msg_read ?
|
dmaengine_terminate_sync(i2c_dev->msg_read ?
|
||||||
i2c_dev->rx_dma_chan :
|
i2c_dev->rx_dma_chan :
|
||||||
i2c_dev->tx_dma_chan);
|
i2c_dev->tx_dma_chan);
|
||||||
|
|
|
@ -2273,19 +2273,6 @@ i2c_new_scanned_device(struct i2c_adapter *adap,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(i2c_new_scanned_device);
|
EXPORT_SYMBOL_GPL(i2c_new_scanned_device);
|
||||||
|
|
||||||
struct i2c_client *
|
|
||||||
i2c_new_probed_device(struct i2c_adapter *adap,
|
|
||||||
struct i2c_board_info *info,
|
|
||||||
unsigned short const *addr_list,
|
|
||||||
int (*probe)(struct i2c_adapter *adap, unsigned short addr))
|
|
||||||
{
|
|
||||||
struct i2c_client *client;
|
|
||||||
|
|
||||||
client = i2c_new_scanned_device(adap, info, addr_list, probe);
|
|
||||||
return IS_ERR(client) ? NULL : client;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(i2c_new_probed_device);
|
|
||||||
|
|
||||||
struct i2c_adapter *i2c_get_adapter(int nr)
|
struct i2c_adapter *i2c_get_adapter(int nr)
|
||||||
{
|
{
|
||||||
struct i2c_adapter *adapter;
|
struct i2c_adapter *adapter;
|
||||||
|
|
|
@ -461,12 +461,6 @@ i2c_new_scanned_device(struct i2c_adapter *adap,
|
||||||
unsigned short const *addr_list,
|
unsigned short const *addr_list,
|
||||||
int (*probe)(struct i2c_adapter *adap, unsigned short addr));
|
int (*probe)(struct i2c_adapter *adap, unsigned short addr));
|
||||||
|
|
||||||
struct i2c_client *
|
|
||||||
i2c_new_probed_device(struct i2c_adapter *adap,
|
|
||||||
struct i2c_board_info *info,
|
|
||||||
unsigned short const *addr_list,
|
|
||||||
int (*probe)(struct i2c_adapter *adap, unsigned short addr));
|
|
||||||
|
|
||||||
/* Common custom probe functions */
|
/* Common custom probe functions */
|
||||||
int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr);
|
int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue