mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-02 10:31:26 -04:00
Merge tag 'i2c-for-6.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c fixes from Wolfram Sang: - riic, imx-lpi2c: suspend/resume fixes - qcom-geni: DMA handling fix - iproc: correct DT binding description * tag 'i2c-for-6.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: imx-lpi2c: change to PIO mode in system-wide suspend/resume progress i2c: qcom-geni: make sure I2C hub controllers can't use SE DMA i2c: riic: Move suspend handling to NOIRQ phase dt-bindings: i2c: brcm,iproc-i2c: Allow 2 reg entries for brcm,iproc-nic-i2c
This commit is contained in:
@@ -16,7 +16,8 @@ properties:
|
||||
- brcm,iproc-nic-i2c
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
clock-frequency:
|
||||
enum: [ 100000, 400000 ]
|
||||
@@ -41,8 +42,15 @@ allOf:
|
||||
contains:
|
||||
const: brcm,iproc-nic-i2c
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
minItems: 2
|
||||
required:
|
||||
- brcm,ape-hsls-addr-mask
|
||||
else:
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
||||
@@ -592,6 +592,13 @@ static bool is_use_dma(struct lpi2c_imx_struct *lpi2c_imx, struct i2c_msg *msg)
|
||||
if (!lpi2c_imx->can_use_dma)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* A system-wide suspend or resume transition is in progress. LPI2C should use PIO to
|
||||
* transfer data to avoid issue caused by no ready DMA HW resource.
|
||||
*/
|
||||
if (pm_suspend_in_progress())
|
||||
return false;
|
||||
|
||||
/*
|
||||
* When the length of data is less than I2C_DMA_THRESHOLD,
|
||||
* cpu mode is used directly to avoid low performance.
|
||||
|
||||
@@ -116,6 +116,7 @@ struct geni_i2c_dev {
|
||||
dma_addr_t dma_addr;
|
||||
struct dma_chan *tx_c;
|
||||
struct dma_chan *rx_c;
|
||||
bool no_dma;
|
||||
bool gpi_mode;
|
||||
bool abort_done;
|
||||
bool is_tx_multi_desc_xfer;
|
||||
@@ -447,7 +448,7 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
|
||||
size_t len = msg->len;
|
||||
struct i2c_msg *cur;
|
||||
|
||||
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
|
||||
dma_buf = gi2c->no_dma ? NULL : i2c_get_dma_safe_msg_buf(msg, 32);
|
||||
if (dma_buf)
|
||||
geni_se_select_mode(se, GENI_SE_DMA);
|
||||
else
|
||||
@@ -486,7 +487,7 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
|
||||
size_t len = msg->len;
|
||||
struct i2c_msg *cur;
|
||||
|
||||
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
|
||||
dma_buf = gi2c->no_dma ? NULL : i2c_get_dma_safe_msg_buf(msg, 32);
|
||||
if (dma_buf)
|
||||
geni_se_select_mode(se, GENI_SE_DMA);
|
||||
else
|
||||
@@ -1080,10 +1081,12 @@ static int geni_i2c_probe(struct platform_device *pdev)
|
||||
goto err_resources;
|
||||
}
|
||||
|
||||
if (desc && desc->no_dma_support)
|
||||
if (desc && desc->no_dma_support) {
|
||||
fifo_disable = false;
|
||||
else
|
||||
gi2c->no_dma = true;
|
||||
} else {
|
||||
fifo_disable = readl_relaxed(gi2c->se.base + GENI_IF_DISABLE_RO) & FIFO_IF_DISABLE;
|
||||
}
|
||||
|
||||
if (fifo_disable) {
|
||||
/* FIFO is disabled, so we can only use GPI DMA */
|
||||
|
||||
@@ -670,12 +670,39 @@ static const struct riic_of_data riic_rz_t2h_info = {
|
||||
|
||||
static int riic_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct riic_dev *riic = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
/*
|
||||
* Some I2C devices may need the I2C controller to remain active
|
||||
* during resume_noirq() or suspend_noirq(). If the controller is
|
||||
* autosuspended, there is no way to wake it up once runtime PM is
|
||||
* disabled (in suspend_late()).
|
||||
*
|
||||
* During system resume, the I2C controller will be available only
|
||||
* after runtime PM is re-enabled (in resume_early()). However, this
|
||||
* may be too late for some devices.
|
||||
*
|
||||
* Wake up the controller in the suspend() callback while runtime PM
|
||||
* is still enabled. The I2C controller will remain available until
|
||||
* the suspend_noirq() callback (pm_runtime_force_suspend()) is
|
||||
* called. During resume, the I2C controller can be restored by the
|
||||
* resume_noirq() callback (pm_runtime_force_resume()).
|
||||
*
|
||||
* Finally, the resume() callback re-enables autosuspend, ensuring
|
||||
* the I2C controller remains available until the system enters
|
||||
* suspend_noirq() and from resume_noirq().
|
||||
*/
|
||||
return pm_runtime_resume_and_get(dev);
|
||||
}
|
||||
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
static int riic_i2c_resume(struct device *dev)
|
||||
{
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int riic_i2c_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct riic_dev *riic = dev_get_drvdata(dev);
|
||||
|
||||
i2c_mark_adapter_suspended(&riic->adapter);
|
||||
|
||||
@@ -683,12 +710,12 @@ static int riic_i2c_suspend(struct device *dev)
|
||||
riic_clear_set_bit(riic, ICCR1_ICE, 0, RIIC_ICCR1);
|
||||
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_sync(dev);
|
||||
pm_runtime_force_suspend(dev);
|
||||
|
||||
return reset_control_assert(riic->rstc);
|
||||
}
|
||||
|
||||
static int riic_i2c_resume(struct device *dev)
|
||||
static int riic_i2c_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct riic_dev *riic = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
@@ -697,6 +724,10 @@ static int riic_i2c_resume(struct device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = riic_init_hw(riic);
|
||||
if (ret) {
|
||||
/*
|
||||
@@ -714,6 +745,7 @@ static int riic_i2c_resume(struct device *dev)
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops riic_i2c_pm_ops = {
|
||||
NOIRQ_SYSTEM_SLEEP_PM_OPS(riic_i2c_suspend_noirq, riic_i2c_resume_noirq)
|
||||
SYSTEM_SLEEP_PM_OPS(riic_i2c_suspend, riic_i2c_resume)
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user