55 * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
66 */
77
8+ #include <linux/bitfield.h>
89#include <linux/clk.h>
910#include <linux/completion.h>
1011#include <linux/i2c.h>
3334#define REG_CTRL_ACK_IGNORE BIT(1)
3435#define REG_CTRL_STATUS BIT(2)
3536#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)
4045
4146#define I2C_TIMEOUT_MS 500
47+ #define FILTER_DELAY 15
4248
4349enum {
4450 TOKEN_END = 0 ,
@@ -133,19 +139,24 @@ static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq)
133139 unsigned long clk_rate = clk_get_rate (i2c -> clk );
134140 unsigned int div ;
135141
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 );
137145
138146 /* clock divider has 12 bits */
139- if (div >= ( 1 << 12 )) {
147+ if (div > GENMASK ( 11 , 0 )) {
140148 dev_err (i2c -> dev , "requested bus frequency too low\n" );
141- div = ( 1 << 12 ) - 1 ;
149+ div = GENMASK ( 11 , 0 ) ;
142150 }
143151
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 ));
146157
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 );
149160
150161 dev_dbg (i2c -> dev , "%s: clk %lu, freq %u, div %u\n" , __func__ ,
151162 clk_rate , freq , div );
@@ -280,7 +291,10 @@ static void meson_i2c_do_start(struct meson_i2c *i2c, struct i2c_msg *msg)
280291 token = (msg -> flags & I2C_M_RD ) ? TOKEN_SLAVE_ADDR_READ :
281292 TOKEN_SLAVE_ADDR_WRITE ;
282293
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+
284298 meson_i2c_add_token (i2c , TOKEN_START );
285299 meson_i2c_add_token (i2c , token );
286300}
@@ -357,16 +371,12 @@ static int meson_i2c_xfer_messages(struct i2c_adapter *adap,
357371 struct meson_i2c * i2c = adap -> algo_data ;
358372 int i , ret = 0 ;
359373
360- clk_enable (i2c -> clk );
361-
362374 for (i = 0 ; i < num ; i ++ ) {
363375 ret = meson_i2c_xfer_msg (i2c , msgs + i , i == num - 1 , atomic );
364376 if (ret )
365377 break ;
366378 }
367379
368- clk_disable (i2c -> clk );
369-
370380 return ret ?: i ;
371381}
372382
@@ -435,7 +445,7 @@ static int meson_i2c_probe(struct platform_device *pdev)
435445 return ret ;
436446 }
437447
438- ret = clk_prepare (i2c -> clk );
448+ ret = clk_prepare_enable (i2c -> clk );
439449 if (ret < 0 ) {
440450 dev_err (& pdev -> dev , "can't prepare clock\n" );
441451 return ret ;
@@ -457,10 +467,14 @@ static int meson_i2c_probe(struct platform_device *pdev)
457467
458468 ret = i2c_add_adapter (& i2c -> adap );
459469 if (ret < 0 ) {
460- clk_unprepare (i2c -> clk );
470+ clk_disable_unprepare (i2c -> clk );
461471 return ret ;
462472 }
463473
474+ /* Disable filtering */
475+ meson_i2c_set_mask (i2c , REG_SLAVE_ADDR ,
476+ REG_SLV_SDA_FILTER | REG_SLV_SCL_FILTER , 0 );
477+
464478 meson_i2c_set_clk_div (i2c , timings .bus_freq_hz );
465479
466480 return 0 ;
@@ -471,7 +485,7 @@ static int meson_i2c_remove(struct platform_device *pdev)
471485 struct meson_i2c * i2c = platform_get_drvdata (pdev );
472486
473487 i2c_del_adapter (& i2c -> adap );
474- clk_unprepare (i2c -> clk );
488+ clk_disable_unprepare (i2c -> clk );
475489
476490 return 0 ;
477491}
0 commit comments