Merge branch 'i2c-embedded/for-next' of git://git.pengutronix.de/git/wsa/linux
Pull i2c-embedded changes from Wolfram Sang: - CBUS driver (an I2C variant) - continued rework of the omap driver - s3c2410 gets lots of fixes and gains pinctrl support - at91 gains DMA support - the GPIO muxer gains devicetree probing - typical fixes and additions all over * 'i2c-embedded/for-next' of git://git.pengutronix.de/git/wsa/linux: (45 commits) i2c: omap: Remove the OMAP_I2C_FLAG_RESET_REGS_POSTIDLE flag i2c: at91: add dma support i2c: at91: change struct members indentation i2c: at91: fix compilation warning i2c: mxs: Do not disable the I2C SMBus quick mode i2c: mxs: Handle i2c DMA failure properly i2c: s3c2410: Remove recently introduced performance overheads i2c: ocores: Move grlib set/get functions into #ifdef CONFIG_OF block i2c: s3c2410: Add fix for i2c suspend/resume i2c: s3c2410: Fix code to free gpios i2c: i2c-cbus-gpio: introduce driver i2c: ocores: Add support for the GRLIB port of the controller and use function pointers for getreg and setreg functions i2c: ocores: Add irq support for sparc i2c: omap: Move the remove constraint ARM: dts: cfa10049: Add the i2c muxer buses to the CFA-10049 i2c: s3c2410: do not special case HDMIPHY stuck bus detection i2c: s3c2410: use exponential back off while polling for bus idle i2c: s3c2410: do not generate STOP for QUIRK_HDMIPHY i2c: s3c2410: grab adapter lock while changing i2c clock i2c: s3c2410: Add support for pinctrl ...
Este commit está contenido en:
@@ -38,6 +38,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
|
||||
@@ -49,6 +50,9 @@
|
||||
#define QUIRK_HDMIPHY (1 << 1)
|
||||
#define QUIRK_NO_GPIO (1 << 2)
|
||||
|
||||
/* Max time to wait for bus to become idle after a xfer (in us) */
|
||||
#define S3C2410_IDLE_TIMEOUT 5000
|
||||
|
||||
/* i2c controller state */
|
||||
enum s3c24xx_i2c_state {
|
||||
STATE_IDLE,
|
||||
@@ -59,7 +63,6 @@ enum s3c24xx_i2c_state {
|
||||
};
|
||||
|
||||
struct s3c24xx_i2c {
|
||||
spinlock_t lock;
|
||||
wait_queue_head_t wait;
|
||||
unsigned int quirks;
|
||||
unsigned int suspended:1;
|
||||
@@ -78,11 +81,11 @@ struct s3c24xx_i2c {
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
struct device *dev;
|
||||
struct resource *ioarea;
|
||||
struct i2c_adapter adap;
|
||||
|
||||
struct s3c2410_platform_i2c *pdata;
|
||||
int gpios[2];
|
||||
struct pinctrl *pctrl;
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
struct notifier_block freq_transition;
|
||||
#endif
|
||||
@@ -235,8 +238,47 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
|
||||
|
||||
dev_dbg(i2c->dev, "STOP\n");
|
||||
|
||||
/* stop the transfer */
|
||||
iicstat &= ~S3C2410_IICSTAT_START;
|
||||
/*
|
||||
* The datasheet says that the STOP sequence should be:
|
||||
* 1) I2CSTAT.5 = 0 - Clear BUSY (or 'generate STOP')
|
||||
* 2) I2CCON.4 = 0 - Clear IRQPEND
|
||||
* 3) Wait until the stop condition takes effect.
|
||||
* 4*) I2CSTAT.4 = 0 - Clear TXRXEN
|
||||
*
|
||||
* Where, step "4*" is only for buses with the "HDMIPHY" quirk.
|
||||
*
|
||||
* However, after much experimentation, it appears that:
|
||||
* a) normal buses automatically clear BUSY and transition from
|
||||
* Master->Slave when they complete generating a STOP condition.
|
||||
* Therefore, step (3) can be done in doxfer() by polling I2CCON.4
|
||||
* after starting the STOP generation here.
|
||||
* b) HDMIPHY bus does neither, so there is no way to do step 3.
|
||||
* There is no indication when this bus has finished generating
|
||||
* STOP.
|
||||
*
|
||||
* In fact, we have found that as soon as the IRQPEND bit is cleared in
|
||||
* step 2, the HDMIPHY bus generates the STOP condition, and then
|
||||
* immediately starts transferring another data byte, even though the
|
||||
* bus is supposedly stopped. This is presumably because the bus is
|
||||
* still in "Master" mode, and its BUSY bit is still set.
|
||||
*
|
||||
* To avoid these extra post-STOP transactions on HDMI phy devices, we
|
||||
* just disable Serial Output on the bus (I2CSTAT.4 = 0) directly,
|
||||
* instead of first generating a proper STOP condition. This should
|
||||
* float SDA & SCK terminating the transfer. Subsequent transfers
|
||||
* start with a proper START condition, and proceed normally.
|
||||
*
|
||||
* The HDMIPHY bus is an internal bus that always has exactly two
|
||||
* devices, the host as Master and the HDMIPHY device as the slave.
|
||||
* Skipping the STOP condition has been tested on this bus and works.
|
||||
*/
|
||||
if (i2c->quirks & QUIRK_HDMIPHY) {
|
||||
/* Stop driving the I2C pins */
|
||||
iicstat &= ~S3C2410_IICSTAT_TXRXEN;
|
||||
} else {
|
||||
/* stop the transfer */
|
||||
iicstat &= ~S3C2410_IICSTAT_START;
|
||||
}
|
||||
writel(iicstat, i2c->regs + S3C2410_IICSTAT);
|
||||
|
||||
i2c->state = STATE_STOP;
|
||||
@@ -490,13 +532,6 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
|
||||
unsigned long iicstat;
|
||||
int timeout = 400;
|
||||
|
||||
/* the timeout for HDMIPHY is reduced to 10 ms because
|
||||
* the hangup is expected to happen, so waiting 400 ms
|
||||
* causes only unnecessary system hangup
|
||||
*/
|
||||
if (i2c->quirks & QUIRK_HDMIPHY)
|
||||
timeout = 10;
|
||||
|
||||
while (timeout-- > 0) {
|
||||
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
|
||||
|
||||
@@ -506,16 +541,61 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
/* hang-up of bus dedicated for HDMIPHY occurred, resetting */
|
||||
if (i2c->quirks & QUIRK_HDMIPHY) {
|
||||
writel(0, i2c->regs + S3C2410_IICCON);
|
||||
writel(0, i2c->regs + S3C2410_IICSTAT);
|
||||
writel(0, i2c->regs + S3C2410_IICDS);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* s3c24xx_i2c_wait_idle
|
||||
*
|
||||
* wait for the i2c bus to become idle.
|
||||
*/
|
||||
|
||||
static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c)
|
||||
{
|
||||
unsigned long iicstat;
|
||||
ktime_t start, now;
|
||||
unsigned long delay;
|
||||
int spins;
|
||||
|
||||
/* ensure the stop has been through the bus */
|
||||
|
||||
dev_dbg(i2c->dev, "waiting for bus idle\n");
|
||||
|
||||
start = now = ktime_get();
|
||||
|
||||
/*
|
||||
* Most of the time, the bus is already idle within a few usec of the
|
||||
* end of a transaction. However, really slow i2c devices can stretch
|
||||
* the clock, delaying STOP generation.
|
||||
*
|
||||
* On slower SoCs this typically happens within a very small number of
|
||||
* instructions so busy wait briefly to avoid scheduling overhead.
|
||||
*/
|
||||
spins = 3;
|
||||
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
|
||||
while ((iicstat & S3C2410_IICSTAT_START) && --spins) {
|
||||
cpu_relax();
|
||||
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
/*
|
||||
* If we do get an appreciable delay as a compromise between idle
|
||||
* detection latency for the normal, fast case, and system load in the
|
||||
* slow device case, use an exponential back off in the polling loop,
|
||||
* up to 1/10th of the total timeout, then continue to poll at a
|
||||
* constant rate up to the timeout.
|
||||
*/
|
||||
delay = 1;
|
||||
while ((iicstat & S3C2410_IICSTAT_START) &&
|
||||
ktime_us_delta(now, start) < S3C2410_IDLE_TIMEOUT) {
|
||||
usleep_range(delay, 2 * delay);
|
||||
if (delay < S3C2410_IDLE_TIMEOUT / 10)
|
||||
delay <<= 1;
|
||||
now = ktime_get();
|
||||
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
|
||||
}
|
||||
|
||||
if (iicstat & S3C2410_IICSTAT_START)
|
||||
dev_warn(i2c->dev, "timeout waiting for bus idle\n");
|
||||
}
|
||||
|
||||
/* s3c24xx_i2c_doxfer
|
||||
@@ -526,8 +606,7 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
|
||||
static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
unsigned long iicstat, timeout;
|
||||
int spins = 20;
|
||||
unsigned long timeout;
|
||||
int ret;
|
||||
|
||||
if (i2c->suspended)
|
||||
@@ -540,8 +619,6 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irq(&i2c->lock);
|
||||
|
||||
i2c->msg = msgs;
|
||||
i2c->msg_num = num;
|
||||
i2c->msg_ptr = 0;
|
||||
@@ -550,7 +627,6 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
|
||||
|
||||
s3c24xx_i2c_enable_irq(i2c);
|
||||
s3c24xx_i2c_message_start(i2c, msgs);
|
||||
spin_unlock_irq(&i2c->lock);
|
||||
|
||||
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
|
||||
|
||||
@@ -564,24 +640,11 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
|
||||
else if (ret != num)
|
||||
dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
|
||||
|
||||
/* ensure the stop has been through the bus */
|
||||
/* For QUIRK_HDMIPHY, bus is already disabled */
|
||||
if (i2c->quirks & QUIRK_HDMIPHY)
|
||||
goto out;
|
||||
|
||||
dev_dbg(i2c->dev, "waiting for bus idle\n");
|
||||
|
||||
/* first, try busy waiting briefly */
|
||||
do {
|
||||
cpu_relax();
|
||||
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
|
||||
} while ((iicstat & S3C2410_IICSTAT_START) && --spins);
|
||||
|
||||
/* if that timed out sleep */
|
||||
if (!spins) {
|
||||
msleep(1);
|
||||
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
|
||||
}
|
||||
|
||||
if (iicstat & S3C2410_IICSTAT_START)
|
||||
dev_warn(i2c->dev, "timeout waiting for bus idle\n");
|
||||
s3c24xx_i2c_wait_idle(i2c);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
@@ -740,7 +803,6 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
|
||||
unsigned long val, void *data)
|
||||
{
|
||||
struct s3c24xx_i2c *i2c = freq_to_i2c(nb);
|
||||
unsigned long flags;
|
||||
unsigned int got;
|
||||
int delta_f;
|
||||
int ret;
|
||||
@@ -754,9 +816,9 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
|
||||
|
||||
if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) ||
|
||||
(val == CPUFREQ_PRECHANGE && delta_f > 0)) {
|
||||
spin_lock_irqsave(&i2c->lock, flags);
|
||||
i2c_lock_adapter(&i2c->adap);
|
||||
ret = s3c24xx_i2c_clockrate(i2c, &got);
|
||||
spin_unlock_irqrestore(&i2c->lock, flags);
|
||||
i2c_unlock_adapter(&i2c->adap);
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(i2c->dev, "cannot find frequency\n");
|
||||
@@ -858,14 +920,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
|
||||
|
||||
pdata = i2c->pdata;
|
||||
|
||||
/* inititalise the gpio */
|
||||
|
||||
if (pdata->cfg_gpio)
|
||||
pdata->cfg_gpio(to_platform_device(i2c->dev));
|
||||
else
|
||||
if (s3c24xx_i2c_parse_dt_gpio(i2c))
|
||||
return -EINVAL;
|
||||
|
||||
/* write slave address */
|
||||
|
||||
writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD);
|
||||
@@ -963,7 +1017,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
i2c->tx_setup = 50;
|
||||
|
||||
spin_lock_init(&i2c->lock);
|
||||
init_waitqueue_head(&i2c->wait);
|
||||
|
||||
/* find the clock and enable it */
|
||||
@@ -989,36 +1042,38 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
i2c->ioarea = request_mem_region(res->start, resource_size(res),
|
||||
pdev->name);
|
||||
|
||||
if (i2c->ioarea == NULL) {
|
||||
dev_err(&pdev->dev, "cannot request IO\n");
|
||||
ret = -ENXIO;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
i2c->regs = ioremap(res->start, resource_size(res));
|
||||
i2c->regs = devm_request_and_ioremap(&pdev->dev, res);
|
||||
|
||||
if (i2c->regs == NULL) {
|
||||
dev_err(&pdev->dev, "cannot map IO\n");
|
||||
ret = -ENXIO;
|
||||
goto err_ioarea;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
|
||||
i2c->regs, i2c->ioarea, res);
|
||||
dev_dbg(&pdev->dev, "registers %p (%p)\n",
|
||||
i2c->regs, res);
|
||||
|
||||
/* setup info block for the i2c core */
|
||||
|
||||
i2c->adap.algo_data = i2c;
|
||||
i2c->adap.dev.parent = &pdev->dev;
|
||||
|
||||
i2c->pctrl = devm_pinctrl_get_select_default(i2c->dev);
|
||||
|
||||
/* inititalise the i2c gpio lines */
|
||||
|
||||
if (i2c->pdata->cfg_gpio) {
|
||||
i2c->pdata->cfg_gpio(to_platform_device(i2c->dev));
|
||||
} else if (IS_ERR(i2c->pctrl) && s3c24xx_i2c_parse_dt_gpio(i2c)) {
|
||||
ret = -EINVAL;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
/* initialise the i2c controller */
|
||||
|
||||
ret = s3c24xx_i2c_init(i2c);
|
||||
if (ret != 0)
|
||||
goto err_iomap;
|
||||
goto err_clk;
|
||||
|
||||
/* find the IRQ for this unit (note, this relies on the init call to
|
||||
* ensure no current IRQs pending
|
||||
@@ -1027,7 +1082,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
i2c->irq = ret = platform_get_irq(pdev, 0);
|
||||
if (ret <= 0) {
|
||||
dev_err(&pdev->dev, "cannot find IRQ\n");
|
||||
goto err_iomap;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
ret = request_irq(i2c->irq, s3c24xx_i2c_irq, 0,
|
||||
@@ -1035,7 +1090,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
|
||||
goto err_iomap;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
ret = s3c24xx_i2c_register_cpufreq(i2c);
|
||||
@@ -1075,13 +1130,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
err_irq:
|
||||
free_irq(i2c->irq, i2c);
|
||||
|
||||
err_iomap:
|
||||
iounmap(i2c->regs);
|
||||
|
||||
err_ioarea:
|
||||
release_resource(i2c->ioarea);
|
||||
kfree(i2c->ioarea);
|
||||
|
||||
err_clk:
|
||||
clk_disable_unprepare(i2c->clk);
|
||||
clk_put(i2c->clk);
|
||||
@@ -1110,16 +1158,13 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
|
||||
clk_disable_unprepare(i2c->clk);
|
||||
clk_put(i2c->clk);
|
||||
|
||||
iounmap(i2c->regs);
|
||||
|
||||
release_resource(i2c->ioarea);
|
||||
s3c24xx_i2c_dt_gpio_free(i2c);
|
||||
kfree(i2c->ioarea);
|
||||
if (pdev->dev.of_node && IS_ERR(i2c->pctrl))
|
||||
s3c24xx_i2c_dt_gpio_free(i2c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int s3c24xx_i2c_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
@@ -1142,10 +1187,14 @@ static int s3c24xx_i2c_resume(struct device *dev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.suspend_noirq = s3c24xx_i2c_suspend_noirq,
|
||||
.resume = s3c24xx_i2c_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define S3C24XX_DEV_PM_OPS (&s3c24xx_i2c_dev_pm_ops)
|
||||
|
Referencia en una nueva incidencia
Block a user