mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-04 04:02:26 +00:00
Merge branch 'i2c/i2c-host' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git
This commit is contained in:
commit
2f19d7a812
@ -621,7 +621,7 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
|
static int i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
|
||||||
unsigned int i2c_clk_rate)
|
unsigned int i2c_clk_rate)
|
||||||
{
|
{
|
||||||
struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
|
struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
|
||||||
@ -637,7 +637,11 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
|
|||||||
|
|
||||||
/* Divider value calculation */
|
/* Divider value calculation */
|
||||||
if (i2c_imx->cur_clk == i2c_clk_rate)
|
if (i2c_imx->cur_clk == i2c_clk_rate)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
|
/* Keep the denominator of the following program always NOT equal to 0. */
|
||||||
|
if (!(i2c_clk_rate / 2))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
i2c_imx->cur_clk = i2c_clk_rate;
|
i2c_imx->cur_clk = i2c_clk_rate;
|
||||||
|
|
||||||
@ -668,6 +672,8 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
|
|||||||
dev_dbg(&i2c_imx->adapter.dev, "IFDR[IC]=0x%x, REAL DIV=%d\n",
|
dev_dbg(&i2c_imx->adapter.dev, "IFDR[IC]=0x%x, REAL DIV=%d\n",
|
||||||
i2c_clk_div[i].val, i2c_clk_div[i].div);
|
i2c_clk_div[i].val, i2c_clk_div[i].div);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i2c_imx_clk_notifier_call(struct notifier_block *nb,
|
static int i2c_imx_clk_notifier_call(struct notifier_block *nb,
|
||||||
@ -677,11 +683,12 @@ static int i2c_imx_clk_notifier_call(struct notifier_block *nb,
|
|||||||
struct imx_i2c_struct *i2c_imx = container_of(nb,
|
struct imx_i2c_struct *i2c_imx = container_of(nb,
|
||||||
struct imx_i2c_struct,
|
struct imx_i2c_struct,
|
||||||
clk_change_nb);
|
clk_change_nb);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (action & POST_RATE_CHANGE)
|
if (action & POST_RATE_CHANGE)
|
||||||
i2c_imx_set_clk(i2c_imx, ndata->new_rate);
|
ret = i2c_imx_set_clk(i2c_imx, ndata->new_rate);
|
||||||
|
|
||||||
return NOTIFY_OK;
|
return notifier_from_errno(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i2c_imx_start(struct imx_i2c_struct *i2c_imx, bool atomic)
|
static int i2c_imx_start(struct imx_i2c_struct *i2c_imx, bool atomic)
|
||||||
@ -1760,7 +1767,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
|
|||||||
goto rpm_disable;
|
goto rpm_disable;
|
||||||
|
|
||||||
/* Request IRQ */
|
/* Request IRQ */
|
||||||
ret = request_irq(irq, i2c_imx_isr, IRQF_SHARED, pdev->name, i2c_imx);
|
ret = request_irq(irq, i2c_imx_isr, IRQF_SHARED | IRQF_NO_SUSPEND,
|
||||||
|
pdev->name, i2c_imx);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "can't claim irq %d\n", irq);
|
dev_err(&pdev->dev, "can't claim irq %d\n", irq);
|
||||||
goto rpm_disable;
|
goto rpm_disable;
|
||||||
@ -1780,7 +1788,11 @@ static int i2c_imx_probe(struct platform_device *pdev)
|
|||||||
i2c_imx->bitrate = pdata->bitrate;
|
i2c_imx->bitrate = pdata->bitrate;
|
||||||
i2c_imx->clk_change_nb.notifier_call = i2c_imx_clk_notifier_call;
|
i2c_imx->clk_change_nb.notifier_call = i2c_imx_clk_notifier_call;
|
||||||
clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb);
|
clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb);
|
||||||
i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk));
|
ret = i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk));
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "can't get I2C clock\n");
|
||||||
|
goto clk_notifier_unregister;
|
||||||
|
}
|
||||||
|
|
||||||
i2c_imx_reset_regs(i2c_imx);
|
i2c_imx_reset_regs(i2c_imx);
|
||||||
|
|
||||||
@ -1874,7 +1886,43 @@ static int i2c_imx_runtime_resume(struct device *dev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int i2c_imx_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int i2c_imx_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
pm_runtime_mark_last_busy(dev);
|
||||||
|
pm_runtime_put_autosuspend(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct dev_pm_ops i2c_imx_pm_ops = {
|
static const struct dev_pm_ops i2c_imx_pm_ops = {
|
||||||
|
NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||||
|
pm_runtime_force_resume)
|
||||||
|
SYSTEM_SLEEP_PM_OPS(i2c_imx_suspend, i2c_imx_resume)
|
||||||
RUNTIME_PM_OPS(i2c_imx_runtime_suspend, i2c_imx_runtime_resume, NULL)
|
RUNTIME_PM_OPS(i2c_imx_runtime_suspend, i2c_imx_runtime_resume, NULL)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -464,12 +464,8 @@ static void ki2c_unregister_devices(struct ki2c *ki2c)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ki2c->client_size; i++) {
|
for (i = 0; i < ki2c->client_size; i++)
|
||||||
struct i2c_client *client = ki2c->client[i];
|
i2c_unregister_device(ki2c->client[i]);
|
||||||
|
|
||||||
if (client)
|
|
||||||
i2c_unregister_device(client);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ki2c_register_devices(struct ki2c *ki2c)
|
static int ki2c_register_devices(struct ki2c *ki2c)
|
||||||
|
Loading…
Reference in New Issue
Block a user