Skip to content

Commit 218e149

Browse files
Naveen Krishna ChWolfram Sang
authored andcommitted
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 <[email protected]> Signed-off-by: Pankaj Dubey <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent a83bea7 commit 218e149

File tree

2 files changed

+64
-14
lines changed

2 files changed

+64
-14
lines changed

Documentation/devicetree/bindings/i2c/i2c-exynos5.txt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@ at various speeds ranging from 100khz to 3.4Mhz.
55

66
Required properties:
77
- 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+
916
- reg: physical base address of the controller and length of memory mapped
1017
region.
1118
- interrupts: interrupt number to the cpu.
@@ -26,7 +33,7 @@ Optional properties:
2633
Example:
2734

2835
hsi2c@12ca0000 {
29-
compatible = "samsung,exynos5-hsi2c";
36+
compatible = "samsung,exynos5250-hsi2c";
3037
reg = <0x12ca0000 0x100>;
3138
interrupts = <56>;
3239
clock-frequency = <100000>;

drivers/i2c/busses/i2c-exynos5.c

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,6 @@
7676
#define HSI2C_RXFIFO_TRIGGER_LEVEL(x) ((x) << 4)
7777
#define HSI2C_TXFIFO_TRIGGER_LEVEL(x) ((x) << 16)
7878

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-
8579
/* I2C_TRAILING_CTL Register bits */
8680
#define HSI2C_TRAILING_COUNT (0xf)
8781

@@ -183,14 +177,54 @@ struct exynos5_i2c {
183177
* 2. Fast speed upto 1Mbps
184178
*/
185179
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+
*/
193+
struct exynos_hsi2c_variant {
194+
unsigned int fifo_depth;
195+
};
196+
197+
static const struct exynos_hsi2c_variant exynos5250_hsi2c_data = {
198+
.fifo_depth = 64,
199+
};
200+
201+
static const struct exynos_hsi2c_variant exynos5260_hsi2c_data = {
202+
.fifo_depth = 16,
186203
};
187204

188205
static const struct of_device_id exynos5_i2c_match[] = {
189-
{ .compatible = "samsung,exynos5-hsi2c" },
190-
{},
206+
{
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+
}, {},
191216
};
192217
MODULE_DEVICE_TABLE(of, exynos5_i2c_match);
193218

219+
static 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+
194228
static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c)
195229
{
196230
writel(readl(i2c->regs + HSI2C_INT_STATUS),
@@ -415,7 +449,7 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
415449
fifo_status = readl(i2c->regs + HSI2C_FIFO_STATUS);
416450
fifo_level = HSI2C_TX_FIFO_LVL(fifo_status);
417451

418-
len = HSI2C_FIFO_MAX - fifo_level;
452+
len = i2c->variant->fifo_depth - fifo_level;
419453
if (len > (i2c->msg->len - i2c->msg_ptr))
420454
len = i2c->msg->len - i2c->msg_ptr;
421455

@@ -483,6 +517,7 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
483517
u32 i2c_auto_conf = 0;
484518
u32 fifo_ctl;
485519
unsigned long flags;
520+
unsigned short trig_lvl;
486521

487522
i2c_ctl = readl(i2c->regs + HSI2C_CTL);
488523
i2c_ctl &= ~(HSI2C_TXCHON | HSI2C_RXCHON);
@@ -493,13 +528,19 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
493528

494529
i2c_auto_conf = HSI2C_READ_WRITE;
495530

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+
497535
int_en |= (HSI2C_INT_RX_ALMOSTFULL_EN |
498536
HSI2C_INT_TRAILING_EN);
499537
} else {
500538
i2c_ctl |= HSI2C_TXCHON;
501539

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+
503544
int_en |= HSI2C_INT_TX_ALMOSTEMPTY_EN;
504545
}
505546

@@ -691,7 +732,9 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
691732
if (ret)
692733
goto err_clk;
693734

694-
exynos5_i2c_init(i2c);
735+
i2c->variant = exynos5_i2c_get_variant(pdev);
736+
737+
exynos5_i2c_reset(i2c);
695738

696739
ret = i2c_add_adapter(&i2c->adap);
697740
if (ret < 0) {

0 commit comments

Comments
 (0)