diff options
| -rw-r--r-- | drivers/i2c/busses/i2c-pxa-pci.c | 5 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 60 |
2 files changed, 49 insertions, 16 deletions
diff --git a/drivers/i2c/busses/i2c-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c index 6659d269b841..b73da6cd6f91 100644 --- a/drivers/i2c/busses/i2c-pxa-pci.c +++ b/drivers/i2c/busses/i2c-pxa-pci.c | |||
| @@ -109,12 +109,15 @@ static int __devinit ce4100_i2c_probe(struct pci_dev *dev, | |||
| 109 | return -EINVAL; | 109 | return -EINVAL; |
| 110 | } | 110 | } |
| 111 | sds = kzalloc(sizeof(*sds), GFP_KERNEL); | 111 | sds = kzalloc(sizeof(*sds), GFP_KERNEL); |
| 112 | if (!sds) | 112 | if (!sds) { |
| 113 | ret = -ENOMEM; | ||
| 113 | goto err_mem; | 114 | goto err_mem; |
| 115 | } | ||
| 114 | 116 | ||
| 115 | for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) { | 117 | for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) { |
| 116 | sds->pdev[i] = add_i2c_device(dev, i); | 118 | sds->pdev[i] = add_i2c_device(dev, i); |
| 117 | if (IS_ERR(sds->pdev[i])) { | 119 | if (IS_ERR(sds->pdev[i])) { |
| 120 | ret = PTR_ERR(sds->pdev[i]); | ||
| 118 | while (--i >= 0) | 121 | while (--i >= 0) |
| 119 | platform_device_unregister(sds->pdev[i]); | 122 | platform_device_unregister(sds->pdev[i]); |
| 120 | goto err_dev_add; | 123 | goto err_dev_add; |
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 2440b7411978..3c94c4a81a55 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c | |||
| @@ -270,14 +270,30 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) | |||
| 270 | 270 | ||
| 271 | /* Rounds down to not include partial word at the end of buf */ | 271 | /* Rounds down to not include partial word at the end of buf */ |
| 272 | words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD; | 272 | words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD; |
| 273 | if (words_to_transfer > tx_fifo_avail) | ||
| 274 | words_to_transfer = tx_fifo_avail; | ||
| 275 | 273 | ||
| 276 | i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); | 274 | /* It's very common to have < 4 bytes, so optimize that case. */ |
| 277 | 275 | if (words_to_transfer) { | |
| 278 | buf += words_to_transfer * BYTES_PER_FIFO_WORD; | 276 | if (words_to_transfer > tx_fifo_avail) |
| 279 | buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD; | 277 | words_to_transfer = tx_fifo_avail; |
| 280 | tx_fifo_avail -= words_to_transfer; | 278 | |
| 279 | /* | ||
| 280 | * Update state before writing to FIFO. If this casues us | ||
| 281 | * to finish writing all bytes (AKA buf_remaining goes to 0) we | ||
| 282 | * have a potential for an interrupt (PACKET_XFER_COMPLETE is | ||
| 283 | * not maskable). We need to make sure that the isr sees | ||
| 284 | * buf_remaining as 0 and doesn't call us back re-entrantly. | ||
| 285 | */ | ||
| 286 | buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD; | ||
| 287 | tx_fifo_avail -= words_to_transfer; | ||
| 288 | i2c_dev->msg_buf_remaining = buf_remaining; | ||
| 289 | i2c_dev->msg_buf = buf + | ||
| 290 | words_to_transfer * BYTES_PER_FIFO_WORD; | ||
| 291 | barrier(); | ||
| 292 | |||
| 293 | i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); | ||
| 294 | |||
| 295 | buf += words_to_transfer * BYTES_PER_FIFO_WORD; | ||
| 296 | } | ||
| 281 | 297 | ||
| 282 | /* | 298 | /* |
| 283 | * If there is a partial word at the end of buf, handle it manually to | 299 | * If there is a partial word at the end of buf, handle it manually to |
| @@ -287,14 +303,15 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) | |||
| 287 | if (tx_fifo_avail > 0 && buf_remaining > 0) { | 303 | if (tx_fifo_avail > 0 && buf_remaining > 0) { |
| 288 | BUG_ON(buf_remaining > 3); | 304 | BUG_ON(buf_remaining > 3); |
| 289 | memcpy(&val, buf, buf_remaining); | 305 | memcpy(&val, buf, buf_remaining); |
| 306 | |||
| 307 | /* Again update before writing to FIFO to make sure isr sees. */ | ||
| 308 | i2c_dev->msg_buf_remaining = 0; | ||
| 309 | i2c_dev->msg_buf = NULL; | ||
| 310 | barrier(); | ||
| 311 | |||
| 290 | i2c_writel(i2c_dev, val, I2C_TX_FIFO); | 312 | i2c_writel(i2c_dev, val, I2C_TX_FIFO); |
| 291 | buf_remaining = 0; | ||
| 292 | tx_fifo_avail--; | ||
| 293 | } | 313 | } |
| 294 | 314 | ||
| 295 | BUG_ON(tx_fifo_avail > 0 && buf_remaining > 0); | ||
| 296 | i2c_dev->msg_buf_remaining = buf_remaining; | ||
| 297 | i2c_dev->msg_buf = buf; | ||
| 298 | return 0; | 315 | return 0; |
| 299 | } | 316 | } |
| 300 | 317 | ||
| @@ -411,9 +428,10 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) | |||
| 411 | tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ); | 428 | tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ); |
| 412 | } | 429 | } |
| 413 | 430 | ||
| 414 | if ((status & I2C_INT_PACKET_XFER_COMPLETE) && | 431 | if (status & I2C_INT_PACKET_XFER_COMPLETE) { |
| 415 | !i2c_dev->msg_buf_remaining) | 432 | BUG_ON(i2c_dev->msg_buf_remaining); |
| 416 | complete(&i2c_dev->msg_complete); | 433 | complete(&i2c_dev->msg_complete); |
| 434 | } | ||
| 417 | 435 | ||
| 418 | i2c_writel(i2c_dev, status, I2C_INT_STATUS); | 436 | i2c_writel(i2c_dev, status, I2C_INT_STATUS); |
| 419 | if (i2c_dev->is_dvc) | 437 | if (i2c_dev->is_dvc) |
| @@ -531,7 +549,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | |||
| 531 | 549 | ||
| 532 | static u32 tegra_i2c_func(struct i2c_adapter *adap) | 550 | static u32 tegra_i2c_func(struct i2c_adapter *adap) |
| 533 | { | 551 | { |
| 534 | return I2C_FUNC_I2C; | 552 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; |
| 535 | } | 553 | } |
| 536 | 554 | ||
| 537 | static const struct i2c_algorithm tegra_i2c_algo = { | 555 | static const struct i2c_algorithm tegra_i2c_algo = { |
| @@ -719,6 +737,17 @@ static int tegra_i2c_resume(struct platform_device *pdev) | |||
| 719 | } | 737 | } |
| 720 | #endif | 738 | #endif |
| 721 | 739 | ||
| 740 | #if defined(CONFIG_OF) | ||
| 741 | /* Match table for of_platform binding */ | ||
| 742 | static const struct of_device_id tegra_i2c_of_match[] __devinitconst = { | ||
| 743 | { .compatible = "nvidia,tegra20-i2c", }, | ||
| 744 | {}, | ||
| 745 | }; | ||
| 746 | MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); | ||
| 747 | #else | ||
| 748 | #define tegra_i2c_of_match NULL | ||
| 749 | #endif | ||
| 750 | |||
| 722 | static struct platform_driver tegra_i2c_driver = { | 751 | static struct platform_driver tegra_i2c_driver = { |
| 723 | .probe = tegra_i2c_probe, | 752 | .probe = tegra_i2c_probe, |
| 724 | .remove = tegra_i2c_remove, | 753 | .remove = tegra_i2c_remove, |
| @@ -729,6 +758,7 @@ static struct platform_driver tegra_i2c_driver = { | |||
| 729 | .driver = { | 758 | .driver = { |
| 730 | .name = "tegra-i2c", | 759 | .name = "tegra-i2c", |
| 731 | .owner = THIS_MODULE, | 760 | .owner = THIS_MODULE, |
| 761 | .of_match_table = tegra_i2c_of_match, | ||
| 732 | }, | 762 | }, |
| 733 | }; | 763 | }; |
| 734 | 764 | ||
