Skip to content

Commit

Permalink
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/wsa/linux

Pull i2c fixes from Wolfram Sang:
 "This is probably not the kind of pull request you want to see that
  late in the cycle.  Yet, the ACPI refactorization was problematic
  again and caused another two issues which need fixing.  My holidays
  with limited internet (plus travelling) and the developer's illness
  didn't help either :(

  The details:

   - ACPI code was refactored out into a seperate file and as a
     side-effect, the i2c-core module got renamed.  Jean Delvare
     rightfully complained about the rename being problematic for
     distributions.  So, Mika and I thought the least problematic way to
     deal with it is to move all the code back into the main i2c core
     source file.  This is mainly a huge code move with some #ifdeffery
     applied.  No functional code changes.  Our personal tests and the
     testbots did not find problems.  (I was thinking about reverting,
     too, yet that would also have ~800 lines changed)

   - The new ACPI code also had a NULL pointer exception, thanks to
     Peter for finding and fixing it.

   - Mikko fixed a locking problem by decoupling clock_prepare and
     clock_enable.

   - Addy learnt that the datasheet was wrong and reimplemented the
     frequency setup according to the new algorithm.

  - Fan fixed an off-by-one error when copying data

  - Janusz fixed a copy'n'paste bug which gave a wrong error message

  - Sergei made sure that "don't touch" bits are not accessed"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: acpi: Fix NULL Pointer dereference
  i2c: move acpi code back into the core
  i2c: rk3x: fix divisor calculation for SCL frequency
  i2c: mxs: fix error message in pio transfer
  i2c: ismt: use correct length when copy buffer
  i2c: rcar: fix RCAR_IRQ_ACK_{RECV|SEND}
  i2c: tegra: Move clk_prepare/clk_set_rate to probe
  • Loading branch information
torvalds committed Sep 25, 2014
2 parents d671e42 + 0aef44e commit 12df9f3
Show file tree
Hide file tree
Showing 10 changed files with 420 additions and 408 deletions.
1 change: 0 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -4476,7 +4476,6 @@ M: Mika Westerberg <[email protected]>
L: [email protected]
L: [email protected]
S: Maintained
F: drivers/i2c/i2c-acpi.c

I2C-TAOS-EVM DRIVER
M: Jean Delvare <[email protected]>
Expand Down
5 changes: 1 addition & 4 deletions drivers/i2c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@
# Makefile for the i2c core.
#

i2ccore-y := i2c-core.o
i2ccore-$(CONFIG_ACPI) += i2c-acpi.o

obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
obj-$(CONFIG_I2C) += i2ccore.o
obj-$(CONFIG_I2C) += i2c-core.o
obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-$(CONFIG_I2C_MUX) += i2c-mux.o
Expand Down
4 changes: 2 additions & 2 deletions drivers/i2c/busses/i2c-ismt.c
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
desc->wr_len_cmd = dma_size;
desc->control |= ISMT_DESC_BLK;
priv->dma_buffer[0] = command;
memcpy(&priv->dma_buffer[1], &data->block[1], dma_size);
memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1);
} else {
/* Block Read */
dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: READ\n");
Expand Down Expand Up @@ -525,7 +525,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
desc->wr_len_cmd = dma_size;
desc->control |= ISMT_DESC_I2C;
priv->dma_buffer[0] = command;
memcpy(&priv->dma_buffer[1], &data->block[1], dma_size);
memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1);
} else {
/* i2c Block Read */
dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: READ\n");
Expand Down
2 changes: 1 addition & 1 deletion drivers/i2c/busses/i2c-mxs.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
ret = mxs_i2c_pio_wait_xfer_end(i2c);
if (ret) {
dev_err(i2c->dev,
"PIO: Failed to send SELECT command!\n");
"PIO: Failed to send READ command!\n");
goto cleanup;
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/i2c/busses/i2c-rcar.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@
#define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR)
#define RCAR_IRQ_STOP (MST)

#define RCAR_IRQ_ACK_SEND (~(MAT | MDE))
#define RCAR_IRQ_ACK_RECV (~(MAT | MDR))
#define RCAR_IRQ_ACK_SEND (~(MAT | MDE) & 0xFF)
#define RCAR_IRQ_ACK_RECV (~(MAT | MDR) & 0xFF)

#define ID_LAST_MSG (1 << 0)
#define ID_IOERROR (1 << 1)
Expand Down
11 changes: 5 additions & 6 deletions drivers/i2c/busses/i2c-rk3x.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,12 +433,11 @@ static void rk3x_i2c_set_scl_rate(struct rk3x_i2c *i2c, unsigned long scl_rate)
unsigned long i2c_rate = clk_get_rate(i2c->clk);
unsigned int div;

/* SCL rate = (clk rate) / (8 * DIV) */
div = DIV_ROUND_UP(i2c_rate, scl_rate * 8);

/* The lower and upper half of the CLKDIV reg describe the length of
* SCL low & high periods. */
div = DIV_ROUND_UP(div, 2);
/* set DIV = DIVH = DIVL
* SCL rate = (clk rate) / (8 * (DIVH + 1 + DIVL + 1))
* = (clk rate) / (16 * (DIV + 1))
*/
div = DIV_ROUND_UP(i2c_rate, scl_rate * 16) - 1;

i2c_writel(i2c, (div << 16) | (div & 0xffff), REG_CLKDIV);
}
Expand Down
57 changes: 45 additions & 12 deletions drivers/i2c/busses/i2c-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,34 +380,33 @@ static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev)
{
int ret;
if (!i2c_dev->hw->has_single_clk_source) {
ret = clk_prepare_enable(i2c_dev->fast_clk);
ret = clk_enable(i2c_dev->fast_clk);
if (ret < 0) {
dev_err(i2c_dev->dev,
"Enabling fast clk failed, err %d\n", ret);
return ret;
}
}
ret = clk_prepare_enable(i2c_dev->div_clk);
ret = clk_enable(i2c_dev->div_clk);
if (ret < 0) {
dev_err(i2c_dev->dev,
"Enabling div clk failed, err %d\n", ret);
clk_disable_unprepare(i2c_dev->fast_clk);
clk_disable(i2c_dev->fast_clk);
}
return ret;
}

static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev)
{
clk_disable_unprepare(i2c_dev->div_clk);
clk_disable(i2c_dev->div_clk);
if (!i2c_dev->hw->has_single_clk_source)
clk_disable_unprepare(i2c_dev->fast_clk);
clk_disable(i2c_dev->fast_clk);
}

static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
{
u32 val;
int err = 0;
int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE;
u32 clk_divisor;

err = tegra_i2c_clock_enable(i2c_dev);
Expand All @@ -428,9 +427,6 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
i2c_writel(i2c_dev, val, I2C_CNFG);
i2c_writel(i2c_dev, 0, I2C_INT_MASK);

clk_multiplier *= (i2c_dev->hw->clk_divisor_std_fast_mode + 1);
clk_set_rate(i2c_dev->div_clk, i2c_dev->bus_clk_rate * clk_multiplier);

/* Make sure clock divisor programmed correctly */
clk_divisor = i2c_dev->hw->clk_divisor_hs_mode;
clk_divisor |= i2c_dev->hw->clk_divisor_std_fast_mode <<
Expand Down Expand Up @@ -712,6 +708,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
void __iomem *base;
int irq;
int ret = 0;
int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
Expand Down Expand Up @@ -777,17 +774,39 @@ static int tegra_i2c_probe(struct platform_device *pdev)

platform_set_drvdata(pdev, i2c_dev);

if (!i2c_dev->hw->has_single_clk_source) {
ret = clk_prepare(i2c_dev->fast_clk);
if (ret < 0) {
dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret);
return ret;
}
}

clk_multiplier *= (i2c_dev->hw->clk_divisor_std_fast_mode + 1);
ret = clk_set_rate(i2c_dev->div_clk,
i2c_dev->bus_clk_rate * clk_multiplier);
if (ret) {
dev_err(i2c_dev->dev, "Clock rate change failed %d\n", ret);
goto unprepare_fast_clk;
}

ret = clk_prepare(i2c_dev->div_clk);
if (ret < 0) {
dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret);
goto unprepare_fast_clk;
}

ret = tegra_i2c_init(i2c_dev);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize i2c controller");
return ret;
goto unprepare_div_clk;
}

ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
if (ret) {
dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
return ret;
goto unprepare_div_clk;
}

i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
Expand All @@ -803,16 +822,30 @@ static int tegra_i2c_probe(struct platform_device *pdev)
ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
if (ret) {
dev_err(&pdev->dev, "Failed to add I2C adapter\n");
return ret;
goto unprepare_div_clk;
}

return 0;

unprepare_div_clk:
clk_unprepare(i2c_dev->div_clk);

unprepare_fast_clk:
if (!i2c_dev->hw->has_single_clk_source)
clk_unprepare(i2c_dev->fast_clk);

return ret;
}

static int tegra_i2c_remove(struct platform_device *pdev)
{
struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c_dev->adapter);

clk_unprepare(i2c_dev->div_clk);
if (!i2c_dev->hw->has_single_clk_source)
clk_unprepare(i2c_dev->fast_clk);

return 0;
}

Expand Down
Loading

0 comments on commit 12df9f3

Please sign in to comment.