5
5
* Copyright (C) 2014 Beniamino Galvani <[email protected] >
6
6
*/
7
7
8
+ #include <linux/bitfield.h>
8
9
#include <linux/clk.h>
9
10
#include <linux/completion.h>
10
11
#include <linux/i2c.h>
33
34
#define REG_CTRL_ACK_IGNORE BIT(1)
34
35
#define REG_CTRL_STATUS BIT(2)
35
36
#define REG_CTRL_ERROR BIT(3)
36
- #define REG_CTRL_CLKDIV_SHIFT 12
37
- #define REG_CTRL_CLKDIV_MASK GENMASK(21, 12)
38
- #define REG_CTRL_CLKDIVEXT_SHIFT 28
39
- #define REG_CTRL_CLKDIVEXT_MASK GENMASK(29, 28)
37
+ #define REG_CTRL_CLKDIV GENMASK(21, 12)
38
+ #define REG_CTRL_CLKDIVEXT GENMASK(29, 28)
39
+
40
+ #define REG_SLV_ADDR GENMASK(7, 0)
41
+ #define REG_SLV_SDA_FILTER GENMASK(10, 8)
42
+ #define REG_SLV_SCL_FILTER GENMASK(13, 11)
43
+ #define REG_SLV_SCL_LOW GENMASK(27, 16)
44
+ #define REG_SLV_SCL_LOW_EN BIT(28)
40
45
41
46
#define I2C_TIMEOUT_MS 500
47
+ #define FILTER_DELAY 15
42
48
43
49
enum {
44
50
TOKEN_END = 0 ,
@@ -133,19 +139,24 @@ static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq)
133
139
unsigned long clk_rate = clk_get_rate (i2c -> clk );
134
140
unsigned int div ;
135
141
136
- div = DIV_ROUND_UP (clk_rate , freq * i2c -> data -> div_factor );
142
+ div = DIV_ROUND_UP (clk_rate , freq );
143
+ div -= FILTER_DELAY ;
144
+ div = DIV_ROUND_UP (div , i2c -> data -> div_factor );
137
145
138
146
/* clock divider has 12 bits */
139
- if (div >= ( 1 << 12 )) {
147
+ if (div > GENMASK ( 11 , 0 )) {
140
148
dev_err (i2c -> dev , "requested bus frequency too low\n" );
141
- div = ( 1 << 12 ) - 1 ;
149
+ div = GENMASK ( 11 , 0 ) ;
142
150
}
143
151
144
- meson_i2c_set_mask (i2c , REG_CTRL , REG_CTRL_CLKDIV_MASK ,
145
- (div & GENMASK (9 , 0 )) << REG_CTRL_CLKDIV_SHIFT );
152
+ meson_i2c_set_mask (i2c , REG_CTRL , REG_CTRL_CLKDIV ,
153
+ FIELD_PREP (REG_CTRL_CLKDIV , div & GENMASK (9 , 0 )));
154
+
155
+ meson_i2c_set_mask (i2c , REG_CTRL , REG_CTRL_CLKDIVEXT ,
156
+ FIELD_PREP (REG_CTRL_CLKDIVEXT , div >> 10 ));
146
157
147
- meson_i2c_set_mask ( i2c , REG_CTRL , REG_CTRL_CLKDIVEXT_MASK ,
148
- ( div >> 10 ) << REG_CTRL_CLKDIVEXT_SHIFT );
158
+ /* Disable HIGH/LOW mode */
159
+ meson_i2c_set_mask ( i2c , REG_SLAVE_ADDR , REG_SLV_SCL_LOW_EN , 0 );
149
160
150
161
dev_dbg (i2c -> dev , "%s: clk %lu, freq %u, div %u\n" , __func__ ,
151
162
clk_rate , freq , div );
@@ -280,7 +291,10 @@ static void meson_i2c_do_start(struct meson_i2c *i2c, struct i2c_msg *msg)
280
291
token = (msg -> flags & I2C_M_RD ) ? TOKEN_SLAVE_ADDR_READ :
281
292
TOKEN_SLAVE_ADDR_WRITE ;
282
293
283
- writel (msg -> addr << 1 , i2c -> regs + REG_SLAVE_ADDR );
294
+
295
+ meson_i2c_set_mask (i2c , REG_SLAVE_ADDR , REG_SLV_ADDR ,
296
+ FIELD_PREP (REG_SLV_ADDR , msg -> addr << 1 ));
297
+
284
298
meson_i2c_add_token (i2c , TOKEN_START );
285
299
meson_i2c_add_token (i2c , token );
286
300
}
@@ -357,16 +371,12 @@ static int meson_i2c_xfer_messages(struct i2c_adapter *adap,
357
371
struct meson_i2c * i2c = adap -> algo_data ;
358
372
int i , ret = 0 ;
359
373
360
- clk_enable (i2c -> clk );
361
-
362
374
for (i = 0 ; i < num ; i ++ ) {
363
375
ret = meson_i2c_xfer_msg (i2c , msgs + i , i == num - 1 , atomic );
364
376
if (ret )
365
377
break ;
366
378
}
367
379
368
- clk_disable (i2c -> clk );
369
-
370
380
return ret ?: i ;
371
381
}
372
382
@@ -435,7 +445,7 @@ static int meson_i2c_probe(struct platform_device *pdev)
435
445
return ret ;
436
446
}
437
447
438
- ret = clk_prepare (i2c -> clk );
448
+ ret = clk_prepare_enable (i2c -> clk );
439
449
if (ret < 0 ) {
440
450
dev_err (& pdev -> dev , "can't prepare clock\n" );
441
451
return ret ;
@@ -457,10 +467,14 @@ static int meson_i2c_probe(struct platform_device *pdev)
457
467
458
468
ret = i2c_add_adapter (& i2c -> adap );
459
469
if (ret < 0 ) {
460
- clk_unprepare (i2c -> clk );
470
+ clk_disable_unprepare (i2c -> clk );
461
471
return ret ;
462
472
}
463
473
474
+ /* Disable filtering */
475
+ meson_i2c_set_mask (i2c , REG_SLAVE_ADDR ,
476
+ REG_SLV_SDA_FILTER | REG_SLV_SCL_FILTER , 0 );
477
+
464
478
meson_i2c_set_clk_div (i2c , timings .bus_freq_hz );
465
479
466
480
return 0 ;
@@ -471,7 +485,7 @@ static int meson_i2c_remove(struct platform_device *pdev)
471
485
struct meson_i2c * i2c = platform_get_drvdata (pdev );
472
486
473
487
i2c_del_adapter (& i2c -> adap );
474
- clk_unprepare (i2c -> clk );
488
+ clk_disable_unprepare (i2c -> clk );
475
489
476
490
return 0 ;
477
491
}
0 commit comments