aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNaveen Krishna Ch <ch.naveen@samsung.com>2014-04-28 04:59:58 -0400
committerWolfram Sang <wsa@the-dreams.de>2014-05-22 04:09:22 -0400
commit218e1496135e94e901bf1c136d81ede7e2b418b8 (patch)
tree201d6039862e875ee922370bf50cc1b8523176e8
parenta83bea7c1170ad8c68d65ed2fff6a533e68f67a4 (diff)
i2c: exynos5: add support for HSI2C on Exynos5260 SoC
HSI2C module on Exynos5260 differs from current modules in following ways: 1. HSI2C on Exynos5260 has fifo_depth of 16bytes 2. Module needs to be reset as a part of init sequence. Hence, Following changes are involved. 1. Add a new compatible string and Updates the Documentation dt bindings. 2. Introduce a variant struct to support the changes in H/W 3. Reset the module during init. Thus, bringing the module back to default state irrespective of what firmware did with it. Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com> Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-exynos5.txt11
-rw-r--r--drivers/i2c/busses/i2c-exynos5.c67
2 files changed, 64 insertions, 14 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-exynos5.txt b/Documentation/devicetree/bindings/i2c/i2c-exynos5.txt
index 056732cfdcee..d4745e31f5c6 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-exynos5.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-exynos5.txt
@@ -5,7 +5,14 @@ at various speeds ranging from 100khz to 3.4Mhz.
5 5
6Required properties: 6Required properties:
7 - compatible: value should be. 7 - compatible: value should be.
8 -> "samsung,exynos5-hsi2c", for i2c compatible with exynos5 hsi2c. 8 -> "samsung,exynos5-hsi2c", (DEPRECATED)
9 for i2c compatible with HSI2C available
10 on Exynos5250 and Exynos5420 SoCs.
11 -> "samsung,exynos5250-hsi2c", for i2c compatible with HSI2C available
12 on Exynos5250 and Exynos5420 SoCs.
13 -> "samsung,exynos5260-hsi2c", for i2c compatible with HSI2C available
14 on Exynos5260 SoCs.
15
9 - reg: physical base address of the controller and length of memory mapped 16 - reg: physical base address of the controller and length of memory mapped
10 region. 17 region.
11 - interrupts: interrupt number to the cpu. 18 - interrupts: interrupt number to the cpu.
@@ -26,7 +33,7 @@ Optional properties:
26Example: 33Example:
27 34
28hsi2c@12ca0000 { 35hsi2c@12ca0000 {
29 compatible = "samsung,exynos5-hsi2c"; 36 compatible = "samsung,exynos5250-hsi2c";
30 reg = <0x12ca0000 0x100>; 37 reg = <0x12ca0000 0x100>;
31 interrupts = <56>; 38 interrupts = <56>;
32 clock-frequency = <100000>; 39 clock-frequency = <100000>;
diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
index 00af0a0a3361..ba1faf0ef96f 100644
--- a/drivers/i2c/busses/i2c-exynos5.c
+++ b/drivers/i2c/busses/i2c-exynos5.c
@@ -76,12 +76,6 @@
76#define HSI2C_RXFIFO_TRIGGER_LEVEL(x) ((x) << 4) 76#define HSI2C_RXFIFO_TRIGGER_LEVEL(x) ((x) << 4)
77#define HSI2C_TXFIFO_TRIGGER_LEVEL(x) ((x) << 16) 77#define HSI2C_TXFIFO_TRIGGER_LEVEL(x) ((x) << 16)
78 78
79/* As per user manual FIFO max depth is 64bytes */
80#define HSI2C_FIFO_MAX 0x40
81/* default trigger levels for Tx and Rx FIFOs */
82#define HSI2C_DEF_TXFIFO_LVL (HSI2C_FIFO_MAX - 0x30)
83#define HSI2C_DEF_RXFIFO_LVL (HSI2C_FIFO_MAX - 0x10)
84
85/* I2C_TRAILING_CTL Register bits */ 79/* I2C_TRAILING_CTL Register bits */
86#define HSI2C_TRAILING_COUNT (0xf) 80#define HSI2C_TRAILING_COUNT (0xf)
87 81
@@ -183,14 +177,54 @@ struct exynos5_i2c {
183 * 2. Fast speed upto 1Mbps 177 * 2. Fast speed upto 1Mbps
184 */ 178 */
185 int speed_mode; 179 int speed_mode;
180
181 /* Version of HS-I2C Hardware */
182 struct exynos_hsi2c_variant *variant;
183};
184
185/**
186 * struct exynos_hsi2c_variant - platform specific HSI2C driver data
187 * @fifo_depth: the fifo depth supported by the HSI2C module
188 *
189 * Specifies platform specific configuration of HSI2C module.
190 * Note: A structure for driver specific platform data is used for future
191 * expansion of its usage.
192 */
193struct exynos_hsi2c_variant {
194 unsigned int fifo_depth;
195};
196
197static const struct exynos_hsi2c_variant exynos5250_hsi2c_data = {
198 .fifo_depth = 64,
199};
200
201static const struct exynos_hsi2c_variant exynos5260_hsi2c_data = {
202 .fifo_depth = 16,
186}; 203};
187 204
188static const struct of_device_id exynos5_i2c_match[] = { 205static const struct of_device_id exynos5_i2c_match[] = {
189 { .compatible = "samsung,exynos5-hsi2c" }, 206 {
190 {}, 207 .compatible = "samsung,exynos5-hsi2c",
208 .data = &exynos5250_hsi2c_data
209 }, {
210 .compatible = "samsung,exynos5250-hsi2c",
211 .data = &exynos5250_hsi2c_data
212 }, {
213 .compatible = "samsung,exynos5260-hsi2c",
214 .data = &exynos5260_hsi2c_data
215 }, {},
191}; 216};
192MODULE_DEVICE_TABLE(of, exynos5_i2c_match); 217MODULE_DEVICE_TABLE(of, exynos5_i2c_match);
193 218
219static inline struct exynos_hsi2c_variant *exynos5_i2c_get_variant
220 (struct platform_device *pdev)
221{
222 const struct of_device_id *match;
223
224 match = of_match_node(exynos5_i2c_match, pdev->dev.of_node);
225 return (struct exynos_hsi2c_variant *)match->data;
226}
227
194static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c) 228static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c)
195{ 229{
196 writel(readl(i2c->regs + HSI2C_INT_STATUS), 230 writel(readl(i2c->regs + HSI2C_INT_STATUS),
@@ -415,7 +449,7 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
415 fifo_status = readl(i2c->regs + HSI2C_FIFO_STATUS); 449 fifo_status = readl(i2c->regs + HSI2C_FIFO_STATUS);
416 fifo_level = HSI2C_TX_FIFO_LVL(fifo_status); 450 fifo_level = HSI2C_TX_FIFO_LVL(fifo_status);
417 451
418 len = HSI2C_FIFO_MAX - fifo_level; 452 len = i2c->variant->fifo_depth - fifo_level;
419 if (len > (i2c->msg->len - i2c->msg_ptr)) 453 if (len > (i2c->msg->len - i2c->msg_ptr))
420 len = i2c->msg->len - i2c->msg_ptr; 454 len = i2c->msg->len - i2c->msg_ptr;
421 455
@@ -483,6 +517,7 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
483 u32 i2c_auto_conf = 0; 517 u32 i2c_auto_conf = 0;
484 u32 fifo_ctl; 518 u32 fifo_ctl;
485 unsigned long flags; 519 unsigned long flags;
520 unsigned short trig_lvl;
486 521
487 i2c_ctl = readl(i2c->regs + HSI2C_CTL); 522 i2c_ctl = readl(i2c->regs + HSI2C_CTL);
488 i2c_ctl &= ~(HSI2C_TXCHON | HSI2C_RXCHON); 523 i2c_ctl &= ~(HSI2C_TXCHON | HSI2C_RXCHON);
@@ -493,13 +528,19 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
493 528
494 i2c_auto_conf = HSI2C_READ_WRITE; 529 i2c_auto_conf = HSI2C_READ_WRITE;
495 530
496 fifo_ctl |= HSI2C_RXFIFO_TRIGGER_LEVEL(HSI2C_DEF_TXFIFO_LVL); 531 trig_lvl = (i2c->msg->len > i2c->variant->fifo_depth) ?
532 (i2c->variant->fifo_depth * 3 / 4) : i2c->msg->len;
533 fifo_ctl |= HSI2C_RXFIFO_TRIGGER_LEVEL(trig_lvl);
534
497 int_en |= (HSI2C_INT_RX_ALMOSTFULL_EN | 535 int_en |= (HSI2C_INT_RX_ALMOSTFULL_EN |
498 HSI2C_INT_TRAILING_EN); 536 HSI2C_INT_TRAILING_EN);
499 } else { 537 } else {
500 i2c_ctl |= HSI2C_TXCHON; 538 i2c_ctl |= HSI2C_TXCHON;
501 539
502 fifo_ctl |= HSI2C_TXFIFO_TRIGGER_LEVEL(HSI2C_DEF_RXFIFO_LVL); 540 trig_lvl = (i2c->msg->len > i2c->variant->fifo_depth) ?
541 (i2c->variant->fifo_depth * 1 / 4) : i2c->msg->len;
542 fifo_ctl |= HSI2C_TXFIFO_TRIGGER_LEVEL(trig_lvl);
543
503 int_en |= HSI2C_INT_TX_ALMOSTEMPTY_EN; 544 int_en |= HSI2C_INT_TX_ALMOSTEMPTY_EN;
504 } 545 }
505 546
@@ -691,7 +732,9 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
691 if (ret) 732 if (ret)
692 goto err_clk; 733 goto err_clk;
693 734
694 exynos5_i2c_init(i2c); 735 i2c->variant = exynos5_i2c_get_variant(pdev);
736
737 exynos5_i2c_reset(i2c);
695 738
696 ret = i2c_add_adapter(&i2c->adap); 739 ret = i2c_add_adapter(&i2c->adap);
697 if (ret < 0) { 740 if (ret < 0) {