diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-mt65xx.c')
-rw-r--r-- | drivers/i2c/busses/i2c-mt65xx.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index aec8e6ce38a4..453358b4d9ca 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #define I2C_DMA_INT_FLAG_NONE 0x0000 | 60 | #define I2C_DMA_INT_FLAG_NONE 0x0000 |
61 | #define I2C_DMA_CLR_FLAG 0x0000 | 61 | #define I2C_DMA_CLR_FLAG 0x0000 |
62 | #define I2C_DMA_HARD_RST 0x0002 | 62 | #define I2C_DMA_HARD_RST 0x0002 |
63 | #define I2C_DMA_4G_MODE 0x0001 | ||
63 | 64 | ||
64 | #define I2C_DEFAULT_SPEED 100000 /* hz */ | 65 | #define I2C_DEFAULT_SPEED 100000 /* hz */ |
65 | #define MAX_FS_MODE_SPEED 400000 | 66 | #define MAX_FS_MODE_SPEED 400000 |
@@ -88,6 +89,8 @@ enum DMA_REGS_OFFSET { | |||
88 | OFFSET_RX_MEM_ADDR = 0x20, | 89 | OFFSET_RX_MEM_ADDR = 0x20, |
89 | OFFSET_TX_LEN = 0x24, | 90 | OFFSET_TX_LEN = 0x24, |
90 | OFFSET_RX_LEN = 0x28, | 91 | OFFSET_RX_LEN = 0x28, |
92 | OFFSET_TX_4G_MODE = 0x54, | ||
93 | OFFSET_RX_4G_MODE = 0x58, | ||
91 | }; | 94 | }; |
92 | 95 | ||
93 | enum i2c_trans_st_rs { | 96 | enum i2c_trans_st_rs { |
@@ -133,6 +136,7 @@ struct mtk_i2c_compatible { | |||
133 | unsigned char dcm: 1; | 136 | unsigned char dcm: 1; |
134 | unsigned char auto_restart: 1; | 137 | unsigned char auto_restart: 1; |
135 | unsigned char aux_len_reg: 1; | 138 | unsigned char aux_len_reg: 1; |
139 | unsigned char support_33bits: 1; | ||
136 | }; | 140 | }; |
137 | 141 | ||
138 | struct mtk_i2c { | 142 | struct mtk_i2c { |
@@ -182,6 +186,7 @@ static const struct mtk_i2c_compatible mt6577_compat = { | |||
182 | .dcm = 1, | 186 | .dcm = 1, |
183 | .auto_restart = 0, | 187 | .auto_restart = 0, |
184 | .aux_len_reg = 0, | 188 | .aux_len_reg = 0, |
189 | .support_33bits = 0, | ||
185 | }; | 190 | }; |
186 | 191 | ||
187 | static const struct mtk_i2c_compatible mt6589_compat = { | 192 | static const struct mtk_i2c_compatible mt6589_compat = { |
@@ -190,6 +195,7 @@ static const struct mtk_i2c_compatible mt6589_compat = { | |||
190 | .dcm = 0, | 195 | .dcm = 0, |
191 | .auto_restart = 0, | 196 | .auto_restart = 0, |
192 | .aux_len_reg = 0, | 197 | .aux_len_reg = 0, |
198 | .support_33bits = 0, | ||
193 | }; | 199 | }; |
194 | 200 | ||
195 | static const struct mtk_i2c_compatible mt8173_compat = { | 201 | static const struct mtk_i2c_compatible mt8173_compat = { |
@@ -198,6 +204,7 @@ static const struct mtk_i2c_compatible mt8173_compat = { | |||
198 | .dcm = 1, | 204 | .dcm = 1, |
199 | .auto_restart = 1, | 205 | .auto_restart = 1, |
200 | .aux_len_reg = 1, | 206 | .aux_len_reg = 1, |
207 | .support_33bits = 1, | ||
201 | }; | 208 | }; |
202 | 209 | ||
203 | static const struct of_device_id mtk_i2c_of_match[] = { | 210 | static const struct of_device_id mtk_i2c_of_match[] = { |
@@ -366,6 +373,11 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk, | |||
366 | return 0; | 373 | return 0; |
367 | } | 374 | } |
368 | 375 | ||
376 | static inline u32 mtk_i2c_set_4g_mode(dma_addr_t addr) | ||
377 | { | ||
378 | return (addr & BIT_ULL(32)) ? I2C_DMA_4G_MODE : I2C_DMA_CLR_FLAG; | ||
379 | } | ||
380 | |||
369 | static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, | 381 | static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, |
370 | int num, int left_num) | 382 | int num, int left_num) |
371 | { | 383 | { |
@@ -373,6 +385,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, | |||
373 | u16 start_reg; | 385 | u16 start_reg; |
374 | u16 control_reg; | 386 | u16 control_reg; |
375 | u16 restart_flag = 0; | 387 | u16 restart_flag = 0; |
388 | u32 reg_4g_mode; | ||
376 | dma_addr_t rpaddr = 0; | 389 | dma_addr_t rpaddr = 0; |
377 | dma_addr_t wpaddr = 0; | 390 | dma_addr_t wpaddr = 0; |
378 | int ret; | 391 | int ret; |
@@ -439,6 +452,12 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, | |||
439 | msgs->len, DMA_FROM_DEVICE); | 452 | msgs->len, DMA_FROM_DEVICE); |
440 | if (dma_mapping_error(i2c->dev, rpaddr)) | 453 | if (dma_mapping_error(i2c->dev, rpaddr)) |
441 | return -ENOMEM; | 454 | return -ENOMEM; |
455 | |||
456 | if (i2c->dev_comp->support_33bits) { | ||
457 | reg_4g_mode = mtk_i2c_set_4g_mode(rpaddr); | ||
458 | writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE); | ||
459 | } | ||
460 | |||
442 | writel((u32)rpaddr, i2c->pdmabase + OFFSET_RX_MEM_ADDR); | 461 | writel((u32)rpaddr, i2c->pdmabase + OFFSET_RX_MEM_ADDR); |
443 | writel(msgs->len, i2c->pdmabase + OFFSET_RX_LEN); | 462 | writel(msgs->len, i2c->pdmabase + OFFSET_RX_LEN); |
444 | } else if (i2c->op == I2C_MASTER_WR) { | 463 | } else if (i2c->op == I2C_MASTER_WR) { |
@@ -448,6 +467,12 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, | |||
448 | msgs->len, DMA_TO_DEVICE); | 467 | msgs->len, DMA_TO_DEVICE); |
449 | if (dma_mapping_error(i2c->dev, wpaddr)) | 468 | if (dma_mapping_error(i2c->dev, wpaddr)) |
450 | return -ENOMEM; | 469 | return -ENOMEM; |
470 | |||
471 | if (i2c->dev_comp->support_33bits) { | ||
472 | reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr); | ||
473 | writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE); | ||
474 | } | ||
475 | |||
451 | writel((u32)wpaddr, i2c->pdmabase + OFFSET_TX_MEM_ADDR); | 476 | writel((u32)wpaddr, i2c->pdmabase + OFFSET_TX_MEM_ADDR); |
452 | writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN); | 477 | writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN); |
453 | } else { | 478 | } else { |
@@ -465,6 +490,15 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, | |||
465 | msgs->len, DMA_TO_DEVICE); | 490 | msgs->len, DMA_TO_DEVICE); |
466 | return -ENOMEM; | 491 | return -ENOMEM; |
467 | } | 492 | } |
493 | |||
494 | if (i2c->dev_comp->support_33bits) { | ||
495 | reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr); | ||
496 | writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE); | ||
497 | |||
498 | reg_4g_mode = mtk_i2c_set_4g_mode(rpaddr); | ||
499 | writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE); | ||
500 | } | ||
501 | |||
468 | writel((u32)wpaddr, i2c->pdmabase + OFFSET_TX_MEM_ADDR); | 502 | writel((u32)wpaddr, i2c->pdmabase + OFFSET_TX_MEM_ADDR); |
469 | writel((u32)rpaddr, i2c->pdmabase + OFFSET_RX_MEM_ADDR); | 503 | writel((u32)rpaddr, i2c->pdmabase + OFFSET_RX_MEM_ADDR); |
470 | writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN); | 504 | writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN); |
@@ -729,6 +763,14 @@ static int mtk_i2c_probe(struct platform_device *pdev) | |||
729 | return -EINVAL; | 763 | return -EINVAL; |
730 | } | 764 | } |
731 | 765 | ||
766 | if (i2c->dev_comp->support_33bits) { | ||
767 | ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(33)); | ||
768 | if (ret) { | ||
769 | dev_err(&pdev->dev, "dma_set_mask return error.\n"); | ||
770 | return ret; | ||
771 | } | ||
772 | } | ||
773 | |||
732 | ret = mtk_i2c_clock_enable(i2c); | 774 | ret = mtk_i2c_clock_enable(i2c); |
733 | if (ret) { | 775 | if (ret) { |
734 | dev_err(&pdev->dev, "clock enable failed!\n"); | 776 | dev_err(&pdev->dev, "clock enable failed!\n"); |