76
76
#define HSI2C_RXFIFO_TRIGGER_LEVEL (x ) ((x) << 4)
77
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
79
/* I2C_TRAILING_CTL Register bits */
86
80
#define HSI2C_TRAILING_COUNT (0xf)
87
81
@@ -183,14 +177,54 @@ struct exynos5_i2c {
183
177
* 2. Fast speed upto 1Mbps
184
178
*/
185
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
+ */
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 ,
186
203
};
187
204
188
205
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
+ }, {},
191
216
};
192
217
MODULE_DEVICE_TABLE (of , exynos5_i2c_match );
193
218
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
+
194
228
static void exynos5_i2c_clr_pend_irq (struct exynos5_i2c * i2c )
195
229
{
196
230
writel (readl (i2c -> regs + HSI2C_INT_STATUS ),
@@ -415,7 +449,7 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
415
449
fifo_status = readl (i2c -> regs + HSI2C_FIFO_STATUS );
416
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
453
if (len > (i2c -> msg -> len - i2c -> msg_ptr ))
420
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
517
u32 i2c_auto_conf = 0 ;
484
518
u32 fifo_ctl ;
485
519
unsigned long flags ;
520
+ unsigned short trig_lvl ;
486
521
487
522
i2c_ctl = readl (i2c -> regs + HSI2C_CTL );
488
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
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
535
int_en |= (HSI2C_INT_RX_ALMOSTFULL_EN |
498
536
HSI2C_INT_TRAILING_EN );
499
537
} else {
500
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
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
732
if (ret )
692
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
739
ret = i2c_add_adapter (& i2c -> adap );
697
740
if (ret < 0 ) {
0 commit comments