[PATCH 2/3] i2c: mediatek: Fix wrong dma sync flag

2021-04-16 Thread Qii Wang
The right flag is apdma_sync when apdma remove hand-shake signel.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 3e34261..bf25acb 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -479,7 +479,7 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 {
u16 control_reg;
 
-   if (i2c->dev_comp->dma_sync) {
+   if (i2c->dev_comp->apdma_sync) {
writel(I2C_DMA_WARM_RST, i2c->pdmabase + OFFSET_RST);
udelay(10);
writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
-- 
1.9.1



[PATCH 1/3] i2c: mediatek: Fix send master code at more than 1MHz

2021-04-16 Thread Qii Wang
There are some omissions in the previous patch about replacing
I2C_MAX_FAST_MODE__FREQ with I2C_MAX_FAST_MODE_PLUS_FREQ and
need to fix it.

Fixes: b44658e755b5("i2c: mediatek: Send i2c master code at more than 1MHz")
Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 2ffd2f3..3e34261 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -564,7 +564,7 @@ static const struct i2c_spec_values 
*mtk_i2c_get_spec(unsigned int speed)
 
 static int mtk_i2c_max_step_cnt(unsigned int target_speed)
 {
-   if (target_speed > I2C_MAX_FAST_MODE_FREQ)
+   if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ)
return MAX_HS_STEP_CNT_DIV;
else
return MAX_STEP_CNT_DIV;
@@ -635,7 +635,7 @@ static int mtk_i2c_check_ac_timing(struct mtk_i2c *i2c,
if (sda_min > sda_max)
return -3;
 
-   if (check_speed > I2C_MAX_FAST_MODE_FREQ) {
+   if (check_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) {
if (i2c->dev_comp->ltiming_adjust) {
i2c->ac_timing.hs = I2C_TIME_DEFAULT_VALUE |
(sample_cnt << 12) | (high_cnt << 8);
@@ -850,7 +850,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
 
control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
-   if ((i2c->speed_hz > I2C_MAX_FAST_MODE_FREQ) || (left_num >= 1))
+   if ((i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ) || (left_num >= 1))
control_reg |= I2C_CONTROL_RS;
 
if (i2c->op == I2C_MASTER_WRRD)
@@ -1067,7 +1067,8 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
}
}
 
-   if (i2c->auto_restart && num >= 2 && i2c->speed_hz > 
I2C_MAX_FAST_MODE_FREQ)
+   if (i2c->auto_restart && num >= 2 &&
+   i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ)
/* ignore the first restart irq after the master code,
 * otherwise the first transfer will be discarded.
 */
-- 
1.9.1



[PATCH 3/3] i2c: mediatek: Use scl_int_delay_ns to compensate clock-stretching

2021-04-16 Thread Qii Wang
The parameters of tSU,STA/tHD,STA/tSU,STOP maybe out of spec due
to device clock-stretch or circuit loss, we could get a suitable
scl_int_delay_ns from i2c_timings to compensate these parameters
to meet the spec via EXT_CONF register.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index bf25acb..5ddfa4e 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -231,6 +231,7 @@ struct mtk_i2c {
struct i2c_adapter adap;/* i2c host adapter */
struct device *dev;
struct completion msg_complete;
+   struct i2c_timings timing_info;
 
/* set in i2c probe */
void __iomem *base; /* i2c base addr */
@@ -607,7 +608,8 @@ static int mtk_i2c_check_ac_timing(struct mtk_i2c *i2c,
else
clk_ns = sample_ns / 2;
 
-   su_sta_cnt = DIV_ROUND_UP(spec->min_su_sta_ns, clk_ns);
+   su_sta_cnt = DIV_ROUND_UP(spec->min_su_sta_ns +
+ i2c->timing_info.scl_int_delay_ns, clk_ns);
if (su_sta_cnt > max_sta_cnt)
return -1;
 
@@ -1176,6 +1178,8 @@ static int mtk_i2c_parse_dt(struct device_node *np, 
struct mtk_i2c *i2c)
i2c->use_push_pull =
of_property_read_bool(np, "mediatek,use-push-pull");
 
+   i2c_parse_fw_timings(i2c->dev, &i2c->timing_info, true);
+
return 0;
 }
 
-- 
1.9.1



[PATCH 0/3] Add some fix patches

2021-04-16 Thread Qii Wang
This series are based on 5.12-rc2 and we provide three i2c patches
to fix some historical issues.

Qii Wang (3):
  i2c: mediatek: Fix send master code at more than 1MHz
  i2c: mediatek: Fix wrong dma sync flag
  i2c: mediatek: Use scl_int_delay_ns to compensate clock-stretching

 drivers/i2c/busses/i2c-mt65xx.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

-- 
1.9.1


Re: [RESEND] i2c: mediatek: Get device clock-stretch time via dts

2021-04-13 Thread Qii Wang
On Tue, 2021-04-13 at 22:17 +0200, Wolfram Sang wrote:
> On Mon, Apr 12, 2021 at 08:03:14PM +0800, Qii Wang wrote:
> > I can't see the relationship between "i2c-scl-falling-time-ns" and clock
> > stretching, is there a parameter related to clock stretching?
> 
> ( you wrote "i2c-scl-falling-time-ns" above, didn't you mean
> "i2c-scl-internal-delay-ns" instead? )
> 

I am sorry, I have confused your comment with lkjoon's comment in the
last mail. what I actually want to say is "i2c-scl-internal-delay-ns".

> Not yet, and I wonder if there can be one. In I2C (not SMBus), devices
> are allowed to stretch the clock as long as they want, so what should be
> specified here?
> 
> I suggesteed "internal-delay" because AFAIU your hardware needs this
> delay to be able to cope with clock stretching.
> 

If there is not a maximum value for clock stretching,
"i2c-scl-internal-delay-ns" should be a good choice for our hardware,
although it maybe not for clock stretching.

> > If you think both of them will affect the ac-timing of SCL, at this
> > point, "i2c-scl-falling-time-ns" maybe a good choice.
> 
> Do you mean "i2c-scl-falling-time-ns" or "i2c-scl-internal-delay-ns"?
> 

"i2c-scl-internal-delay-ns" is better.

Thanks for your review.
Qii




Re: [RESEND] i2c: mediatek: Get device clock-stretch time via dts

2021-04-12 Thread Qii Wang
On Wed, 2021-04-07 at 20:19 +0200, Wolfram Sang wrote:
> > Due to clock stretch, our HW IP cannot meet the ac-timing
> > spec(tSU;STA,tSU;STO). 
> > There isn't a same delay for clock stretching, so we need pass a
> > parameter which can be found through measurement to meet most
> > conditions.
> 
> What about using this existing binding?
> 
> - i2c-scl-internal-delay-ns
> Number of nanoseconds the IP core additionally needs to setup SCL.
> 

I can't see the relationship between "i2c-scl-falling-time-ns" and clock
stretching, is there a parameter related to clock stretching?
If you think both of them will affect the ac-timing of SCL, at this
point, "i2c-scl-falling-time-ns" maybe a good choice.



Re: [RESEND] i2c: mediatek: Get device clock-stretch time via dts

2021-04-07 Thread Qii Wang
On Tue, 2021-04-06 at 21:48 +0200, Wolfram Sang wrote:
> On Sat, Mar 13, 2021 at 04:04:24PM +0800, qii.w...@mediatek.com wrote:
> > From: Qii Wang 
> > 
> > tSU,STA/tHD,STA/tSU,STOP maybe out of spec due to device
> > clock-stretching or circuit loss, we could get device
> > clock-stretch time from dts to adjust these parameters
> > to meet the spec via EXT_CONF register.
> > 
> > Signed-off-by: Qii Wang 
> 
> I tried to understand from the code what the new binding expresses, but
> I don't fully understand it. Is it the maximum clock stretch time?
> Because I cannot recall a device which always uses the same delay for
> clock stretching.
> 

Due to clock stretch, our HW IP cannot meet the ac-timing
spec(tSU;STA,tSU;STO). 
There isn't a same delay for clock stretching, so we need pass a
parameter which can be found through measurement to meet most
conditions.



Re: [PATCH] dt-bindings: i2c: Add device clock-stretch time via dts

2021-03-25 Thread Qii Wang
On Wed, 2021-03-24 at 11:12 -0600, Rob Herring wrote:
> On Sat, Mar 13, 2021 at 04:07:09PM +0800, qii.w...@mediatek.com wrote:
> > From: Qii Wang 
> > 
> > tSU,STA/tHD,STA/tSU,STOP maybe out of spec due to device
> > clock-stretching or circuit loss, we could get device
> > clock-stretch time from dts to adjust these parameters
> > to meet the spec via EXT_CONF register.
> > 
> > Signed-off-by: Qii Wang 
> > ---
> >  Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt 
> > b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
> > index 7f0194f..97f66f0 100644
> > --- a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
> > +++ b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
> > @@ -32,6 +32,7 @@ Optional properties:
> >- mediatek,have-pmic: platform can control i2c form special pmic side.
> >  Only mt6589 and mt8135 support this feature.
> >- mediatek,use-push-pull: IO config use push-pull mode.
> > +  - clock-stretch-ns: Slave device clock-stretch time.
> 
> Should be a common I2C property?
> 

Wolfram Sang will look at this next and think about it. I hope it would
be a common I2C property.

> >  
> >  Example:
> >  
> > -- 
> > 1.9.1
> > 



Re: [PATCH] i2c: mediatek: Get device clock-stretch time via dts

2021-03-02 Thread Qii Wang
Hi,
On Tue, 2021-03-02 at 19:30 +0800, Ikjoon Jang wrote:
> Hi Qii,
> >
> > @@ -1171,6 +1173,8 @@ static int mtk_i2c_parse_dt(struct device_node *np, 
> > struct mtk_i2c *i2c)
> > if (i2c->clk_src_div == 0)
> > return -EINVAL;
> >
> > +   of_property_read_u32(np, "clock-stretch-ns", 
> > &i2c->clock_stretch_ns);
> > +
> 
> I think this new property "clock-stretch-ns" is for the same purpose of
> "i2c-scl-falling-time-ns" + "i2c-scl-rising-time-ns" defined in
> Documentation/devicetree/bindings/i2c/i2c.txt?
> 

I haven't find the corresponding instructions;and this patch is for the
problem caused by clock-stretch when the scl is pulled.

> > i2c->have_pmic = of_property_read_bool(np, "mediatek,have-pmic");
> > i2c->use_push_pull =
> > of_property_read_bool(np, "mediatek,use-push-pull");
> > --
> > 1.9.1
> > ___
> > Linux-mediatek mailing list
> > linux-media...@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-mediatek



Re: [PATCH] i2c: mediatek: Get device clock-stretch time via dts

2021-03-01 Thread Qii Wang
Hi,
On Wed, 2021-02-03 at 18:35 +0800, qii.w...@mediatek.com wrote:
> From: Qii Wang 
> 
> tSU,STA/tHD,STA/tSU,STOP maybe out of spec due to device
> clock-stretching or circuit loss, we could get device
> clock-stretch time from dts to adjust these parameters
> to meet the spec via EXT_CONF register.
> 
> Signed-off-by: Qii Wang 
> ---

Can it merge into 5.12? or do I need to resend the patch?

Thanks,
Qii


Re: [RESEND, V2] i2c: mediatek: Move suspend and resume handling to NOIRQ phase

2021-01-26 Thread Qii Wang
Hi Wolfram,

On Sat, 2021-01-09 at 16:29 +0800, qii.w...@mediatek.com wrote:
> From: Qii Wang 
> 
> Some i2c device driver indirectly uses I2C driver when it is now
> being suspended. The i2c devices driver is suspended during the
> NOIRQ phase and this cannot be changed due to other dependencies.
> Therefore, we also need to move the suspend handling for the I2C
> controller driver to the NOIRQ phase as well.
> 
> Signed-off-by: Qii Wang 
> ---
> 
> Changes in v2:
> - Replied some comments
> - Fixed the wrong spelling medaitek to mediatek
> 
>  drivers/i2c/busses/i2c-mt65xx.c | 19 ---
>  1 file changed, 16 insertions(+), 3 deletions(-)
> 

I haven't seen any new comments, can it go into 5.11?

Thanks

Qii


Re: i2c: mediatek: Fix apdma and i2c hand-shake timeout

2021-01-04 Thread Qii Wang
On Mon, 2021-01-04 at 19:32 +0100, Wolfram Sang wrote:
> On Mon, Jan 04, 2021 at 07:29:59PM +0100, Wolfram Sang wrote:
> > On Thu, Dec 24, 2020 at 08:26:07PM +0800, qii.w...@mediatek.com wrote:
> > > From: Qii Wang 
> > > 
> > > With the apdma remove hand-shake signal, it requirs special
> > > operation timing to reset i2c manually, otherwise the interrupt
> > > will not be triggered, i2c transmission will be timeout.
> > > 
> > > Signed-off-by: Qii Wang 
> > 
> > Applied to for-current, thanks!
> 
> Any Fixes:-Tag we could add?
> 

Could you help me add:
Fixes: 8426fe70cfa4("i2c: mediatek: Add apdma sync in i2c driver")
Thanks


Re: [v2] i2c: mediatek: Move suspend and resume handling to NOIRQ phase

2020-12-22 Thread Qii Wang
Hi sirs:
If there is no new comment, I will resent it in 5.11.


Re: [v2] i2c: mediatek: Move suspend and resume handling to NOIRQ phase

2020-12-15 Thread Qii Wang
On Mon, 2020-12-14 at 22:08 +0200, Grygorii Strashko wrote:
> 
> On 14/12/2020 10:48, Qii Wang wrote:
> > On Thu, 2020-12-10 at 15:03 +0200, Grygorii Strashko wrote:
> >>
> >> On 10/12/2020 03:56, Qii Wang wrote:
> >>> On Mon, 2020-12-07 at 18:35 +0200, Grygorii Strashko wrote:
> >>>>
> >>>>>
> >>>>> On Thu, 2020-12-03 at 10:01 +0200, Grygorii Strashko wrote:
> >>>>>>
> >>>>>> On 03/12/2020 03:25, Qii Wang wrote:
> >>>>>>> On Wed, 2020-12-02 at 16:35 +0100, Wolfram Sang wrote:
> >>>>>>>> Hi,
> >>>>>>>>
> >>>>>>>>> Some i2c device driver indirectly uses I2C driver when it is now
> >>>>>>>>> being suspended. The i2c devices driver is suspended during the
> >>>>>>>>> NOIRQ phase and this cannot be changed due to other dependencies.
> >>>>>>>>> Therefore, we also need to move the suspend handling for the I2C
> >>>>>>>>> controller driver to the NOIRQ phase as well.
> >>>>>>>>>
> >>>>>>>>> Signed-off-by: Qii Wang 
> >>>>>>>>
> >>>>>>>> Is this a bugfix and should go into 5.10? Or can it wait for 5.11?
> >>>>>>>>
> >>>>>>>
> >>>>>>> Yes, Can you help to apply it into 5.10? Thanks
> >>>>>>
> >>>>>> To be honest if you still do have any i2c device which accessing i2c 
> >>>>>> buss after _noirq
> >>>>>> stage and your driver does not implement .master_xfer_atomic() - you 
> >>>>>> definitely have a bigger problem.
> >>>>>> So adding IRQF_NO_SUSPEND sound like a hack and probably works just by 
> >>>>>> luck.
> >>>>>>
> >>>>>
> >>>>> At present, it is only a problem caused by missing interrupts,
> >>>>> and .master_xfer_atomic() just a implement in polling mode. Why not set
> >>>>> the interrupt to a state that can always be triggered?
> >>>>>
> >>>>>
> >>>>
> >>>> Because you must not use any IRQ driven operations after _noirq suspend 
> >>>> state as it might (and most probably will)
> >>>> cause unpredictable behavior later  in suspend_enter():
> >>>>
> >>>>  arch_suspend_disable_irqs();
> >>>>  BUG_ON(!irqs_disabled());
> >>>> ^after this point any IRQ driven I2C transfer will cause IRQ to be 
> >>>> re-enabled
> >>>>
> >>>> if you need  turn off device from platform callbacks -  
> >>>> .master_xfer_atomic() has to be implemented and used.
> >>>> 
> >>> Maybe my comment is a bit disturbing.Our purpose is not to call i2c and
> >>> use interrupts after _noirq pauses.So We use
> >>> i2c_mark_adapter_suspended&i2c_mark_adapter_resumed to block these i2c
> >>> transfers, There will not have any IRQ driven I2C transfer after this
> >>> point:
> >>>   arch_suspend_disable_irqs();
> >>>   BUG_ON(!irqs_disabled());
> >>> But some device driver will do i2c transfer after
> >>> dpm_noirq_resume_devices in dpm_resume_noirq(PMSG_RESUME) when our
> >>> driver irq hasn't resume.
> >>>   void dpm_resume_noirq(pm_message_t state)
> >>>   {
> >>>   dpm_noirq_resume_devices(state);
> >>
> >> Just to clarify. You have resume sequence in dpm_noirq_resume_devices
> >>dpm_noirq_resume_devices -> resume I2C -> resume some device -> do i2c 
> >> transfer after?
> >>
> > 
> > Yes.
> 
> huh. First consider IRQF_EARLY_RESUME - it's better, but still will be a hack
> 
There should be the same problem during the suspend process, So
IRQF_EARLY_RESUME should not be able to solve the problem.

> > 
> >> Is "some device" in Kernel mainline?
> >>
> > 
> > The problematic device driver is drivers/regulator/da9211-regulator.c in
> > Kernel mainline.
> 
> regulator is passive device, somebody should call it !?
> 
> And da9211-regulator IRQ handler should remain disabled till 
> resume_device_irqs() call.
> 

Not only will i2c transfer be called in da9211-regulator IRQ handler,
but also other drivers will call da9211_buck_ops which containing i2c
transfers.

> note. regulator_class implements only
> 
> static const struct dev_pm_ops __maybe_unused regulator_pm_ops = {
>   .suspend= regulator_suspend,
>   .resume = regulator_resume,
> };
> 
> 
> > 
> >>>   resume_device_irqs();
> >>>   device_wakeup_disarm_wake_irqs();
> >>>   cpuidle_resume();
> >>>   }
> >>> .master_xfer_atomic() seems to be invalid for this question at this
> >>> time?
> >>>
> >>
> > 
> 



Re: [v2] i2c: mediatek: Move suspend and resume handling to NOIRQ phase

2020-12-14 Thread Qii Wang
On Thu, 2020-12-10 at 15:03 +0200, Grygorii Strashko wrote:
> 
> On 10/12/2020 03:56, Qii Wang wrote:
> > On Mon, 2020-12-07 at 18:35 +0200, Grygorii Strashko wrote:
> >>
> >>>
> >>> On Thu, 2020-12-03 at 10:01 +0200, Grygorii Strashko wrote:
> >>>>
> >>>> On 03/12/2020 03:25, Qii Wang wrote:
> >>>>> On Wed, 2020-12-02 at 16:35 +0100, Wolfram Sang wrote:
> >>>>>> Hi,
> >>>>>>
> >>>>>>> Some i2c device driver indirectly uses I2C driver when it is now
> >>>>>>> being suspended. The i2c devices driver is suspended during the
> >>>>>>> NOIRQ phase and this cannot be changed due to other dependencies.
> >>>>>>> Therefore, we also need to move the suspend handling for the I2C
> >>>>>>> controller driver to the NOIRQ phase as well.
> >>>>>>>
> >>>>>>> Signed-off-by: Qii Wang 
> >>>>>>
> >>>>>> Is this a bugfix and should go into 5.10? Or can it wait for 5.11?
> >>>>>>
> >>>>>
> >>>>> Yes, Can you help to apply it into 5.10? Thanks
> >>>>
> >>>> To be honest if you still do have any i2c device which accessing i2c 
> >>>> buss after _noirq
> >>>> stage and your driver does not implement .master_xfer_atomic() - you 
> >>>> definitely have a bigger problem.
> >>>> So adding IRQF_NO_SUSPEND sound like a hack and probably works just by 
> >>>> luck.
> >>>>
> >>>
> >>> At present, it is only a problem caused by missing interrupts,
> >>> and .master_xfer_atomic() just a implement in polling mode. Why not set
> >>> the interrupt to a state that can always be triggered?
> >>>
> >>>
> >>
> >> Because you must not use any IRQ driven operations after _noirq suspend 
> >> state as it might (and most probably will)
> >> cause unpredictable behavior later  in suspend_enter():
> >>
> >>arch_suspend_disable_irqs();
> >>BUG_ON(!irqs_disabled());
> >> ^after this point any IRQ driven I2C transfer will cause IRQ to be 
> >> re-enabled
> >>
> >> if you need  turn off device from platform callbacks -  
> >> .master_xfer_atomic() has to be implemented and used.
> >>
> > Maybe my comment is a bit disturbing.Our purpose is not to call i2c and
> > use interrupts after _noirq pauses.So We use
> > i2c_mark_adapter_suspended&i2c_mark_adapter_resumed to block these i2c
> > transfers, There will not have any IRQ driven I2C transfer after this
> > point:
> >  arch_suspend_disable_irqs();
> >  BUG_ON(!irqs_disabled());
> > But some device driver will do i2c transfer after
> > dpm_noirq_resume_devices in dpm_resume_noirq(PMSG_RESUME) when our
> > driver irq hasn't resume.
> > void dpm_resume_noirq(pm_message_t state)
> > {
> > dpm_noirq_resume_devices(state);
> 
> Just to clarify. You have resume sequence in dpm_noirq_resume_devices
>   dpm_noirq_resume_devices -> resume I2C -> resume some device -> do i2c 
> transfer after?
> 

Yes.

> Is "some device" in Kernel mainline?
> 

The problematic device driver is drivers/regulator/da9211-regulator.c in
Kernel mainline.

> > resume_device_irqs();
> > device_wakeup_disarm_wake_irqs();
> > cpuidle_resume();
> > }
> > .master_xfer_atomic() seems to be invalid for this question at this
> > time?
> > 
> 



Re: [v2] i2c: mediatek: Move suspend and resume handling to NOIRQ phase

2020-12-09 Thread Qii Wang
On Mon, 2020-12-07 at 18:35 +0200, Grygorii Strashko wrote:
> 
> > 
> > On Thu, 2020-12-03 at 10:01 +0200, Grygorii Strashko wrote:
> >>
> >> On 03/12/2020 03:25, Qii Wang wrote:
> >>> On Wed, 2020-12-02 at 16:35 +0100, Wolfram Sang wrote:
> >>>> Hi,
> >>>>
> >>>>> Some i2c device driver indirectly uses I2C driver when it is now
> >>>>> being suspended. The i2c devices driver is suspended during the
> >>>>> NOIRQ phase and this cannot be changed due to other dependencies.
> >>>>> Therefore, we also need to move the suspend handling for the I2C
> >>>>> controller driver to the NOIRQ phase as well.
> >>>>>
> >>>>> Signed-off-by: Qii Wang 
> >>>>
> >>>> Is this a bugfix and should go into 5.10? Or can it wait for 5.11?
> >>>>
> >>>
> >>> Yes, Can you help to apply it into 5.10? Thanks
> >>
> >> To be honest if you still do have any i2c device which accessing i2c buss 
> >> after _noirq
> >> stage and your driver does not implement .master_xfer_atomic() - you 
> >> definitely have a bigger problem.
> >> So adding IRQF_NO_SUSPEND sound like a hack and probably works just by 
> >> luck.
> >>
> > 
> > At present, it is only a problem caused by missing interrupts,
> > and .master_xfer_atomic() just a implement in polling mode. Why not set
> > the interrupt to a state that can always be triggered?
> > 
> > 
> 
> Because you must not use any IRQ driven operations after _noirq suspend state 
> as it might (and most probably will)
> cause unpredictable behavior later  in suspend_enter():
> 
>   arch_suspend_disable_irqs();
>   BUG_ON(!irqs_disabled());
> ^after this point any IRQ driven I2C transfer will cause IRQ to be re-enabled
> 
> if you need  turn off device from platform callbacks -  .master_xfer_atomic() 
> has to be implemented and used.
>   
Maybe my comment is a bit disturbing.Our purpose is not to call i2c and
use interrupts after _noirq pauses.So We use
i2c_mark_adapter_suspended&i2c_mark_adapter_resumed to block these i2c
transfers, There will not have any IRQ driven I2C transfer after this
point:
arch_suspend_disable_irqs();
BUG_ON(!irqs_disabled());
But some device driver will do i2c transfer after
dpm_noirq_resume_devices in dpm_resume_noirq(PMSG_RESUME) when our
driver irq hasn't resume.
void dpm_resume_noirq(pm_message_t state)
{
dpm_noirq_resume_devices(state);
resume_device_irqs();
device_wakeup_disarm_wake_irqs();
cpuidle_resume();
}
.master_xfer_atomic() seems to be invalid for this question at this
time?



Re: [v2] i2c: mediatek: Move suspend and resume handling to NOIRQ phase

2020-12-06 Thread Qii Wang
Hi:
Thank you very much for your patience review.
There are two main purposes of this patch:
1.i2c_mark_adapter_suspended&i2c_mark_adapter_resumed
Avoid accessing the adapter while it is suspended by marking it
suspended during suspend.  This allows the I2C core to catch this, and
print a warning.
https://patchwork.kernel.org/project/linux-arm-kernel/patch/20181219164827.20985-2-wsa+rene...@sang-engineering.com/

2. IRQF_NO_SUSPEND.
Having interrupts disabled means not only that an interrupt will not
occur at an awkward time, but also that using any functionality that
requires interrupts will not work. So if the driver uses an I2C bus or
similar to tell the device to turn off, and if the I2C bus uses
interrupts to indicate completion (which is normal), then either the
device must be powered-off in suspend_late, so the I2C interrupt must be
marked IRQF_NO_SUSPEND.
https://patchwork.kernel.org/project/linux-acpi/patch/20180923135812.29574-8-hdego...@redhat.com/

On Thu, 2020-12-03 at 10:01 +0200, Grygorii Strashko wrote:
> 
> On 03/12/2020 03:25, Qii Wang wrote:
> > On Wed, 2020-12-02 at 16:35 +0100, Wolfram Sang wrote:
> >> Hi,
> >>
> >>> Some i2c device driver indirectly uses I2C driver when it is now
> >>> being suspended. The i2c devices driver is suspended during the
> >>> NOIRQ phase and this cannot be changed due to other dependencies.
> >>> Therefore, we also need to move the suspend handling for the I2C
> >>> controller driver to the NOIRQ phase as well.
> >>>
> >>> Signed-off-by: Qii Wang 
> >>
> >> Is this a bugfix and should go into 5.10? Or can it wait for 5.11?
> >>
> > 
> > Yes, Can you help to apply it into 5.10? Thanks
> 
> To be honest if you still do have any i2c device which accessing i2c buss 
> after _noirq
> stage and your driver does not implement .master_xfer_atomic() - you 
> definitely have a bigger problem.
> So adding IRQF_NO_SUSPEND sound like a hack and probably works just by luck.
> 

At present, it is only a problem caused by missing interrupts,
and .master_xfer_atomic() just a implement in polling mode. Why not set
the interrupt to a state that can always be triggered?




Re: [v2] i2c: mediatek: Move suspend and resume handling to NOIRQ phase

2020-12-02 Thread Qii Wang
On Wed, 2020-12-02 at 16:35 +0100, Wolfram Sang wrote:
> Hi,
> 
> > Some i2c device driver indirectly uses I2C driver when it is now
> > being suspended. The i2c devices driver is suspended during the
> > NOIRQ phase and this cannot be changed due to other dependencies.
> > Therefore, we also need to move the suspend handling for the I2C
> > controller driver to the NOIRQ phase as well.
> > 
> > Signed-off-by: Qii Wang 
> 
> Is this a bugfix and should go into 5.10? Or can it wait for 5.11?
> 

Yes, Can you help to apply it into 5.10? Thanks

> Thanks,
> 
>Wolfram
> 



Re: [i2c-next,PATCH] i2c: medaitek: Move suspend and resume handling to NOIRQ phase

2020-11-09 Thread Qii Wang
I am sorry, there is a misspelling in my subject.
-medaitek
+mediatek
I will revise it with other new comments and then update this patch.

On Sat, 2020-11-07 at 17:09 +0800, qii.w...@mediatek.com wrote:
> From: Qii Wang 
> 
> Some i2c device driver indirectly uses I2C driver when it is now
> being suspended. The i2c devices driver is suspended during the
> NOIRQ phase and this cannot be changed due to other dependencies.
> Therefore, we also need to move the suspend handling for the I2C
> controller driver to the NOIRQ phase as well.
> 
> Signed-off-by: Qii Wang 
> ---
>  drivers/i2c/busses/i2c-mt65xx.c | 19 ---
>  1 file changed, 16 insertions(+), 3 deletions(-)




Re: [PATCH] i2c: mediatek: remove redundant null check

2020-10-25 Thread Qii Wang
Thanks, it looks good for me, it would be better to remove all useless
members

On Wed, 2020-09-30 at 08:42 +, Xu Wang wrote:
> Because clk_disable_unprepare already checked NULL clock parameter,
> so the additional checks are unnecessary, just remove it
> 
> Signed-off-by: Xu Wang 
> ---
>  drivers/i2c/busses/i2c-mt65xx.c | 9 +++--
>  1 file changed, 3 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
> index 0cbdfbe605b5..48d37de827e1 100644
> --- a/drivers/i2c/busses/i2c-mt65xx.c
> +++ b/drivers/i2c/busses/i2c-mt65xx.c
> @@ -449,8 +449,7 @@ static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
>   return 0;
>  
>  err_arb:
> - if (i2c->have_pmic)
> - clk_disable_unprepare(i2c->clk_pmic);
> + clk_disable_unprepare(i2c->clk_pmic);
>  err_pmic:
>   clk_disable_unprepare(i2c->clk_main);
>  err_main:
> @@ -461,11 +460,9 @@ static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
>  
>  static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
>  {
> - if (i2c->clk_arb)
> - clk_disable_unprepare(i2c->clk_arb);
> + clk_disable_unprepare(i2c->clk_arb);
>  
> - if (i2c->have_pmic)
> - clk_disable_unprepare(i2c->clk_pmic);
> + clk_disable_unprepare(i2c->clk_pmic);
>  
>   clk_disable_unprepare(i2c->clk_main);
>   clk_disable_unprepare(i2c->clk_dma);



[PATCH 2/2] i2c: mediatek: Send i2c master code at more than 1MHz

2020-09-17 Thread Qii Wang
The master code needs to being sent when the speed is more than
I2C_MAX_FAST_MODE_PLUS_FREQ, not I2C_MAX_FAST_MODE_FREQ in the
latest I2C-bus specification and user manual.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index a1978eb..0cbdfbe 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -759,7 +759,7 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned 
int parent_clk)
for (clk_div = 1; clk_div <= max_clk_div; clk_div++) {
clk_src = parent_clk / clk_div;
 
-   if (target_speed > I2C_MAX_FAST_MODE_FREQ) {
+   if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) {
/* Set master code speed register */
ret = mtk_i2c_calculate_speed(i2c, clk_src,
  I2C_MAX_FAST_MODE_FREQ,
-- 
1.9.1


[PATCH 0/2] Fix some definitions for bus frequency

2020-09-17 Thread Qii Wang
This series are based on 5.9-rc1 and we provide two i2c patches
to fix some definitions for bus frequency.

Qii Wang (2):
  i2c: mediatek: Fix generic definitions for bus frequency
  i2c: mediatek: Send i2c master code at more than 1MHz

 drivers/i2c/busses/i2c-mt65xx.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

-- 
1.9.1



[PATCH 1/2] i2c: mediatek: Fix generic definitions for bus frequency

2020-09-17 Thread Qii Wang
The max frequency of mediatek i2c controller driver is
I2C_MAX_HIGH_SPEED_MODE_FREQ, not I2C_MAX_FAST_MODE_PLUS_FREQ.
Fix it.

Fixes: 90224e6468e1 ("i2c: drivers: Use generic definitions
for bus frequencies")
Reviewed-by: Yingjoe Chen 
Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index efc1404..a1978eb 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -681,8 +681,8 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, 
unsigned int clk_src,
unsigned int cnt_mul;
int ret = -EINVAL;
 
-   if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ)
-   target_speed = I2C_MAX_FAST_MODE_PLUS_FREQ;
+   if (target_speed > I2C_MAX_HIGH_SPEED_MODE_FREQ)
+   target_speed = I2C_MAX_HIGH_SPEED_MODE_FREQ;
 
max_step_cnt = mtk_i2c_max_step_cnt(target_speed);
base_step_cnt = max_step_cnt;
-- 
1.9.1


Re: [PATCH] i2c: mediatek: Fix generic definitions for bus frequencies

2020-09-14 Thread Qii Wang
On Mon, 2020-09-14 at 15:48 +0300, Andy Shevchenko wrote:
> On Sat, Sep 12, 2020 at 9:02 AM  wrote:
> >
> > From: Qii Wang 
> >
> > The master code needs to being sent when the speed is more than
> > I2C_MAX_FAST_MODE_PLUS_FREQ instead of
> > I2C_MAX_HIGH_SPEED_MODE_FREQ. Fix it.
> >
> > Signed-off-by: Qii Wang 
> > ---
> >  drivers/i2c/busses/i2c-mt65xx.c | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/i2c/busses/i2c-mt65xx.c 
> > b/drivers/i2c/busses/i2c-mt65xx.c
> > index efc1404..0cbdfbe 100644
> > --- a/drivers/i2c/busses/i2c-mt65xx.c
> > +++ b/drivers/i2c/busses/i2c-mt65xx.c
> > @@ -681,8 +681,8 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, 
> > unsigned int clk_src,
> > unsigned int cnt_mul;
> > int ret = -EINVAL;
> >
> > -   if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ)
> > -   target_speed = I2C_MAX_FAST_MODE_PLUS_FREQ;
> > +   if (target_speed > I2C_MAX_HIGH_SPEED_MODE_FREQ)
> > +   target_speed = I2C_MAX_HIGH_SPEED_MODE_FREQ;
> 
> Thanks for fixing this. Indeed, somehow I messed these up.
> 
> >
> > max_step_cnt = mtk_i2c_max_step_cnt(target_speed);
> > base_step_cnt = max_step_cnt;
> > @@ -759,7 +759,7 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, 
> > unsigned int parent_clk)
> > for (clk_div = 1; clk_div <= max_clk_div; clk_div++) {
> > clk_src = parent_clk / clk_div;
> >
> > -   if (target_speed > I2C_MAX_FAST_MODE_FREQ) {
> > +   if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) {
> 
> But this one is not related. Original code used to have
> 
> #define MAX_FS_MODE_SPEED  40
> 
>if (target_speed > MAX_FS_MODE_SPEED) {
> 
> And this change doesn't fix the above mentioned problem.
> 
> So, please split into two separate changes.
> 

ok, Thank you for your comments

> > /* Set master code speed register */
> > ret = mtk_i2c_calculate_speed(i2c, clk_src,
> >   
> > I2C_MAX_FAST_MODE_FREQ,
> > --
> > 1.9.1
> 
> 
> 



Re: [v2] i2c: mediatek: Fix i2c_spec_values description

2020-08-07 Thread Qii Wang
On Fri, 2020-08-07 at 15:19 +0200, matthias@kernel.org wrote:
> From: Matthias Brugger 
> 
> The struct i2c_spec_values have it's members documented but is
> missing the starting '@', which leads to warings like:
> 
> drivers/i2c/busses/i2c-mt65xx.c:267: warning: Function parameter or member 
> 'min_low_ns' not described in 'i2c_spec_values'
> 
> We also delete min_high_ns member as it is not used in the code.
> 
> Signed-off-by: Matthias Brugger 

Reviewed-by: Qii Wang 

> ---
> 
> Changes since v1:
> delete mint_high_ns member
> 
>  drivers/i2c/busses/i2c-mt65xx.c | 9 -
>  1 file changed, 4 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
> index e889f74703e4..efc14041d45b 100644
> --- a/drivers/i2c/busses/i2c-mt65xx.c
> +++ b/drivers/i2c/busses/i2c-mt65xx.c
> @@ -253,14 +253,13 @@ struct mtk_i2c {
>  
>  /**
>   * struct i2c_spec_values:
> - * min_low_ns: min LOW period of the SCL clock
> - * min_su_sta_ns: min set-up time for a repeated START condition
> - * max_hd_dat_ns: max data hold time
> - * min_su_dat_ns: min data set-up time
> + * @min_low_ns: min LOW period of the SCL clock
> + * @min_su_sta_ns: min set-up time for a repeated START condition
> + * @max_hd_dat_ns: max data hold time
> + * @min_su_dat_ns: min data set-up time
>   */
>  struct i2c_spec_values {
>   unsigned int min_low_ns;
> - unsigned int min_high_ns;
>   unsigned int min_su_sta_ns;
>   unsigned int max_hd_dat_ns;
>   unsigned int min_su_dat_ns;



Re: [PATCH] i2c: mediatek: Fix i2c_spec_values description

2020-08-06 Thread Qii Wang
On Thu, 2020-08-06 at 15:35 +0200, Matthias Brugger wrote:
> 
> On 06/08/2020 13:06, Qii Wang wrote:
> > On Thu, 2020-08-06 at 11:48 +0200, Matthias Brugger wrote:
> >> The struct i2c_spec_values have it's members documented but is missing the
> >> starting '@', which leads to warings like:
> >>
> >> drivers/i2c/busses/i2c-mt65xx.c:267: warning: Function parameter or member
> >> 'min_low_ns' not described in 'i2c_spec_values'
> >>
> >> Signed-off-by: Matthias Brugger 
> >> ---
> >>drivers/i2c/busses/i2c-mt65xx.c | 8 
> >>1 file changed, 4 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/drivers/i2c/busses/i2c-mt65xx.c 
> >> b/drivers/i2c/busses/i2c-mt65xx.c
> >> index e889f74703e4..f51b35fc400f 100644
> >> --- a/drivers/i2c/busses/i2c-mt65xx.c
> >> +++ b/drivers/i2c/busses/i2c-mt65xx.c
> >> @@ -253,10 +253,10 @@ struct mtk_i2c {
> >>
> >>/**
> >> * struct i2c_spec_values:
> >> - * min_low_ns: min LOW period of the SCL clock
> > 
> > Can you help me add a description of min_high_ns. As
> > @min_high_ns: min HIGH period of the SCL clock
> 
> Right, I forgot about this one.
> 
> Actually I don't see any code which uses the value, so I think it should be 
> deleted from the struct.
> 
> Do you have any thoughts on this.
> 

That is right, it is used for internal test before. You can deleted it.



Re: [PATCH] i2c: mediatek: Fix i2c_spec_values description

2020-08-06 Thread Qii Wang
On Thu, 2020-08-06 at 11:48 +0200, Matthias Brugger wrote:
> The struct i2c_spec_values have it's members documented but is missing the 
> starting '@', which leads to warings like:
> 
> drivers/i2c/busses/i2c-mt65xx.c:267: warning: Function parameter or member 
> 'min_low_ns' not described in 'i2c_spec_values'
> 
> Signed-off-by: Matthias Brugger 
> ---
>   drivers/i2c/busses/i2c-mt65xx.c | 8 
>   1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
> index e889f74703e4..f51b35fc400f 100644
> --- a/drivers/i2c/busses/i2c-mt65xx.c
> +++ b/drivers/i2c/busses/i2c-mt65xx.c
> @@ -253,10 +253,10 @@ struct mtk_i2c {
> 
>   /**
>* struct i2c_spec_values:
> - * min_low_ns: min LOW period of the SCL clock

Can you help me add a description of min_high_ns. As
@min_high_ns: min HIGH period of the SCL clock
Thanks
 
> - * min_su_sta_ns: min set-up time for a repeated START condition
> - * max_hd_dat_ns: max data hold time
> - * min_su_dat_ns: min data set-up time
> + * @min_low_ns: min LOW period of the SCL clock
> + * @min_su_sta_ns: min set-up time for a repeated START condition
> + * @max_hd_dat_ns: max data hold time
> + * @min_su_dat_ns: min data set-up time
>*/
>   struct i2c_spec_values {
>   unsigned int min_low_ns;



[PATCH v3 4/4] i2c: mediatek: Add i2c compatible for MediaTek MT8192

2020-08-05 Thread Qii Wang
Add i2c compatible for MT8192. Compare to MT8183 i2c controller,
MT8192 support more then 8GB DMA mode.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 463860e..e889f74 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -386,6 +386,20 @@ struct i2c_spec_values {
.max_dma_support = 33,
 };
 
+static const struct mtk_i2c_compatible mt8192_compat = {
+   .quirks = &mt8183_i2c_quirks,
+   .regs = mt_i2c_regs_v2,
+   .pmic_i2c = 0,
+   .dcm = 0,
+   .auto_restart = 1,
+   .aux_len_reg = 1,
+   .timing_adjust = 1,
+   .dma_sync = 1,
+   .ltiming_adjust = 1,
+   .apdma_sync = 1,
+   .max_dma_support = 36,
+};
+
 static const struct of_device_id mtk_i2c_of_match[] = {
{ .compatible = "mediatek,mt2712-i2c", .data = &mt2712_compat },
{ .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
@@ -393,6 +407,7 @@ struct i2c_spec_values {
{ .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
{ .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
{ .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
+   { .compatible = "mediatek,mt8192-i2c", .data = &mt8192_compat },
{}
 };
 MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
-- 
1.9.1


[PATCH v3 0/4] add i2c support for mt8192

2020-08-05 Thread Qii Wang
This series are based on 5.8-rc1 and we provide four i2c patches
to support mt8192 SoC.

Main changes compared to v2:
--delete unused I2C_DMA_4G_MODE

Main changes compared to v1:
--modify the commit with access more than 8GB dram
--add Reviewed-by and Acked-by from Yingjoe, Matthias and Rob

Qii Wang (4):
  i2c: mediatek: Add apdma sync in i2c driver
  i2c: mediatek: Add access to more than 8GB dram in i2c driver
  dt-bindings: i2c: update bindings for MT8192 SoC
  i2c: mediatek: Add i2c compatible for MediaTek MT8192

 .../devicetree/bindings/i2c/i2c-mt65xx.txt |  1 +
 drivers/i2c/busses/i2c-mt65xx.c| 77 +++---
 2 files changed, 53 insertions(+), 25 deletions(-)

-- 
1.9.1


[PATCH v3 1/4] i2c: mediatek: Add apdma sync in i2c driver

2020-08-05 Thread Qii Wang
With the apdma remove hand-shake signal, it need to keep i2c and
apdma in sync manually.

Reviewed-by: Yingjoe Chen 
Reviewed-by: Matthias Brugger 
Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 23 ---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index deef69e..e6b984a 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -48,6 +48,9 @@
 
 #define I2C_DMA_CON_TX 0x
 #define I2C_DMA_CON_RX 0x0001
+#define I2C_DMA_ASYNC_MODE 0x0004
+#define I2C_DMA_SKIP_CONFIG0x0010
+#define I2C_DMA_DIR_CHANGE 0x0200
 #define I2C_DMA_START_EN   0x0001
 #define I2C_DMA_INT_FLAG_NONE  0x
 #define I2C_DMA_CLR_FLAG   0x
@@ -205,6 +208,7 @@ struct mtk_i2c_compatible {
unsigned char timing_adjust: 1;
unsigned char dma_sync: 1;
unsigned char ltiming_adjust: 1;
+   unsigned char apdma_sync: 1;
 };
 
 struct mtk_i2c_ac_timing {
@@ -311,6 +315,7 @@ struct i2c_spec_values {
.timing_adjust = 1,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt6577_compat = {
@@ -324,6 +329,7 @@ struct i2c_spec_values {
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
@@ -337,6 +343,7 @@ struct i2c_spec_values {
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt7622_compat = {
@@ -350,6 +357,7 @@ struct i2c_spec_values {
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
@@ -362,6 +370,7 @@ struct i2c_spec_values {
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt8183_compat = {
@@ -375,6 +384,7 @@ struct i2c_spec_values {
.timing_adjust = 1,
.dma_sync = 1,
.ltiming_adjust = 1,
+   .apdma_sync = 0,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
@@ -798,6 +808,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
u16 start_reg;
u16 control_reg;
u16 restart_flag = 0;
+   u16 dma_sync = 0;
u32 reg_4g_mode;
u8 *dma_rd_buf = NULL;
u8 *dma_wr_buf = NULL;
@@ -851,10 +862,16 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
struct i2c_msg *msgs,
mtk_i2c_writew(i2c, num, OFFSET_TRANSAC_LEN);
}
 
+   if (i2c->dev_comp->apdma_sync) {
+   dma_sync = I2C_DMA_SKIP_CONFIG | I2C_DMA_ASYNC_MODE;
+   if (i2c->op == I2C_MASTER_WRRD)
+   dma_sync |= I2C_DMA_DIR_CHANGE;
+   }
+
/* Prepare buffer data to start transfer */
if (i2c->op == I2C_MASTER_RD) {
writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
-   writel(I2C_DMA_CON_RX, i2c->pdmabase + OFFSET_CON);
+   writel(I2C_DMA_CON_RX | dma_sync, i2c->pdmabase + OFFSET_CON);
 
dma_rd_buf = i2c_get_dma_safe_msg_buf(msgs, 1);
if (!dma_rd_buf)
@@ -877,7 +894,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
writel(msgs->len, i2c->pdmabase + OFFSET_RX_LEN);
} else if (i2c->op == I2C_MASTER_WR) {
writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
-   writel(I2C_DMA_CON_TX, i2c->pdmabase + OFFSET_CON);
+   writel(I2C_DMA_CON_TX | dma_sync, i2c->pdmabase + OFFSET_CON);
 
dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 1);
if (!dma_wr_buf)
@@ -900,7 +917,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN);
} else {
writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_INT_FLAG);
-   writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_CON);
+   writel(I2C_DMA_CLR_FLAG | dma_sync, i2c->pdmabase + OFFSET_CON);
 
dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 1);
if (!dma_wr_buf)
-- 
1.9.1


[PATCH v3 2/4] i2c: mediatek: Add access to more than 8GB dram in i2c driver

2020-08-05 Thread Qii Wang
Newer MTK chip support more than 8GB of dram. Replace support_33bits
with more general dma_max_support and remove mtk_i2c_set_4g_mode.

Reviewed-by: Yingjoe Chen 
Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 39 +--
 1 file changed, 17 insertions(+), 22 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index e6b984a..463860e 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -55,7 +55,6 @@
 #define I2C_DMA_INT_FLAG_NONE  0x
 #define I2C_DMA_CLR_FLAG   0x
 #define I2C_DMA_HARD_RST   0x0002
-#define I2C_DMA_4G_MODE0x0001
 
 #define MAX_SAMPLE_CNT_DIV 8
 #define MAX_STEP_CNT_DIV   64
@@ -204,11 +203,11 @@ struct mtk_i2c_compatible {
unsigned char dcm: 1;
unsigned char auto_restart: 1;
unsigned char aux_len_reg: 1;
-   unsigned char support_33bits: 1;
unsigned char timing_adjust: 1;
unsigned char dma_sync: 1;
unsigned char ltiming_adjust: 1;
unsigned char apdma_sync: 1;
+   unsigned char max_dma_support;
 };
 
 struct mtk_i2c_ac_timing {
@@ -311,11 +310,11 @@ struct i2c_spec_values {
.dcm = 1,
.auto_restart = 1,
.aux_len_reg = 1,
-   .support_33bits = 1,
.timing_adjust = 1,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 33,
 };
 
 static const struct mtk_i2c_compatible mt6577_compat = {
@@ -325,11 +324,11 @@ struct i2c_spec_values {
.dcm = 1,
.auto_restart = 0,
.aux_len_reg = 0,
-   .support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 32,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
@@ -339,11 +338,11 @@ struct i2c_spec_values {
.dcm = 0,
.auto_restart = 0,
.aux_len_reg = 0,
-   .support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 32,
 };
 
 static const struct mtk_i2c_compatible mt7622_compat = {
@@ -353,11 +352,11 @@ struct i2c_spec_values {
.dcm = 1,
.auto_restart = 1,
.aux_len_reg = 1,
-   .support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 32,
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
@@ -366,11 +365,11 @@ struct i2c_spec_values {
.dcm = 1,
.auto_restart = 1,
.aux_len_reg = 1,
-   .support_33bits = 1,
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 33,
 };
 
 static const struct mtk_i2c_compatible mt8183_compat = {
@@ -380,11 +379,11 @@ struct i2c_spec_values {
.dcm = 0,
.auto_restart = 1,
.aux_len_reg = 1,
-   .support_33bits = 1,
.timing_adjust = 1,
.dma_sync = 1,
.ltiming_adjust = 1,
.apdma_sync = 0,
+   .max_dma_support = 33,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
@@ -796,11 +795,6 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned 
int parent_clk)
return 0;
 }
 
-static inline u32 mtk_i2c_set_4g_mode(dma_addr_t addr)
-{
-   return (addr & BIT_ULL(32)) ? I2C_DMA_4G_MODE : I2C_DMA_CLR_FLAG;
-}
-
 static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
   int num, int left_num)
 {
@@ -885,8 +879,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
return -ENOMEM;
}
 
-   if (i2c->dev_comp->support_33bits) {
-   reg_4g_mode = mtk_i2c_set_4g_mode(rpaddr);
+   if (i2c->dev_comp->max_dma_support > 32) {
+   reg_4g_mode = upper_32_bits(rpaddr);
writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE);
}
 
@@ -908,8 +902,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
return -ENOMEM;
}
 
-   if (i2c->dev_comp->support_33bits) {
-   reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr);
+   if (i2c->dev_comp->max_dma_support > 32) {
+   reg_4g_mode = upper_32_bits(wpaddr);
writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);
}
 
@@ -954,11 +948,11 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
struct i2c_msg *msgs,
return -ENOMEM;
}
 
-   if (i2c->dev_comp->support_33bits) {
-   reg_4g_mode = mtk_i2

[PATCH v3 3/4] dt-bindings: i2c: update bindings for MT8192 SoC

2020-08-05 Thread Qii Wang
Add a DT binding documentation for the MT8192 soc.

Acked-by: Rob Herring 
Signed-off-by: Qii Wang 
---
 Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt 
b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
index 88b71c1..7f0194f 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
@@ -14,6 +14,7 @@ Required properties:
   "mediatek,mt7629-i2c", "mediatek,mt2712-i2c": for MediaTek MT7629
   "mediatek,mt8173-i2c": for MediaTek MT8173
   "mediatek,mt8183-i2c": for MediaTek MT8183
+  "mediatek,mt8192-i2c": for MediaTek MT8192
   "mediatek,mt8516-i2c", "mediatek,mt2712-i2c": for MediaTek MT8516
   - reg: physical base address of the controller and dma base, length of memory
 mapped region.
-- 
1.9.1


Re: [PATCH v2 2/4] i2c: mediatek: Add access to more than 8GB dram in i2c driver

2020-07-29 Thread Qii Wang
On Wed, 2020-07-29 at 09:59 +0200, Matthias Brugger wrote:
> 
> On 28/07/2020 14:30, Qii Wang wrote:
> > Newer MTK chip support more than 8GB of dram. Replace support_33bits
> > with more general dma_max_support and remove mtk_i2c_set_4g_mode.
> > 
> > Signed-off-by: Qii Wang 
> > ---
> >   drivers/i2c/busses/i2c-mt65xx.c | 38 
> > +-
> >   1 file changed, 17 insertions(+), 21 deletions(-)
> > 
> > diff --git a/drivers/i2c/busses/i2c-mt65xx.c 
> > b/drivers/i2c/busses/i2c-mt65xx.c
> > index e6b984a..49777a6 100644
> > --- a/drivers/i2c/busses/i2c-mt65xx.c
> > +++ b/drivers/i2c/busses/i2c-mt65xx.c
> > @@ -204,11 +204,11 @@ struct mtk_i2c_compatible {
> > unsigned char dcm: 1;
> > unsigned char auto_restart: 1;
> > unsigned char aux_len_reg: 1;
> > -   unsigned char support_33bits: 1;
> > unsigned char timing_adjust: 1;
> > unsigned char dma_sync: 1;
> > unsigned char ltiming_adjust: 1;
> > unsigned char apdma_sync: 1;
> > +   unsigned char max_dma_support;
> >   };
> >   
> >   struct mtk_i2c_ac_timing {
> > @@ -311,11 +311,11 @@ struct i2c_spec_values {
> > .dcm = 1,
> > .auto_restart = 1,
> > .aux_len_reg = 1,
> > -   .support_33bits = 1,
> > .timing_adjust = 1,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > .apdma_sync = 0,
> > +   .max_dma_support = 33,
> >   };
> >   
> >   static const struct mtk_i2c_compatible mt6577_compat = {
> > @@ -325,11 +325,11 @@ struct i2c_spec_values {
> > .dcm = 1,
> > .auto_restart = 0,
> > .aux_len_reg = 0,
> > -   .support_33bits = 0,
> > .timing_adjust = 0,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > .apdma_sync = 0,
> > +   .max_dma_support = 32,
> >   };
> >   
> >   static const struct mtk_i2c_compatible mt6589_compat = {
> > @@ -339,11 +339,11 @@ struct i2c_spec_values {
> > .dcm = 0,
> > .auto_restart = 0,
> > .aux_len_reg = 0,
> > -   .support_33bits = 0,
> > .timing_adjust = 0,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > .apdma_sync = 0,
> > +   .max_dma_support = 32,
> >   };
> >   
> >   static const struct mtk_i2c_compatible mt7622_compat = {
> > @@ -353,11 +353,11 @@ struct i2c_spec_values {
> > .dcm = 1,
> > .auto_restart = 1,
> > .aux_len_reg = 1,
> > -   .support_33bits = 0,
> > .timing_adjust = 0,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > .apdma_sync = 0,
> > +   .max_dma_support = 32,
> >   };
> >   
> >   static const struct mtk_i2c_compatible mt8173_compat = {
> > @@ -366,11 +366,11 @@ struct i2c_spec_values {
> > .dcm = 1,
> > .auto_restart = 1,
> > .aux_len_reg = 1,
> > -   .support_33bits = 1,
> > .timing_adjust = 0,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > .apdma_sync = 0,
> > +   .max_dma_support = 33,
> >   };
> >   
> >   static const struct mtk_i2c_compatible mt8183_compat = {
> > @@ -380,11 +380,11 @@ struct i2c_spec_values {
> > .dcm = 0,
> > .auto_restart = 1,
> > .aux_len_reg = 1,
> > -   .support_33bits = 1,
> > .timing_adjust = 1,
> > .dma_sync = 1,
> > .ltiming_adjust = 1,
> > .apdma_sync = 0,
> > +   .max_dma_support = 33,
> >   };
> >   
> >   static const struct of_device_id mtk_i2c_of_match[] = {
> > @@ -796,11 +796,6 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, 
> > unsigned int parent_clk)
> > return 0;
> >   }
> >   
> > -static inline u32 mtk_i2c_set_4g_mode(dma_addr_t addr)
> > -{
> > -   return (addr & BIT_ULL(32)) ? I2C_DMA_4G_MODE : I2C_DMA_CLR_FLAG;
> 
> I think you missed my comment in the last version:
> I2C_DMA_4G_MODE is no longer needed, you can delete it.
> 
> Regards,
> Matthias
> 

Sorry for missing that comment, I will remove it.
Thank you for your comments and reminders.

> > -}
> > -
> >   static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
> >int num, int left_num)
> >   {
> > @@ -885,8 +880,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
> > struct i2c_msg *msgs,
> > return -ENOMEM;
> > }
> >   
> > -   if (i2c->dev_comp->support_33bits) {
> > -   reg_4g_mode = mt

[PATCH v2 3/4] dt-bindings: i2c: update bindings for MT8192 SoC

2020-07-28 Thread Qii Wang
Add a DT binding documentation for the MT8192 soc.

Acked-by: Rob Herring 
Signed-off-by: Qii Wang 
---
 Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt 
b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
index 88b71c1..7f0194f 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
@@ -14,6 +14,7 @@ Required properties:
   "mediatek,mt7629-i2c", "mediatek,mt2712-i2c": for MediaTek MT7629
   "mediatek,mt8173-i2c": for MediaTek MT8173
   "mediatek,mt8183-i2c": for MediaTek MT8183
+  "mediatek,mt8192-i2c": for MediaTek MT8192
   "mediatek,mt8516-i2c", "mediatek,mt2712-i2c": for MediaTek MT8516
   - reg: physical base address of the controller and dma base, length of memory
 mapped region.
-- 
1.9.1


[PATCH v2 4/4] i2c: mediatek: Add i2c compatible for MediaTek MT8192

2020-07-28 Thread Qii Wang
Add i2c compatible for MT8192. Compare to MT8183 i2c controller,
MT8192 support more then 8GB DMA mode.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 49777a6..dbf31eb 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -387,6 +387,20 @@ struct i2c_spec_values {
.max_dma_support = 33,
 };
 
+static const struct mtk_i2c_compatible mt8192_compat = {
+   .quirks = &mt8183_i2c_quirks,
+   .regs = mt_i2c_regs_v2,
+   .pmic_i2c = 0,
+   .dcm = 0,
+   .auto_restart = 1,
+   .aux_len_reg = 1,
+   .timing_adjust = 1,
+   .dma_sync = 1,
+   .ltiming_adjust = 1,
+   .apdma_sync = 1,
+   .max_dma_support = 36,
+};
+
 static const struct of_device_id mtk_i2c_of_match[] = {
{ .compatible = "mediatek,mt2712-i2c", .data = &mt2712_compat },
{ .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
@@ -394,6 +408,7 @@ struct i2c_spec_values {
{ .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
{ .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
{ .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
+   { .compatible = "mediatek,mt8192-i2c", .data = &mt8192_compat },
{}
 };
 MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
-- 
1.9.1


[PATCH v2 1/4] i2c: mediatek: Add apdma sync in i2c driver

2020-07-28 Thread Qii Wang
With the apdma remove hand-shake signal, it need to keep i2c and
apdma in sync manually.

Reviewed-by: Yingjoe Chen 
Reviewed-by: Matthias Brugger 
Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 23 ---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index deef69e..e6b984a 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -48,6 +48,9 @@
 
 #define I2C_DMA_CON_TX 0x
 #define I2C_DMA_CON_RX 0x0001
+#define I2C_DMA_ASYNC_MODE 0x0004
+#define I2C_DMA_SKIP_CONFIG0x0010
+#define I2C_DMA_DIR_CHANGE 0x0200
 #define I2C_DMA_START_EN   0x0001
 #define I2C_DMA_INT_FLAG_NONE  0x
 #define I2C_DMA_CLR_FLAG   0x
@@ -205,6 +208,7 @@ struct mtk_i2c_compatible {
unsigned char timing_adjust: 1;
unsigned char dma_sync: 1;
unsigned char ltiming_adjust: 1;
+   unsigned char apdma_sync: 1;
 };
 
 struct mtk_i2c_ac_timing {
@@ -311,6 +315,7 @@ struct i2c_spec_values {
.timing_adjust = 1,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt6577_compat = {
@@ -324,6 +329,7 @@ struct i2c_spec_values {
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
@@ -337,6 +343,7 @@ struct i2c_spec_values {
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt7622_compat = {
@@ -350,6 +357,7 @@ struct i2c_spec_values {
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
@@ -362,6 +370,7 @@ struct i2c_spec_values {
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt8183_compat = {
@@ -375,6 +384,7 @@ struct i2c_spec_values {
.timing_adjust = 1,
.dma_sync = 1,
.ltiming_adjust = 1,
+   .apdma_sync = 0,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
@@ -798,6 +808,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
u16 start_reg;
u16 control_reg;
u16 restart_flag = 0;
+   u16 dma_sync = 0;
u32 reg_4g_mode;
u8 *dma_rd_buf = NULL;
u8 *dma_wr_buf = NULL;
@@ -851,10 +862,16 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
struct i2c_msg *msgs,
mtk_i2c_writew(i2c, num, OFFSET_TRANSAC_LEN);
}
 
+   if (i2c->dev_comp->apdma_sync) {
+   dma_sync = I2C_DMA_SKIP_CONFIG | I2C_DMA_ASYNC_MODE;
+   if (i2c->op == I2C_MASTER_WRRD)
+   dma_sync |= I2C_DMA_DIR_CHANGE;
+   }
+
/* Prepare buffer data to start transfer */
if (i2c->op == I2C_MASTER_RD) {
writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
-   writel(I2C_DMA_CON_RX, i2c->pdmabase + OFFSET_CON);
+   writel(I2C_DMA_CON_RX | dma_sync, i2c->pdmabase + OFFSET_CON);
 
dma_rd_buf = i2c_get_dma_safe_msg_buf(msgs, 1);
if (!dma_rd_buf)
@@ -877,7 +894,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
writel(msgs->len, i2c->pdmabase + OFFSET_RX_LEN);
} else if (i2c->op == I2C_MASTER_WR) {
writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
-   writel(I2C_DMA_CON_TX, i2c->pdmabase + OFFSET_CON);
+   writel(I2C_DMA_CON_TX | dma_sync, i2c->pdmabase + OFFSET_CON);
 
dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 1);
if (!dma_wr_buf)
@@ -900,7 +917,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN);
} else {
writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_INT_FLAG);
-   writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_CON);
+   writel(I2C_DMA_CLR_FLAG | dma_sync, i2c->pdmabase + OFFSET_CON);
 
dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 1);
if (!dma_wr_buf)
-- 
1.9.1


[PATCH v2 0/4] add i2c support for mt8192

2020-07-28 Thread Qii Wang
This series are based on 5.8-rc1 and we provide four i2c patches
to support mt8192 SoC.

Main changes compared to v1:
--modify the commit with access more than 8GB dram
--add Reviewed-by and Acked-by from Yingjoe, Matthias and Rob

Qii Wang (4):
  i2c: mediatek: Add apdma sync in i2c driver
  i2c: mediatek: Add access to more than 8GB dram in i2c driver
  dt-bindings: i2c: update bindings for MT8192 SoC
  i2c: mediatek: Add i2c compatible for MediaTek MT8192

 .../devicetree/bindings/i2c/i2c-mt65xx.txt |  1 +
 drivers/i2c/busses/i2c-mt65xx.c| 76 +++---
 2 files changed, 53 insertions(+), 24 deletions(-)

-- 
1.9.1

[PATCH v2 2/4] i2c: mediatek: Add access to more than 8GB dram in i2c driver

2020-07-28 Thread Qii Wang
Newer MTK chip support more than 8GB of dram. Replace support_33bits
with more general dma_max_support and remove mtk_i2c_set_4g_mode.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 38 +-
 1 file changed, 17 insertions(+), 21 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index e6b984a..49777a6 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -204,11 +204,11 @@ struct mtk_i2c_compatible {
unsigned char dcm: 1;
unsigned char auto_restart: 1;
unsigned char aux_len_reg: 1;
-   unsigned char support_33bits: 1;
unsigned char timing_adjust: 1;
unsigned char dma_sync: 1;
unsigned char ltiming_adjust: 1;
unsigned char apdma_sync: 1;
+   unsigned char max_dma_support;
 };
 
 struct mtk_i2c_ac_timing {
@@ -311,11 +311,11 @@ struct i2c_spec_values {
.dcm = 1,
.auto_restart = 1,
.aux_len_reg = 1,
-   .support_33bits = 1,
.timing_adjust = 1,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 33,
 };
 
 static const struct mtk_i2c_compatible mt6577_compat = {
@@ -325,11 +325,11 @@ struct i2c_spec_values {
.dcm = 1,
.auto_restart = 0,
.aux_len_reg = 0,
-   .support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 32,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
@@ -339,11 +339,11 @@ struct i2c_spec_values {
.dcm = 0,
.auto_restart = 0,
.aux_len_reg = 0,
-   .support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 32,
 };
 
 static const struct mtk_i2c_compatible mt7622_compat = {
@@ -353,11 +353,11 @@ struct i2c_spec_values {
.dcm = 1,
.auto_restart = 1,
.aux_len_reg = 1,
-   .support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 32,
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
@@ -366,11 +366,11 @@ struct i2c_spec_values {
.dcm = 1,
.auto_restart = 1,
.aux_len_reg = 1,
-   .support_33bits = 1,
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 33,
 };
 
 static const struct mtk_i2c_compatible mt8183_compat = {
@@ -380,11 +380,11 @@ struct i2c_spec_values {
.dcm = 0,
.auto_restart = 1,
.aux_len_reg = 1,
-   .support_33bits = 1,
.timing_adjust = 1,
.dma_sync = 1,
.ltiming_adjust = 1,
.apdma_sync = 0,
+   .max_dma_support = 33,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
@@ -796,11 +796,6 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned 
int parent_clk)
return 0;
 }
 
-static inline u32 mtk_i2c_set_4g_mode(dma_addr_t addr)
-{
-   return (addr & BIT_ULL(32)) ? I2C_DMA_4G_MODE : I2C_DMA_CLR_FLAG;
-}
-
 static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
   int num, int left_num)
 {
@@ -885,8 +880,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
return -ENOMEM;
}
 
-   if (i2c->dev_comp->support_33bits) {
-   reg_4g_mode = mtk_i2c_set_4g_mode(rpaddr);
+   if (i2c->dev_comp->max_dma_support > 32) {
+   reg_4g_mode = upper_32_bits(rpaddr);
writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE);
}
 
@@ -908,8 +903,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
return -ENOMEM;
}
 
-   if (i2c->dev_comp->support_33bits) {
-   reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr);
+   if (i2c->dev_comp->max_dma_support > 32) {
+   reg_4g_mode = upper_32_bits(wpaddr);
writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);
}
 
@@ -954,11 +949,11 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
struct i2c_msg *msgs,
return -ENOMEM;
}
 
-   if (i2c->dev_comp->support_33bits) {
-   reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr);
+   if (i2c->dev_comp->max_dma_support > 32) {
+   reg_4g_mode = upper_32_bits(wpaddr);
writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);
 
-   reg_4g_mode = mtk_i2c_set_4g_mode(rpaddr);

Re: [PATCH 2/4] i2c: mediatek: Support DMA mask range over 33-bits

2020-07-22 Thread Qii Wang
On Thu, 2020-07-23 at 09:24 +0800, Yingjoe Chen wrote:
> On Wed, 2020-07-22 at 20:31 +0800, Qii Wang wrote:
> > Replace 'support_33bits with 'dma_max_support' for DMA mask
> > operation, and replace 'mtk_i2c_set_4g_mode' with 'upper_32_bits'.
> 
> This doesn't explain why we need this patch. How about:
> 
> Newer MTK chip support more than 8GB of dram. Replace support_33bits
> with more general dma_max_support.
> 

ok, Thanks for your comments.

> 
> > 
> > Signed-off-by: Qii Wang 
> > ---
> >  drivers/i2c/busses/i2c-mt65xx.c | 37 +
> >  1 file changed, 17 insertions(+), 20 deletions(-)
> > 
> > diff --git a/drivers/i2c/busses/i2c-mt65xx.c 
> > b/drivers/i2c/busses/i2c-mt65xx.c
> > index e6b984a..e475877 100644
> > --- a/drivers/i2c/busses/i2c-mt65xx.c
> > +++ b/drivers/i2c/busses/i2c-mt65xx.c
> > @@ -209,6 +209,7 @@ struct mtk_i2c_compatible {
> > unsigned char dma_sync: 1;
> > unsigned char ltiming_adjust: 1;
> > unsigned char apdma_sync: 1;
> > +   unsigned char max_dma_support;
> 
> support_33bits is no longer used. Please remove it.
> 
> Joe.C
> 

ok.

> 



Re: [PATCH 1/4] i2c: mediatek: Add apdma sync in i2c driver

2020-07-22 Thread Qii Wang
On Thu, 2020-07-23 at 09:29 +0800, Yingjoe Chen wrote:
> On Wed, 2020-07-22 at 20:31 +0800, Qii Wang wrote:
> > With the apdma remove hand-shake signal, it need to keep i2c and
> > apdma in sync manually.
> > 
> 
> Looks good to me,
> 
> Reviewed-by: Yingjoe Chen 
> 
> 
> Just a reminder, we have another patch 'i2c: mediatek: Add to support
> continuous mode' under review now. Please remember to update OFFSET_CON
> access code in that patch.
> 
> Joe.C
> 
> 

I and Qiangming are looking at whether the original multi-write code can
cover it, After confirming again, then we will decide whether it need to
send that patch. Thanks for your comments.

> 
> > Signed-off-by: Qii Wang 
> > ---
> >  drivers/i2c/busses/i2c-mt65xx.c | 23 ---
> >  1 file changed, 20 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/i2c/busses/i2c-mt65xx.c 
> > b/drivers/i2c/busses/i2c-mt65xx.c
> > index deef69e..e6b984a 100644
> > --- a/drivers/i2c/busses/i2c-mt65xx.c
> > +++ b/drivers/i2c/busses/i2c-mt65xx.c
> > @@ -48,6 +48,9 @@
> >  
> >  #define I2C_DMA_CON_TX 0x
> >  #define I2C_DMA_CON_RX 0x0001
> > +#define I2C_DMA_ASYNC_MODE 0x0004
> > +#define I2C_DMA_SKIP_CONFIG0x0010
> > +#define I2C_DMA_DIR_CHANGE 0x0200
> >  #define I2C_DMA_START_EN   0x0001
> >  #define I2C_DMA_INT_FLAG_NONE  0x
> >  #define I2C_DMA_CLR_FLAG   0x
> > @@ -205,6 +208,7 @@ struct mtk_i2c_compatible {
> > unsigned char timing_adjust: 1;
> > unsigned char dma_sync: 1;
> > unsigned char ltiming_adjust: 1;
> > +   unsigned char apdma_sync: 1;
> >  };
> >  
> >  struct mtk_i2c_ac_timing {
> > @@ -311,6 +315,7 @@ struct i2c_spec_values {
> > .timing_adjust = 1,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > +   .apdma_sync = 0,
> >  };
> >  
> >  static const struct mtk_i2c_compatible mt6577_compat = {
> > @@ -324,6 +329,7 @@ struct i2c_spec_values {
> > .timing_adjust = 0,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > +   .apdma_sync = 0,
> >  };
> >  
> >  static const struct mtk_i2c_compatible mt6589_compat = {
> > @@ -337,6 +343,7 @@ struct i2c_spec_values {
> > .timing_adjust = 0,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > +   .apdma_sync = 0,
> >  };
> >  
> >  static const struct mtk_i2c_compatible mt7622_compat = {
> > @@ -350,6 +357,7 @@ struct i2c_spec_values {
> > .timing_adjust = 0,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > +   .apdma_sync = 0,
> >  };
> >  
> >  static const struct mtk_i2c_compatible mt8173_compat = {
> > @@ -362,6 +370,7 @@ struct i2c_spec_values {
> > .timing_adjust = 0,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > +   .apdma_sync = 0,
> >  };
> >  
> >  static const struct mtk_i2c_compatible mt8183_compat = {
> > @@ -375,6 +384,7 @@ struct i2c_spec_values {
> > .timing_adjust = 1,
> > .dma_sync = 1,
> > .ltiming_adjust = 1,
> > +   .apdma_sync = 0,
> >  };
> >  
> >  static const struct of_device_id mtk_i2c_of_match[] = {
> > @@ -798,6 +808,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
> > struct i2c_msg *msgs,
> > u16 start_reg;
> > u16 control_reg;
> > u16 restart_flag = 0;
> > +   u16 dma_sync = 0;
> > u32 reg_4g_mode;
> > u8 *dma_rd_buf = NULL;
> > u8 *dma_wr_buf = NULL;
> > @@ -851,10 +862,16 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
> > struct i2c_msg *msgs,
> > mtk_i2c_writew(i2c, num, OFFSET_TRANSAC_LEN);
> > }
> >  
> > +   if (i2c->dev_comp->apdma_sync) {
> > +   dma_sync = I2C_DMA_SKIP_CONFIG | I2C_DMA_ASYNC_MODE;
> > +   if (i2c->op == I2C_MASTER_WRRD)
> > +   dma_sync |= I2C_DMA_DIR_CHANGE;
> > +   }
> > +
> > /* Prepare buffer data to start transfer */
> > if (i2c->op == I2C_MASTER_RD) {
> > writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
> > -   writel(I2C_DMA_CON_RX, i2c->pdmabase + OFFSET_CON);
> > +   writel(I2C_DMA_CON_RX | dma_sync, i2c->pdmabase + OFFSET_CON);
> >  
> > dma_rd_buf = i2c_get_dma_safe_msg_buf(msgs, 1);
> > if (!dma_rd_buf)
> > @@ -877,7 +894,7 @@ static int mtk_i2c_do_transf

Re: [PATCH 2/4] i2c: mediatek: Support DMA mask range over 33-bits

2020-07-22 Thread Qii Wang
On Wed, 2020-07-22 at 17:38 +0200, Matthias Brugger wrote:
> 
> On 22/07/2020 14:31, Qii Wang wrote:
> > Replace 'support_33bits with 'dma_max_support' for DMA mask
> > operation, and replace 'mtk_i2c_set_4g_mode' with 'upper_32_bits'.
> 
> Please explain more in detail what you are doing and how this fits to the way 
> the HW works.
> 

As Yingjoe sir said, Newer MTK chip support more than 8GB of dram, and
the register TX/RX_4G_MODE of APDMA has added corresponding bit to
support.So we Replace support_33bits with more general dma_max_support.I
will modify the title and commit as :
i2c: mediatek: Add access to more than 8GB dram in i2c driver
Newer MTK chip support more than 8GB of dram. Replace support_33bits
with more general dma_max_support and remove mtk_i2c_set_4g_mode.

> > 
> > Signed-off-by: Qii Wang 
> > ---
> >   drivers/i2c/busses/i2c-mt65xx.c | 37 +
> >   1 file changed, 17 insertions(+), 20 deletions(-)
> > 
> > diff --git a/drivers/i2c/busses/i2c-mt65xx.c 
> > b/drivers/i2c/busses/i2c-mt65xx.c
> > index e6b984a..e475877 100644
> > --- a/drivers/i2c/busses/i2c-mt65xx.c
> > +++ b/drivers/i2c/busses/i2c-mt65xx.c
> > @@ -209,6 +209,7 @@ struct mtk_i2c_compatible {
> > unsigned char dma_sync: 1;
> > unsigned char ltiming_adjust: 1;
> > unsigned char apdma_sync: 1;
> > +   unsigned char max_dma_support;
> >   };
> >   
> >   struct mtk_i2c_ac_timing {
> > @@ -311,11 +312,11 @@ struct i2c_spec_values {
> > .dcm = 1,
> > .auto_restart = 1,
> > .aux_len_reg = 1,
> > -   .support_33bits = 1,
> > .timing_adjust = 1,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > .apdma_sync = 0,
> > +   .max_dma_support = 33,
> >   };
> >   
> >   static const struct mtk_i2c_compatible mt6577_compat = {
> > @@ -325,11 +326,11 @@ struct i2c_spec_values {
> > .dcm = 1,
> > .auto_restart = 0,
> > .aux_len_reg = 0,
> > -   .support_33bits = 0,
> > .timing_adjust = 0,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > .apdma_sync = 0,
> > +   .max_dma_support = 32,
> >   };
> >   
> >   static const struct mtk_i2c_compatible mt6589_compat = {
> > @@ -339,11 +340,11 @@ struct i2c_spec_values {
> > .dcm = 0,
> > .auto_restart = 0,
> > .aux_len_reg = 0,
> > -   .support_33bits = 0,
> > .timing_adjust = 0,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > .apdma_sync = 0,
> > +   .max_dma_support = 32,
> >   };
> >   
> >   static const struct mtk_i2c_compatible mt7622_compat = {
> > @@ -353,11 +354,11 @@ struct i2c_spec_values {
> > .dcm = 1,
> > .auto_restart = 1,
> > .aux_len_reg = 1,
> > -   .support_33bits = 0,
> > .timing_adjust = 0,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > .apdma_sync = 0,
> > +   .max_dma_support = 32,
> >   };
> >   
> >   static const struct mtk_i2c_compatible mt8173_compat = {
> > @@ -366,11 +367,11 @@ struct i2c_spec_values {
> > .dcm = 1,
> > .auto_restart = 1,
> > .aux_len_reg = 1,
> > -   .support_33bits = 1,
> > .timing_adjust = 0,
> > .dma_sync = 0,
> > .ltiming_adjust = 0,
> > .apdma_sync = 0,
> > +   .max_dma_support = 33,
> >   };
> >   
> >   static const struct mtk_i2c_compatible mt8183_compat = {
> > @@ -380,11 +381,11 @@ struct i2c_spec_values {
> > .dcm = 0,
> > .auto_restart = 1,
> > .aux_len_reg = 1,
> > -   .support_33bits = 1,
> > .timing_adjust = 1,
> > .dma_sync = 1,
> > .ltiming_adjust = 1,
> > .apdma_sync = 0,
> > +   .max_dma_support = 33,
> >   };
> >   
> >   static const struct of_device_id mtk_i2c_of_match[] = {
> > @@ -796,11 +797,6 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, 
> > unsigned int parent_clk)
> > return 0;
> >   }
> >   
> > -static inline u32 mtk_i2c_set_4g_mode(dma_addr_t addr)
> > -{
> > -   return (addr & BIT_ULL(32)) ? I2C_DMA_4G_MODE : I2C_DMA_CLR_FLAG;
> 
> I2C_DMA_4G_MODE define could now be deleted as well.
> 
> Regards,
> Matthias
> 
> > -}
> > -
> >   static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
> >int num, int left_num)
> >   {
> > @@ -885,8 +881,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
> > struct i2c_

[PATCH 1/4] i2c: mediatek: Add apdma sync in i2c driver

2020-07-22 Thread Qii Wang
With the apdma remove hand-shake signal, it need to keep i2c and
apdma in sync manually.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 23 ---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index deef69e..e6b984a 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -48,6 +48,9 @@
 
 #define I2C_DMA_CON_TX 0x
 #define I2C_DMA_CON_RX 0x0001
+#define I2C_DMA_ASYNC_MODE 0x0004
+#define I2C_DMA_SKIP_CONFIG0x0010
+#define I2C_DMA_DIR_CHANGE 0x0200
 #define I2C_DMA_START_EN   0x0001
 #define I2C_DMA_INT_FLAG_NONE  0x
 #define I2C_DMA_CLR_FLAG   0x
@@ -205,6 +208,7 @@ struct mtk_i2c_compatible {
unsigned char timing_adjust: 1;
unsigned char dma_sync: 1;
unsigned char ltiming_adjust: 1;
+   unsigned char apdma_sync: 1;
 };
 
 struct mtk_i2c_ac_timing {
@@ -311,6 +315,7 @@ struct i2c_spec_values {
.timing_adjust = 1,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt6577_compat = {
@@ -324,6 +329,7 @@ struct i2c_spec_values {
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
@@ -337,6 +343,7 @@ struct i2c_spec_values {
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt7622_compat = {
@@ -350,6 +357,7 @@ struct i2c_spec_values {
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
@@ -362,6 +370,7 @@ struct i2c_spec_values {
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
+   .apdma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt8183_compat = {
@@ -375,6 +384,7 @@ struct i2c_spec_values {
.timing_adjust = 1,
.dma_sync = 1,
.ltiming_adjust = 1,
+   .apdma_sync = 0,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
@@ -798,6 +808,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
u16 start_reg;
u16 control_reg;
u16 restart_flag = 0;
+   u16 dma_sync = 0;
u32 reg_4g_mode;
u8 *dma_rd_buf = NULL;
u8 *dma_wr_buf = NULL;
@@ -851,10 +862,16 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
struct i2c_msg *msgs,
mtk_i2c_writew(i2c, num, OFFSET_TRANSAC_LEN);
}
 
+   if (i2c->dev_comp->apdma_sync) {
+   dma_sync = I2C_DMA_SKIP_CONFIG | I2C_DMA_ASYNC_MODE;
+   if (i2c->op == I2C_MASTER_WRRD)
+   dma_sync |= I2C_DMA_DIR_CHANGE;
+   }
+
/* Prepare buffer data to start transfer */
if (i2c->op == I2C_MASTER_RD) {
writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
-   writel(I2C_DMA_CON_RX, i2c->pdmabase + OFFSET_CON);
+   writel(I2C_DMA_CON_RX | dma_sync, i2c->pdmabase + OFFSET_CON);
 
dma_rd_buf = i2c_get_dma_safe_msg_buf(msgs, 1);
if (!dma_rd_buf)
@@ -877,7 +894,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
writel(msgs->len, i2c->pdmabase + OFFSET_RX_LEN);
} else if (i2c->op == I2C_MASTER_WR) {
writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
-   writel(I2C_DMA_CON_TX, i2c->pdmabase + OFFSET_CON);
+   writel(I2C_DMA_CON_TX | dma_sync, i2c->pdmabase + OFFSET_CON);
 
dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 1);
if (!dma_wr_buf)
@@ -900,7 +917,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN);
} else {
writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_INT_FLAG);
-   writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_CON);
+   writel(I2C_DMA_CLR_FLAG | dma_sync, i2c->pdmabase + OFFSET_CON);
 
dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 1);
if (!dma_wr_buf)
-- 
1.9.1


[PATCH 3/4] dt-bindings: i2c: update bindings for MT8192 SoC

2020-07-22 Thread Qii Wang
Add a DT binding documentation for the MT8192 soc.

Signed-off-by: Qii Wang 
---
 Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt 
b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
index 88b71c1..7f0194f 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
@@ -14,6 +14,7 @@ Required properties:
   "mediatek,mt7629-i2c", "mediatek,mt2712-i2c": for MediaTek MT7629
   "mediatek,mt8173-i2c": for MediaTek MT8173
   "mediatek,mt8183-i2c": for MediaTek MT8183
+  "mediatek,mt8192-i2c": for MediaTek MT8192
   "mediatek,mt8516-i2c", "mediatek,mt2712-i2c": for MediaTek MT8516
   - reg: physical base address of the controller and dma base, length of memory
 mapped region.
-- 
1.9.1


[PATCH 2/4] i2c: mediatek: Support DMA mask range over 33-bits

2020-07-22 Thread Qii Wang
Replace 'support_33bits with 'dma_max_support' for DMA mask
operation, and replace 'mtk_i2c_set_4g_mode' with 'upper_32_bits'.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 37 +
 1 file changed, 17 insertions(+), 20 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index e6b984a..e475877 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -209,6 +209,7 @@ struct mtk_i2c_compatible {
unsigned char dma_sync: 1;
unsigned char ltiming_adjust: 1;
unsigned char apdma_sync: 1;
+   unsigned char max_dma_support;
 };
 
 struct mtk_i2c_ac_timing {
@@ -311,11 +312,11 @@ struct i2c_spec_values {
.dcm = 1,
.auto_restart = 1,
.aux_len_reg = 1,
-   .support_33bits = 1,
.timing_adjust = 1,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 33,
 };
 
 static const struct mtk_i2c_compatible mt6577_compat = {
@@ -325,11 +326,11 @@ struct i2c_spec_values {
.dcm = 1,
.auto_restart = 0,
.aux_len_reg = 0,
-   .support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 32,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
@@ -339,11 +340,11 @@ struct i2c_spec_values {
.dcm = 0,
.auto_restart = 0,
.aux_len_reg = 0,
-   .support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 32,
 };
 
 static const struct mtk_i2c_compatible mt7622_compat = {
@@ -353,11 +354,11 @@ struct i2c_spec_values {
.dcm = 1,
.auto_restart = 1,
.aux_len_reg = 1,
-   .support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 32,
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
@@ -366,11 +367,11 @@ struct i2c_spec_values {
.dcm = 1,
.auto_restart = 1,
.aux_len_reg = 1,
-   .support_33bits = 1,
.timing_adjust = 0,
.dma_sync = 0,
.ltiming_adjust = 0,
.apdma_sync = 0,
+   .max_dma_support = 33,
 };
 
 static const struct mtk_i2c_compatible mt8183_compat = {
@@ -380,11 +381,11 @@ struct i2c_spec_values {
.dcm = 0,
.auto_restart = 1,
.aux_len_reg = 1,
-   .support_33bits = 1,
.timing_adjust = 1,
.dma_sync = 1,
.ltiming_adjust = 1,
.apdma_sync = 0,
+   .max_dma_support = 33,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
@@ -796,11 +797,6 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned 
int parent_clk)
return 0;
 }
 
-static inline u32 mtk_i2c_set_4g_mode(dma_addr_t addr)
-{
-   return (addr & BIT_ULL(32)) ? I2C_DMA_4G_MODE : I2C_DMA_CLR_FLAG;
-}
-
 static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
   int num, int left_num)
 {
@@ -885,8 +881,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
return -ENOMEM;
}
 
-   if (i2c->dev_comp->support_33bits) {
-   reg_4g_mode = mtk_i2c_set_4g_mode(rpaddr);
+   if (i2c->dev_comp->max_dma_support > 32) {
+   reg_4g_mode = upper_32_bits(rpaddr);
writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE);
}
 
@@ -908,8 +904,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
return -ENOMEM;
}
 
-   if (i2c->dev_comp->support_33bits) {
-   reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr);
+   if (i2c->dev_comp->max_dma_support > 32) {
+   reg_4g_mode = upper_32_bits(wpaddr);
writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);
}
 
@@ -954,11 +950,11 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
struct i2c_msg *msgs,
return -ENOMEM;
}
 
-   if (i2c->dev_comp->support_33bits) {
-   reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr);
+   if (i2c->dev_comp->max_dma_support > 32) {
+   reg_4g_mode = upper_32_bits(wpaddr);
writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);
 
-   reg_4g_mode = mtk_i2c_set_4g_mode(rpaddr);
+   reg_4g_mode = upper_32_bits(rpaddr);
writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE);
}
 
@@ -1232,8 

[PATCH 4/4] i2c: mediatek: Add i2c compatible for MediaTek MT8192

2020-07-22 Thread Qii Wang
Add i2c compatible for MT8192. Compare to MT8183 i2c controller,
MT8192 support more then 8GB DMA mode.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index e475877..47f3eef 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -388,6 +388,20 @@ struct i2c_spec_values {
.max_dma_support = 33,
 };
 
+static const struct mtk_i2c_compatible mt8192_compat = {
+   .quirks = &mt8183_i2c_quirks,
+   .regs = mt_i2c_regs_v2,
+   .pmic_i2c = 0,
+   .dcm = 0,
+   .auto_restart = 1,
+   .aux_len_reg = 1,
+   .timing_adjust = 1,
+   .dma_sync = 1,
+   .ltiming_adjust = 1,
+   .apdma_sync = 1,
+   .max_dma_support = 36,
+};
+
 static const struct of_device_id mtk_i2c_of_match[] = {
{ .compatible = "mediatek,mt2712-i2c", .data = &mt2712_compat },
{ .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
@@ -395,6 +409,7 @@ struct i2c_spec_values {
{ .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
{ .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
{ .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
+   { .compatible = "mediatek,mt8192-i2c", .data = &mt8192_compat },
{}
 };
 MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
-- 
1.9.1


[PATCH 0/4] add i2c support for mt8192

2020-07-22 Thread Qii Wang
This series are based on 5.8-rc1 and we provide four i2c patches
to support mt8192 SoC.

Qii Wang (4):
  i2c: mediatek: Add apdma sync in i2c driver
  i2c: mediatek: Support DMA mask range over 33-bits
  dt-bindings: i2c: update bindings for MT8192 SoC
  i2c: mediatek: Add i2c compatible for MediaTek MT8192

 .../devicetree/bindings/i2c/i2c-mt65xx.txt |  1 +
 drivers/i2c/busses/i2c-mt65xx.c| 75 +++---
 2 files changed, 53 insertions(+), 23 deletions(-)

--
1.9.1



Re: [PATCH] i2c: mediatek: Add to support continuous mode

2020-06-28 Thread Qii Wang
Hi Qiangming:
Do you have the specific timing cost data about the "continuous mode"?
Is it better than the default multi-write mode(one message by one
message) ?I need to know if this patch is very necessary.

On Fri, 2020-06-19 at 16:06 +0800, Qiangming Xia wrote:
> From: "qiangming.xia" 
> 
> Mediatek i2c controller support for continuous mode,
> it allow to transfer once multiple writing messages of equal length.
> For example, a slave need write a serial of non-continuous
> offset range in chip,e.g. writing offset 0,offset 2 and offset 4.
> Normally, it need three times i2c write operation. However,it can
> use once transfer to finish it by using continuous mode.
> 
> Change-Id: If06991e3fd32867bdeaacf15bb24864d5c5904d0
> Signed-off-by: Qiangming Xia 
> ---
>  drivers/i2c/busses/i2c-mt65xx.c | 67 +
>  1 file changed, 67 insertions(+)
> 
> diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
> index deef69e56906..76ec65d869f6 100644
> --- a/drivers/i2c/busses/i2c-mt65xx.c
> +++ b/drivers/i2c/busses/i2c-mt65xx.c
> @@ -97,6 +97,7 @@ enum mtk_trans_op {
>   I2C_MASTER_WR = 1,
>   I2C_MASTER_RD,
>   I2C_MASTER_WRRD,
> + I2C_MASTER_CONTINUOUS_WR,
>  };
>  
>  enum I2C_REGS_OFFSET {
> @@ -846,6 +847,9 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
> struct i2c_msg *msgs,
>   OFFSET_TRANSFER_LEN);
>   }
>   mtk_i2c_writew(i2c, I2C_WRRD_TRANAC_VALUE, OFFSET_TRANSAC_LEN);
> + } else if (i2c->op == I2C_MASTER_CONTINUOUS_WR) {
> + mtk_i2c_writew(i2c, msgs->len / num, OFFSET_TRANSFER_LEN);
> + mtk_i2c_writew(i2c, num, OFFSET_TRANSAC_LEN);
>   } else {
>   mtk_i2c_writew(i2c, msgs->len, OFFSET_TRANSFER_LEN);
>   mtk_i2c_writew(i2c, num, OFFSET_TRANSAC_LEN);
> @@ -896,6 +900,23 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
> struct i2c_msg *msgs,
>   writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);
>   }
>  
> + writel((u32)wpaddr, i2c->pdmabase + OFFSET_TX_MEM_ADDR);
> + writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN);
> + } else if (i2c->op == I2C_MASTER_CONTINUOUS_WR) {
> + writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
> + writel(I2C_DMA_CON_TX, i2c->pdmabase + OFFSET_CON);
> + wpaddr = dma_map_single(i2c->dev, msgs->buf,
> + msgs->len, DMA_TO_DEVICE);
> + if (dma_mapping_error(i2c->dev, wpaddr)) {
> + kfree(msgs->buf);
> + return -ENOMEM;
> + }
> +
> + if (i2c->dev_comp->support_33bits) {
> + reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr);
> + writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);
> + }
> +
>   writel((u32)wpaddr, i2c->pdmabase + OFFSET_TX_MEM_ADDR);
>   writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN);
>   } else {
> @@ -979,6 +1000,11 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
> struct i2c_msg *msgs,
>msgs->len, DMA_FROM_DEVICE);
>  
>   i2c_put_dma_safe_msg_buf(dma_rd_buf, msgs, true);
> + } else if (i2c->op == I2C_MASTER_CONTINUOUS_WR) {
> + dma_unmap_single(i2c->dev, wpaddr,
> +  msgs->len, DMA_TO_DEVICE);
> +
> + kfree(msgs->buf);
>   } else {
>   dma_unmap_single(i2c->dev, wpaddr, msgs->len,
>DMA_TO_DEVICE);
> @@ -1009,6 +1035,9 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
>  {
>   int ret;
>   int left_num = num;
> + int i, j;
> + u8 *dma_multi_wr_buf;
> + struct i2c_msg multi_msg[1];
>   struct mtk_i2c *i2c = i2c_get_adapdata(adap);
>  
>   ret = mtk_i2c_clock_enable(i2c);
> @@ -1025,6 +1054,44 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
>   }
>   }
>  
> + if (num > 1) {
> + for (i = 0; i < num - 1; i++) {
> + if (!(msgs[i].flags & I2C_M_RD) && !(msgs[i+1].flags &
> + I2C_M_RD) && (msgs[i].addr == msgs[i+1].addr)
> + && (msgs[i].len == msgs[i+1].len)) {
> + continue;
> + } else
> + break;
> + }
> + if (i >= num - 1) {
> + i2c->op = I2C_MASTER_CONTINUOUS_WR;
> + j = 0;
> + dma_multi_wr_buf = kzalloc(msgs->len * num, GFP_KERNEL);
> + if (!dma_multi_wr_buf) {
> + ret =  -ENOMEM;
> + goto err_exit;
> + }
> + multi_msg->addr  = msgs->addr;
> + multi

Re: [PATCH] i2c: mediatek: Add to support continuous mode

2020-06-19 Thread Qii Wang
On Fri, 2020-06-19 at 16:06 +0800, Qiangming Xia wrote:
> From: "qiangming.xia" 
> 
> Mediatek i2c controller support for continuous mode,
> it allow to transfer once multiple writing messages of equal length.
> For example, a slave need write a serial of non-continuous
> offset range in chip,e.g. writing offset 0,offset 2 and offset 4.
> Normally, it need three times i2c write operation. However,it can
> use once transfer to finish it by using continuous mode.
> 
> Change-Id: If06991e3fd32867bdeaacf15bb24864d5c5904d0
> Signed-off-by: Qiangming Xia 
> ---
>  drivers/i2c/busses/i2c-mt65xx.c | 67 +
>  1 file changed, 67 insertions(+)
> 
> diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
> index deef69e56906..76ec65d869f6 100644
> --- a/drivers/i2c/busses/i2c-mt65xx.c
> +++ b/drivers/i2c/busses/i2c-mt65xx.c
> @@ -97,6 +97,7 @@ enum mtk_trans_op {
>   I2C_MASTER_WR = 1,
>   I2C_MASTER_RD,
>   I2C_MASTER_WRRD,
> + I2C_MASTER_CONTINUOUS_WR,
>  };
>  
>  enum I2C_REGS_OFFSET {
> @@ -846,6 +847,9 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
> struct i2c_msg *msgs,
>   OFFSET_TRANSFER_LEN);
>   }
>   mtk_i2c_writew(i2c, I2C_WRRD_TRANAC_VALUE, OFFSET_TRANSAC_LEN);
> + } else if (i2c->op == I2C_MASTER_CONTINUOUS_WR) {
> + mtk_i2c_writew(i2c, msgs->len / num, OFFSET_TRANSFER_LEN);
> + mtk_i2c_writew(i2c, num, OFFSET_TRANSAC_LEN);
>   } else {
>   mtk_i2c_writew(i2c, msgs->len, OFFSET_TRANSFER_LEN);
>   mtk_i2c_writew(i2c, num, OFFSET_TRANSAC_LEN);
> @@ -896,6 +900,23 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
> struct i2c_msg *msgs,
>   writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);
>   }
>  
> + writel((u32)wpaddr, i2c->pdmabase + OFFSET_TX_MEM_ADDR);
> + writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN);
> + } else if (i2c->op == I2C_MASTER_CONTINUOUS_WR) {
> + writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
> + writel(I2C_DMA_CON_TX, i2c->pdmabase + OFFSET_CON);
> + wpaddr = dma_map_single(i2c->dev, msgs->buf,
> + msgs->len, DMA_TO_DEVICE);
> + if (dma_mapping_error(i2c->dev, wpaddr)) {
> + kfree(msgs->buf);
> + return -ENOMEM;
> + }
> +
> + if (i2c->dev_comp->support_33bits) {
> + reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr);
> + writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);
> + }
> +
>   writel((u32)wpaddr, i2c->pdmabase + OFFSET_TX_MEM_ADDR);
>   writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN);
>   } else {
> @@ -979,6 +1000,11 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
> struct i2c_msg *msgs,
>msgs->len, DMA_FROM_DEVICE);
>  
>   i2c_put_dma_safe_msg_buf(dma_rd_buf, msgs, true);
> + } else if (i2c->op == I2C_MASTER_CONTINUOUS_WR) {
> + dma_unmap_single(i2c->dev, wpaddr,
> +  msgs->len, DMA_TO_DEVICE);
> +
> + kfree(msgs->buf);
>   } else {
>   dma_unmap_single(i2c->dev, wpaddr, msgs->len,
>DMA_TO_DEVICE);
> @@ -1009,6 +1035,9 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
>  {
>   int ret;
>   int left_num = num;
> + int i, j;
> + u8 *dma_multi_wr_buf;
> + struct i2c_msg multi_msg[1];
>   struct mtk_i2c *i2c = i2c_get_adapdata(adap);
>  
>   ret = mtk_i2c_clock_enable(i2c);
> @@ -1025,6 +1054,44 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
>   }
>   }
>  
> + if (num > 1) {
> + for (i = 0; i < num - 1; i++) {
> + if (!(msgs[i].flags & I2C_M_RD) && !(msgs[i+1].flags &
> + I2C_M_RD) && (msgs[i].addr == msgs[i+1].addr)
> + && (msgs[i].len == msgs[i+1].len)) {

if these conditions are not met, Can these transfers work?
 
> + continue;
> + } else
> + break;
> + }
> + if (i >= num - 1) {
> + i2c->op = I2C_MASTER_CONTINUOUS_WR;
> + j = 0;
> + dma_multi_wr_buf = kzalloc(msgs->len * num, GFP_KERNEL);
> + if (!dma_multi_wr_buf) {
> + ret =  -ENOMEM;
> + goto err_exit;
> + }
> + multi_msg->addr  = msgs->addr;
> + multi_msg->len   = msgs->len * num;
> + multi_msg->buf   = dma_multi_wr_buf;
> + multi_msg->flags  = 0;
> +  

Re: [PATCH v2 2/2] i2c: mediatek: Add i2c ac-timing adjust support

2020-05-20 Thread Qii Wang
Hi Geert,

On Wed, 2020-05-20 at 10:58 +0200, Geert Uytterhoeven wrote:
> Hi Qii,
> 
> On Wed, May 20, 2020 at 10:44 AM Qii Wang  wrote:
> > On Tue, 2020-05-19 at 09:14 +0200, Geert Uytterhoeven wrote:
> > > On Tue, May 19, 2020 at 4:59 AM Qii Wang  wrote:
> > > > On Mon, 2020-05-18 at 17:44 +0200, Geert Uytterhoeven wrote:
> > > > > On Thu, May 14, 2020 at 3:13 PM Qii Wang  
> > > > > wrote:
> > > > > > This patch adds a algorithm to calculate some ac-timing parameters
> > > > > > which can fully meet I2C Spec.
> > > > > >
> > > > > > Signed-off-by: Qii Wang 
> > > > > > ---
> > > > > >  drivers/i2c/busses/i2c-mt65xx.c | 328 
> > > > > > +---
> > > > > >  1 file changed, 277 insertions(+), 51 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/i2c/busses/i2c-mt65xx.c 
> > > > > > b/drivers/i2c/busses/i2c-mt65xx.c
> > > > > > index 0ca6c38a..7020618 100644
> > > > > > --- a/drivers/i2c/busses/i2c-mt65xx.c
> > > > > > +++ b/drivers/i2c/busses/i2c-mt65xx.c
> > > > >
> > > > > > +/*
> > > > > > + * Check and Calculate i2c ac-timing
> > > > > > + *
> > > > > > + * Hardware design:
> > > > > > + * sample_ns = (10 * (sample_cnt + 1)) / clk_src
> > > > > > + * xxx_cnt_div =  spec->min_xxx_ns / sample_ns
> > > > > > + *
> > > > > > + * Sample_ns is rounded down for xxx_cnt_div would be greater
> > > > > > + * than the smallest spec.
> > > > > > + * The sda_timing is chosen as the middle value between
> > > > > > + * the largest and smallest.
> > > > > > + */
> > > > > > +static int mtk_i2c_check_ac_timing(struct mtk_i2c *i2c,
> > > > > > +  unsigned int clk_src,
> > > > > > +  unsigned int check_speed,
> > > > > > +  unsigned int step_cnt,
> > > > > > +  unsigned int sample_cnt)
> > > > > > +{
> > > > > > +   const struct i2c_spec_values *spec;
> > > > > > +   unsigned int su_sta_cnt, low_cnt, high_cnt, max_step_cnt;
> > > > > > +   unsigned int sda_max, sda_min, clk_ns, max_sta_cnt = 0x3f;
> > > > > > +   long long sample_ns = (10 * (sample_cnt + 1)) / 
> > > > > > clk_src;
> > > > >
> > > > > So sample_ns is a 64-bit value. Is that really needed?
> > > > >
> > > >
> > > > (10 * (sample_cnt + 1)) / clk_src value is a 32-bit, (10
> > > > * (sample_cnt + 1)) will over 32-bit if sample_cnt is 7.
> > >
> > > The intermediate value will indeed not fit in 32-bit.
> > > But that doesn't mean the end result won't fit in 32-bit.
> > > As you divide spec->min_low_ns and spec->min_su_dat_ns (which I assume
> > > are small numbers) by sample_ns below, sample_ns cannot be very large,
> > > or the quotient will be zero anyway.
> > > So just doing the multiplication in 64-bit, followed by a 64-by-32
> > > division is probably fine:
> > >
> > > unsigned int sample_ns = div_u64(10ULL * (sample_cnt + 1), 
> > > clk_src);
> > >
> > > You may want to take precautions for the case where the passed value of
> > > clk_src is a small number (can that happen?).
> > >
> > > BTW, clk_get_rate() returns "unsigned long", while mtk_i2c_set_speed()
> > > takes an "unsigned int" parent_clk, which may cause future issues.
> > > You may want to change that to "unsigned long", along the whole
> > > propagation path, and use div64_ul() instead of div_u64() above.
> > >
> >
> > The return type of div_u64 is u64(unsigned long long), there is a
> > compulsory type conversion operator. Do you think it is needed?
> 
> The result of a 64-by-32 bit division may indeed not fit in 32-bit, so that's
> why it returns u64.
> If you know the quotient will always fit, it's fine.
> 
> > BTW, we just need to change the type of sample_ns to unsigned int, no
> > matter which method is used, what is your opinion?
> 
> Indeed.
&g

Re: [PATCH v2 2/2] i2c: mediatek: Add i2c ac-timing adjust support

2020-05-20 Thread Qii Wang
Hi Geert,

On Tue, 2020-05-19 at 09:14 +0200, Geert Uytterhoeven wrote:
> Hi Qii,
> 
> On Tue, May 19, 2020 at 4:59 AM Qii Wang  wrote:
> > On Mon, 2020-05-18 at 17:44 +0200, Geert Uytterhoeven wrote:
> > > On Thu, May 14, 2020 at 3:13 PM Qii Wang  wrote:
> > > > This patch adds a algorithm to calculate some ac-timing parameters
> > > > which can fully meet I2C Spec.
> > > >
> > > > Signed-off-by: Qii Wang 
> > > > ---
> > > >  drivers/i2c/busses/i2c-mt65xx.c | 328 
> > > > +---
> > > >  1 file changed, 277 insertions(+), 51 deletions(-)
> > > >
> > > > diff --git a/drivers/i2c/busses/i2c-mt65xx.c 
> > > > b/drivers/i2c/busses/i2c-mt65xx.c
> > > > index 0ca6c38a..7020618 100644
> > > > --- a/drivers/i2c/busses/i2c-mt65xx.c
> > > > +++ b/drivers/i2c/busses/i2c-mt65xx.c
> > >
> > > > +/*
> > > > + * Check and Calculate i2c ac-timing
> > > > + *
> > > > + * Hardware design:
> > > > + * sample_ns = (10 * (sample_cnt + 1)) / clk_src
> > > > + * xxx_cnt_div =  spec->min_xxx_ns / sample_ns
> > > > + *
> > > > + * Sample_ns is rounded down for xxx_cnt_div would be greater
> > > > + * than the smallest spec.
> > > > + * The sda_timing is chosen as the middle value between
> > > > + * the largest and smallest.
> > > > + */
> > > > +static int mtk_i2c_check_ac_timing(struct mtk_i2c *i2c,
> > > > +  unsigned int clk_src,
> > > > +  unsigned int check_speed,
> > > > +  unsigned int step_cnt,
> > > > +  unsigned int sample_cnt)
> > > > +{
> > > > +   const struct i2c_spec_values *spec;
> > > > +   unsigned int su_sta_cnt, low_cnt, high_cnt, max_step_cnt;
> > > > +   unsigned int sda_max, sda_min, clk_ns, max_sta_cnt = 0x3f;
> > > > +   long long sample_ns = (10 * (sample_cnt + 1)) / clk_src;
> > >
> > > So sample_ns is a 64-bit value. Is that really needed?
> > >
> >
> > (10 * (sample_cnt + 1)) / clk_src value is a 32-bit, (10
> > * (sample_cnt + 1)) will over 32-bit if sample_cnt is 7.
> 
> The intermediate value will indeed not fit in 32-bit.
> But that doesn't mean the end result won't fit in 32-bit.
> As you divide spec->min_low_ns and spec->min_su_dat_ns (which I assume
> are small numbers) by sample_ns below, sample_ns cannot be very large,
> or the quotient will be zero anyway.
> So just doing the multiplication in 64-bit, followed by a 64-by-32
> division is probably fine:
> 
> unsigned int sample_ns = div_u64(10ULL * (sample_cnt + 1), 
> clk_src);
> 
> You may want to take precautions for the case where the passed value of
> clk_src is a small number (can that happen?).
> 
> BTW, clk_get_rate() returns "unsigned long", while mtk_i2c_set_speed()
> takes an "unsigned int" parent_clk, which may cause future issues.
> You may want to change that to "unsigned long", along the whole
> propagation path, and use div64_ul() instead of div_u64() above.
> 

The return type of div_u64 is u64(unsigned long long), there is a
compulsory type conversion operator. Do you think it is needed?
BTW, we just need to change the type of sample_ns to unsigned int, no
matter which method is used, what is your opinion?

> > I think 10 and clk_src is too big, maybe I can reduce then with
> > be divided all by 1000.
> > example:
> >
> > unsigned int sample_ns;
> > unsigned int clk_src_khz = clk_src / 1000;
> 
> That may cause too much loss of precision.
> 

clk_src is more than MHz and less than GHZ for MTK i2c controller, so it
wouldn't cause too much loss of precision.

> >
> > if(clk_src_khz)
> > sample_ns = (100 * (sample_cnt + 1)) / clk_src_khz;
> > else
> > return -EINVAL;
> >
> > > > +   if (!i2c->dev_comp->timing_adjust)
> > > > +   return 0;
> > > > +
> > > > +   if (i2c->dev_comp->ltiming_adjust)
> > > > +   max_sta_cnt = 0x100;
> > > > +
> > > > +   spec = mtk_i2c_get_spec(check_speed);
> > > > +
> > > > +   if (i2c->dev_comp->ltiming_adjust)
> > > > +   clk_ns = 10 / clk_src;
> > > > +   else
> > > > +   clk_ns = sample_ns / 2;
> > > > +
> > > > +   su_sta_cnt = DIV_ROUND_UP(spec->min_su_sta_ns, clk_ns);
> > > > +   if (su_sta_cnt > max_sta_cnt)
> > > > +   return -1;
> > > > +
> > > > +   low_cnt = DIV_ROUND_UP(spec->min_low_ns, sample_ns);
> > >
> > > So this is a 32-bit by 64-bit division (indeed, not 64-by-32!)
> 
> Gr{oetje,eeting}s,
> 
> Geert
> 



Re: [PATCH v2 2/2] i2c: mediatek: Add i2c ac-timing adjust support

2020-05-18 Thread Qii Wang
On Mon, 2020-05-18 at 17:44 +0200, Geert Uytterhoeven wrote:
> On Thu, May 14, 2020 at 3:13 PM Qii Wang  wrote:
> > This patch adds a algorithm to calculate some ac-timing parameters
> > which can fully meet I2C Spec.
> >
> > Signed-off-by: Qii Wang 
> > ---
> >  drivers/i2c/busses/i2c-mt65xx.c | 328 
> > +---
> >  1 file changed, 277 insertions(+), 51 deletions(-)
> >
> > diff --git a/drivers/i2c/busses/i2c-mt65xx.c 
> > b/drivers/i2c/busses/i2c-mt65xx.c
> > index 0ca6c38a..7020618 100644
> > --- a/drivers/i2c/busses/i2c-mt65xx.c
> > +++ b/drivers/i2c/busses/i2c-mt65xx.c
> 
> > +/*
> > + * Check and Calculate i2c ac-timing
> > + *
> > + * Hardware design:
> > + * sample_ns = (10 * (sample_cnt + 1)) / clk_src
> > + * xxx_cnt_div =  spec->min_xxx_ns / sample_ns
> > + *
> > + * Sample_ns is rounded down for xxx_cnt_div would be greater
> > + * than the smallest spec.
> > + * The sda_timing is chosen as the middle value between
> > + * the largest and smallest.
> > + */
> > +static int mtk_i2c_check_ac_timing(struct mtk_i2c *i2c,
> > +  unsigned int clk_src,
> > +  unsigned int check_speed,
> > +  unsigned int step_cnt,
> > +  unsigned int sample_cnt)
> > +{
> > +   const struct i2c_spec_values *spec;
> > +   unsigned int su_sta_cnt, low_cnt, high_cnt, max_step_cnt;
> > +   unsigned int sda_max, sda_min, clk_ns, max_sta_cnt = 0x3f;
> > +   long long sample_ns = (10 * (sample_cnt + 1)) / clk_src;
> 
> So sample_ns is a 64-bit value. Is that really needed?
> 

(10 * (sample_cnt + 1)) / clk_src value is a 32-bit, (10
* (sample_cnt + 1)) will over 32-bit if sample_cnt is 7.

I think 10 and clk_src is too big, maybe I can reduce then with
be divided all by 1000.
example:

unsigned int sample_ns;
unsigned int clk_src_khz = clk_src / 1000;

if(clk_src_khz)
sample_ns = (100 * (sample_cnt + 1)) / clk_src_khz;
else
return -EINVAL;

> > +   if (!i2c->dev_comp->timing_adjust)
> > +   return 0;
> > +
> > +   if (i2c->dev_comp->ltiming_adjust)
> > +   max_sta_cnt = 0x100;
> > +
> > +   spec = mtk_i2c_get_spec(check_speed);
> > +
> > +   if (i2c->dev_comp->ltiming_adjust)
> > +   clk_ns = 10 / clk_src;
> > +   else
> > +   clk_ns = sample_ns / 2;
> > +
> > +   su_sta_cnt = DIV_ROUND_UP(spec->min_su_sta_ns, clk_ns);
> > +   if (su_sta_cnt > max_sta_cnt)
> > +   return -1;
> > +
> > +   low_cnt = DIV_ROUND_UP(spec->min_low_ns, sample_ns);
> 
> So this is a 32-bit by 64-bit division (indeed, not 64-by-32!)
> 
> nore...@ellerman.id.au reports:
> 
> ERROR: modpost: "__udivdi3" [drivers/i2c/busses/i2c-mt65xx.ko] undefined!
> ERROR: modpost: "__divdi3" [drivers/i2c/busses/i2c-mt65xx.ko] undefined!
> 
> for 32-bit builds.
> 
> > +   max_step_cnt = mtk_i2c_max_step_cnt(check_speed);
> > +   if ((2 * step_cnt) > low_cnt && low_cnt < max_step_cnt) {
> > +   if (low_cnt > step_cnt) {
> > +   high_cnt = 2 * step_cnt - low_cnt;
> > +   } else {
> > +   high_cnt = step_cnt;
> > +   low_cnt = step_cnt;
> > +   }
> > +   } else {
> > +   return -2;
> > +   }
> > +
> > +   sda_max = spec->max_hd_dat_ns / sample_ns;
> > +   if (sda_max > low_cnt)
> > +   sda_max = 0;
> > +
> > +   sda_min = DIV_ROUND_UP(spec->min_su_dat_ns, sample_ns);
> 
> One more.
> 
> Gr{oetje,eeting}s,
> 
> Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- 
> ge...@linux-m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like 
> that.
> -- Linus Torvalds



[PATCH v2 0/2] Add i2c ac-timing adjust support

2020-05-14 Thread Qii Wang
This series are based on 5.7-rc1, we provide two patches to support i2c 
ac-timing.

Main changes compared to v1:
--add maintainer for mediatek i2c controller driver
--fix warning of self-assignment

Qii Wang (2):
  MAINTAINERS: add maintainer for mediatek i2c controller driver
  i2c: mediatek: Add i2c ac-timing adjust support

 MAINTAINERS |   7 +
 drivers/i2c/busses/i2c-mt65xx.c | 328 +---
 2 files changed, 284 insertions(+), 51 deletions(-)

--
1.9.1



[PATCH v2 2/2] i2c: mediatek: Add i2c ac-timing adjust support

2020-05-14 Thread Qii Wang
This patch adds a algorithm to calculate some ac-timing parameters
which can fully meet I2C Spec.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c | 328 +---
 1 file changed, 277 insertions(+), 51 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 0ca6c38a..7020618 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -40,12 +40,11 @@
 #define I2C_SOFT_RST   0x0001
 #define I2C_FIFO_ADDR_CLR  0x0001
 #define I2C_DELAY_LEN  0x0002
-#define I2C_ST_START_CON   0x8001
-#define I2C_FS_START_CON   0x1800
 #define I2C_TIME_CLR_VALUE 0x
 #define I2C_TIME_DEFAULT_VALUE 0x0003
 #define I2C_WRRD_TRANAC_VALUE  0x0002
 #define I2C_RD_TRANAC_VALUE0x0001
+#define I2C_SCL_MIS_COMP_VALUE 0x
 
 #define I2C_DMA_CON_TX 0x
 #define I2C_DMA_CON_RX 0x0001
@@ -55,10 +54,13 @@
 #define I2C_DMA_HARD_RST   0x0002
 #define I2C_DMA_4G_MODE0x0001
 
-#define I2C_DEFAULT_CLK_DIV5
 #define MAX_SAMPLE_CNT_DIV 8
 #define MAX_STEP_CNT_DIV   64
+#define MAX_CLOCK_DIV  256
 #define MAX_HS_STEP_CNT_DIV8
+#define I2C_STANDARD_MODE_BUFFER   (1000 / 2)
+#define I2C_FAST_MODE_BUFFER   (300 / 2)
+#define I2C_FAST_MODE_PLUS_BUFFER  (20 / 2)
 
 #define I2C_CONTROL_RS  (0x1 << 1)
 #define I2C_CONTROL_DMA_EN  (0x1 << 2)
@@ -123,6 +125,12 @@ enum I2C_REGS_OFFSET {
OFFSET_TRANSFER_LEN_AUX,
OFFSET_CLOCK_DIV,
OFFSET_LTIMING,
+   OFFSET_SCL_HIGH_LOW_RATIO,
+   OFFSET_HS_SCL_HIGH_LOW_RATIO,
+   OFFSET_SCL_MIS_COMP_POINT,
+   OFFSET_STA_STO_AC_TIMING,
+   OFFSET_HS_STA_STO_AC_TIMING,
+   OFFSET_SDA_TIMING,
 };
 
 static const u16 mt_i2c_regs_v1[] = {
@@ -150,6 +158,12 @@ enum I2C_REGS_OFFSET {
[OFFSET_DEBUGCTRL] = 0x68,
[OFFSET_TRANSFER_LEN_AUX] = 0x6c,
[OFFSET_CLOCK_DIV] = 0x70,
+   [OFFSET_SCL_HIGH_LOW_RATIO] = 0x74,
+   [OFFSET_HS_SCL_HIGH_LOW_RATIO] = 0x78,
+   [OFFSET_SCL_MIS_COMP_POINT] = 0x7C,
+   [OFFSET_STA_STO_AC_TIMING] = 0x80,
+   [OFFSET_HS_STA_STO_AC_TIMING] = 0x84,
+   [OFFSET_SDA_TIMING] = 0x88,
 };
 
 static const u16 mt_i2c_regs_v2[] = {
@@ -168,9 +182,11 @@ enum I2C_REGS_OFFSET {
[OFFSET_HS] = 0x30,
[OFFSET_IO_CONFIG] = 0x34,
[OFFSET_FIFO_ADDR_CLR] = 0x38,
+   [OFFSET_SDA_TIMING] = 0x3c,
[OFFSET_TRANSFER_LEN_AUX] = 0x44,
[OFFSET_CLOCK_DIV] = 0x48,
[OFFSET_SOFTRESET] = 0x50,
+   [OFFSET_SCL_MIS_COMP_POINT] = 0x90,
[OFFSET_DEBUGSTAT] = 0xe0,
[OFFSET_DEBUGCTRL] = 0xe8,
[OFFSET_FIFO_STAT] = 0xf4,
@@ -191,6 +207,19 @@ struct mtk_i2c_compatible {
unsigned char ltiming_adjust: 1;
 };
 
+struct mtk_i2c_ac_timing {
+   u16 htiming;
+   u16 ltiming;
+   u16 hs;
+   u16 ext;
+   u16 inter_clk_div;
+   u16 scl_hl_ratio;
+   u16 hs_scl_hl_ratio;
+   u16 sta_stop;
+   u16 hs_sta_stop;
+   u16 sda_timing;
+};
+
 struct mtk_i2c {
struct i2c_adapter adap;/* i2c host adapter */
struct device *dev;
@@ -215,9 +244,46 @@ struct mtk_i2c {
u16 ltiming_reg;
unsigned char auto_restart;
bool ignore_restart_irq;
+   struct mtk_i2c_ac_timing ac_timing;
const struct mtk_i2c_compatible *dev_comp;
 };
 
+/**
+ * struct i2c_spec_values:
+ * min_low_ns: min LOW period of the SCL clock
+ * min_su_sta_ns: min set-up time for a repeated START condition
+ * max_hd_dat_ns: max data hold time
+ * min_su_dat_ns: min data set-up time
+ */
+struct i2c_spec_values {
+   unsigned int min_low_ns;
+   unsigned int min_high_ns;
+   unsigned int min_su_sta_ns;
+   unsigned int max_hd_dat_ns;
+   unsigned int min_su_dat_ns;
+};
+
+static const struct i2c_spec_values standard_mode_spec = {
+   .min_low_ns = 4700 + I2C_STANDARD_MODE_BUFFER,
+   .min_su_sta_ns = 4700 + I2C_STANDARD_MODE_BUFFER,
+   .max_hd_dat_ns = 3450 - I2C_STANDARD_MODE_BUFFER,
+   .min_su_dat_ns = 250 + I2C_STANDARD_MODE_BUFFER,
+};
+
+static const struct i2c_spec_values fast_mode_spec = {
+   .min_low_ns = 1300 + I2C_FAST_MODE_BUFFER,
+   .min_su_sta_ns = 600 + I2C_FAST_MODE_BUFFER,
+   .max_hd_dat_ns = 900 - I2C_FAST_MODE_BUFFER,
+   .min_su_dat_ns = 100 + I2C_FAST_MODE_BUFFER,
+};
+
+static const struct i2c_spec_values fast_mode_plus_spec = {
+   .min_low_ns = 500 + I2C_FAST_MODE_PLUS_BUFFER,
+   .min_su_sta_ns = 260 + I2C_FAST_MODE_PLUS_BUFFER,
+   .max_hd_dat_ns = 400 - I2C_FAST_MODE_PLUS_BUFFER,
+   .min_su_dat_ns = 50 + I2C_FAST_MODE_PLUS_BUFFER,
+};
+
 static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
  

[PATCH v2 1/2] MAINTAINERS: add maintainer for mediatek i2c controller driver

2020-05-14 Thread Qii Wang
Add Qii Wang as maintainer for mediatek i2c controller driver.

Signed-off-by: Qii Wang 
---
 MAINTAINERS | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index e64e5db..c0fdf11 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10658,6 +10658,13 @@ L: net...@vger.kernel.org
 S: Maintained
 F: drivers/net/ethernet/mediatek/
 
+MEDIATEK I2C CONTROLLER DRIVER
+M: Qii Wang 
+L: linux-...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
+F: drivers/i2c/busses/i2c-mt65xx.c
+
 MEDIATEK JPEG DRIVER
 M: Rick Chang 
 M: Bin Liu 
-- 
1.9.1


Re: [PATCH] i2c: mediatek: Add i2c ac-timing adjust support

2020-05-14 Thread Qii Wang
On Thu, 2020-05-14 at 08:29 +0200, Wolfram Sang wrote:
> > > Last question: You seem to be the one doing major updates to this
> > > driver. Thanks for that! Are you maybe interested in becoming the
> > > maintainer for this driver? I think there won't be much patches to
> > > review and reports to handle but it will speed up processing for me.
> > 
> > Yes, It is my honor to be the maintainer for this driver.
> 
> Awesome! :) Can you prepare a patch for MAINTAINERS or shall I?
> 

ok, I will send with this patch.


Re: [PATCH] i2c: mediatek: Add i2c ac-timing adjust support

2020-05-13 Thread Qii Wang
On Tue, 2020-05-12 at 15:38 +0200, Wolfram Sang wrote:
> Hi Qii Wang,
> 
> On Thu, Mar 26, 2020 at 07:54:36PM +0800, qii.w...@mediatek.com wrote:
> > From: Qii Wang 
> > 
> > This patch adds a algorithm to calculate some ac-timing parameters
> > which can fully meet I2C Spec.
> > 
> > Signed-off-by: Qii Wang 
> 
> Could you rebase this on top of i2c/for-next or v5.7-rcX? Because of
> commit 90224e6468e1 ("i2c: drivers: Use generic definitions for bus
> frequencies") which was added two days before your patch was sent out.
> 
> Otherwise mostly minor nits.
> 
> > +static int mtk_i2c_max_step_cnt(unsigned int target_speed)
> > +{
> > +   if (target_speed > MAX_FS_MODE_SPEED)
> > +   return MAX_HS_STEP_CNT_DIV;
> > +   else
> > +   return MAX_STEP_CNT_DIV;
> > +}
> 
> Maybe ternary operator here? Your choice.
> 

Use ternary operator here will over 80 bytes, and need a line break,
Maybe this code looks simpler.

> And my code checkers complained:
> 
> CPPCHECK
> drivers/i2c/busses/i2c-mt65xx.c:591:11: warning: Redundant assignment of 
> 'sda_max' to itself. [selfAssignment]
>   sda_max = sda_max;
>   ^
> drivers/i2c/busses/i2c-mt65xx.c:597:11: warning: Redundant assignment of 
> 'sda_min' to itself. [selfAssignment]
>   sda_min = sda_min;
> 
ok, I will modify it.

> Last question: You seem to be the one doing major updates to this
> driver. Thanks for that! Are you maybe interested in becoming the
> maintainer for this driver? I think there won't be much patches to
> review and reports to handle but it will speed up processing for me.
> 

Yes, It is my honor to be the maintainer for this driver.

> All the best,
> 
>Wolfram
> 



Re: [PATCH v2] i2c: mediatek: disable zero-length transfers for mt8183

2019-08-23 Thread Qii Wang
On Fri, 2019-08-23 at 16:13 +0800, Hsin-Yi Wang wrote:
> On Fri, Aug 23, 2019 at 4:09 PM Qii Wang  wrote:
> 
> > >
> > >  static u32 mtk_i2c_functionality(struct i2c_adapter *adap)
> > >  {
> > > - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
> > > + if (adap->quirks->flags & I2C_AQ_NO_ZERO_LEN)
> > > + return I2C_FUNC_I2C |
> > > + (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
> > > + else
> > > + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
> >
> > It can be removed?
> See previous discussion: https://patchwork.kernel.org/patch/10814391/#22484435
> but not all SoC's quirks has I2C_AQ_NO_ZERO_LEN.
ok, it looks good for me, thanks.
Reviewed-by: Qii Wang 




Re: [PATCH v2] i2c: mediatek: disable zero-length transfers for mt8183

2019-08-23 Thread Qii Wang
On Thu, 2019-08-22 at 17:45 +0800, Hsin-Yi Wang wrote:
> When doing i2cdetect quick write mode, we would get transfer
> error ENOMEM, and i2cdetect shows there's no device at the address.
> Quoting from mt8183 datasheet, the number of transfers to be
> transferred in one transaction should be set to bigger than 1,
> so we should forbid zero-length transfer and update functionality.
> 
> Incorrect return:
> localhost ~ # i2cdetect -q -y 0
>  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
> 00:  -- -- -- -- -- -- -- -- -- -- -- -- --
> 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> 70: -- -- -- -- -- -- -- --
> 
> After this patch:
> localhost ~ #  i2cdetect -q -y 0
> Error: Can't use SMBus Quick Write command on this bus
> 
> localhost ~ #  i2cdetect -y 0
> Warning: Can't use SMBus Quick Write command, will skip some addresses
>  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
> 00:
> 10:
> 20:
> 30: -- -- -- -- -- -- -- --
> 40:
> 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
> 60:
> 70:
> 
> Reported-by: Alexandru M Stan 
> Signed-off-by: Hsin-Yi Wang 
> ---
> Change from v1:
> * restore the order of algo and quirks
> ---
>  drivers/i2c/busses/i2c-mt65xx.c | 11 ++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
> index 252edb433fdf..29eae1bf4f86 100644
> --- a/drivers/i2c/busses/i2c-mt65xx.c
> +++ b/drivers/i2c/busses/i2c-mt65xx.c
> @@ -234,6 +234,10 @@ static const struct i2c_adapter_quirks mt7622_i2c_quirks 
> = {
>   .max_num_msgs = 255,
>  };
>  
> +static const struct i2c_adapter_quirks mt8183_i2c_quirks = {
> + .flags = I2C_AQ_NO_ZERO_LEN,
> +};
> +
>  static const struct mtk_i2c_compatible mt2712_compat = {
>   .regs = mt_i2c_regs_v1,
>   .pmic_i2c = 0,
> @@ -298,6 +302,7 @@ static const struct mtk_i2c_compatible mt8173_compat = {
>  };
>  
>  static const struct mtk_i2c_compatible mt8183_compat = {
> + .quirks = &mt8183_i2c_quirks,
>   .regs = mt_i2c_regs_v2,
>   .pmic_i2c = 0,
>   .dcm = 0,
> @@ -870,7 +875,11 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
>  
>  static u32 mtk_i2c_functionality(struct i2c_adapter *adap)
>  {
> - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
> + if (adap->quirks->flags & I2C_AQ_NO_ZERO_LEN)
> + return I2C_FUNC_I2C |
> + (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
> + else
> + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;

It can be removed?

>  }
>  
>  static const struct i2c_algorithm mtk_i2c_algorithm = {




Re: [PATCH v3 1/2] dt-bindings: i3c: Document MediaTek I3C master bindings

2019-07-29 Thread Qii Wang
On Sat, 2019-07-27 at 11:18 +0200, Boris Brezillon wrote:
> On Sat, 27 Jul 2019 09:23:33 +0800
> Qii Wang  wrote:
> 
> > On Wed, 2019-07-24 at 14:21 -0600, Rob Herring wrote:
> > > On Tue, Jul 09, 2019 at 09:09:21PM +0800, Qii Wang wrote:  
> > > > Document MediaTek I3C master DT bindings.
> > > > 
> > > > Signed-off-by: Qii Wang 
> > > > ---
> > > >  .../devicetree/bindings/i3c/mtk,i3c-master.txt |   48 
> > > > 
> > > >  1 file changed, 48 insertions(+)
> > > >  create mode 100644 
> > > > Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt 
> > > > b/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
> > > > new file mode 100644
> > > > index 000..d32eda6
> > > > --- /dev/null
> > > > +++ b/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
> > > > @@ -0,0 +1,48 @@
> > > > +Bindings for MediaTek I3C master block
> > > > +=
> > > > +
> > > > +Required properties:
> > > > +
> > > > +- compatible: shall be "mediatek,i3c-master"  
> > > 
> > > Needs to be SoC specific.
> > >   
> > 
> > We hope that the SOCs will use the same driver and try to avoid big
> > changes. If there are inevitable changes in the future, then we will
> > modify the compatible to be SoC specific. cdns,i3c-master.txt is not SoC
> > specific either.
> 
> The cadence case is a bit different I think. When the driver was
> developed there was no SoC integrating this IP. I guess Mediatek knows
> already which SoC(s) will embed the I3C master block.
> 

ok, I will modify it as "mediatek,mt8183-i3c".

> > 
> > > > +- reg: physical base address of the controller and apdma base, length 
> > > > of
> > > > +  memory mapped region.
> > > > +- reg-names: shall be "main" for master controller and "dma" for apdma.
> > > > +- interrupts: the interrupt line connected to this I3C master.
> > > > +- clocks: shall reference the i3c and apdma clocks.
> > > > +- clock-names: shall include "main" and "dma".
> > > > +
> > > > +Mandatory properties defined by the generic binding (see
> > > > +Documentation/devicetree/bindings/i3c/i3c.txt for more details):
> > > > +
> > > > +- #address-cells: shall be set to 3
> > > > +- #size-cells: shall be set to 0
> > > > +
> > > > +Optional properties defined by the generic binding (see
> > > > +Documentation/devicetree/bindings/i3c/i3c.txt for more details):
> > > > +
> > > > +- i2c-scl-hz
> > > > +- i3c-scl-hz
> > > > +
> > > > +I3C device connected on the bus follow the generic description (see
> > > > +Documentation/devicetree/bindings/i3c/i3c.txt for more details).
> > > > +
> > > > +Example:
> > > > +
> > > > +   i3c0: i3c@1100d000 {
> > > > +   compatible = "mediatek,i3c-master";
> > > > +   reg = <0x1100d000 0x1000>,
> > > > + <0x11000300 0x80>;
> > > > +   reg-names = "main", "dma";
> > > > +   interrupts = ;
> > > > +   clocks = <&infracfg CLK_INFRA_I3C0>,
> > > > +<&infracfg CLK_INFRA_AP_DMA>;
> > > > +   clock-names = "main", "dma";
> > > > +   #address-cells = <3>;
> > > > +   #size-cells = <0>;
> > > > +   i2c-scl-hz = <10>;
> > > > +
> > > > +   nunchuk: nunchuk@52 {
> > > > +   compatible = "nintendo,nunchuk";
> > > > +   reg = <0x52 0x0 0x10>;
> > > > +   };
> > > > +   };
> > > > -- 
> > > > 1.7.9.5
> > > >   
> > 
> > 
> 




Re: [PATCH v3 1/2] dt-bindings: i3c: Document MediaTek I3C master bindings

2019-07-26 Thread Qii Wang
On Wed, 2019-07-24 at 14:21 -0600, Rob Herring wrote:
> On Tue, Jul 09, 2019 at 09:09:21PM +0800, Qii Wang wrote:
> > Document MediaTek I3C master DT bindings.
> > 
> > Signed-off-by: Qii Wang 
> > ---
> >  .../devicetree/bindings/i3c/mtk,i3c-master.txt |   48 
> > 
> >  1 file changed, 48 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt 
> > b/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
> > new file mode 100644
> > index 000..d32eda6
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
> > @@ -0,0 +1,48 @@
> > +Bindings for MediaTek I3C master block
> > +=
> > +
> > +Required properties:
> > +
> > +- compatible: shall be "mediatek,i3c-master"
> 
> Needs to be SoC specific.
> 

We hope that the SOCs will use the same driver and try to avoid big
changes. If there are inevitable changes in the future, then we will
modify the compatible to be SoC specific. cdns,i3c-master.txt is not SoC
specific either.

> > +- reg: physical base address of the controller and apdma base, length of
> > +  memory mapped region.
> > +- reg-names: shall be "main" for master controller and "dma" for apdma.
> > +- interrupts: the interrupt line connected to this I3C master.
> > +- clocks: shall reference the i3c and apdma clocks.
> > +- clock-names: shall include "main" and "dma".
> > +
> > +Mandatory properties defined by the generic binding (see
> > +Documentation/devicetree/bindings/i3c/i3c.txt for more details):
> > +
> > +- #address-cells: shall be set to 3
> > +- #size-cells: shall be set to 0
> > +
> > +Optional properties defined by the generic binding (see
> > +Documentation/devicetree/bindings/i3c/i3c.txt for more details):
> > +
> > +- i2c-scl-hz
> > +- i3c-scl-hz
> > +
> > +I3C device connected on the bus follow the generic description (see
> > +Documentation/devicetree/bindings/i3c/i3c.txt for more details).
> > +
> > +Example:
> > +
> > +   i3c0: i3c@1100d000 {
> > +   compatible = "mediatek,i3c-master";
> > +   reg = <0x1100d000 0x1000>,
> > + <0x11000300 0x80>;
> > +   reg-names = "main", "dma";
> > +   interrupts = ;
> > +   clocks = <&infracfg CLK_INFRA_I3C0>,
> > +<&infracfg CLK_INFRA_AP_DMA>;
> > +   clock-names = "main", "dma";
> > +   #address-cells = <3>;
> > +   #size-cells = <0>;
> > +   i2c-scl-hz = <10>;
> > +
> > +   nunchuk: nunchuk@52 {
> > +   compatible = "nintendo,nunchuk";
> > +   reg = <0x52 0x0 0x10>;
> > +   };
> > +   };
> > -- 
> > 1.7.9.5
> > 




Re: [PATCH 1/2] dt-bindings: i2c: Add MediaTek i2c AC timing binding

2019-07-17 Thread Qii Wang
On Wed, 2019-06-26 at 15:39 +0200, Wolfram Sang wrote:
> Hi,
> 
> On Tue, Jun 11, 2019 at 04:11:54PM +0800, Qii Wang wrote:
> > Add i2c AC timing binding to binding file. It can give the AC
> > timing parameters to meet I2C specification at different speed.
> > 
> > Signed-off-by: Qii Wang 
> 
> I think this is a too specific 1:1 mapping of your register set into DT
> world. We already have these generic parameters:
> 
> - clock-frequency
> frequency of bus clock in Hz.
> 
> - i2c-scl-falling-time-ns
> Number of nanoseconds the SCL signal takes to fall; t(f) in the I2C
> specification.
> 
> - i2c-scl-internal-delay-ns
> Number of nanoseconds the IP core additionally needs to setup SCL.
> 
> - i2c-scl-rising-time-ns
> Number of nanoseconds the SCL signal takes to rise; t(r) in the I2C
> specification.
> 
> - i2c-sda-falling-time-ns
> Number of nanoseconds the SDA signal takes to fall; t(f) in the I2C
> specification.
> 
> (check Documentation/devicetree/bindings/i2c/i2c.txt)
> 
> Can't you use those to derive your values from that? Which ones are you 
> missing
> if not?
> 
> Regards,
> 
>Wolfram

I have take a little time to develop a new patch which based on your
suggestions, and it tested OK. Thanks for your suggestions, I will
update the patch after I test it fully.




[PATCH v3 2/2] i3c: master: Add driver for MediaTek IP

2019-07-09 Thread Qii Wang
Add a driver for MediaTek I3C master IP.

Signed-off-by: Qii Wang 
---
 drivers/i3c/master/Kconfig  |   10 +
 drivers/i3c/master/Makefile |1 +
 drivers/i3c/master/i3c-master-mtk.c | 1239 +++
 3 files changed, 1250 insertions(+)
 create mode 100644 drivers/i3c/master/i3c-master-mtk.c

diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig
index 26c6b58..acc00d9 100644
--- a/drivers/i3c/master/Kconfig
+++ b/drivers/i3c/master/Kconfig
@@ -20,3 +20,13 @@ config DW_I3C_MASTER
 
  This driver can also be built as a module.  If so, the module
  will be called dw-i3c-master.
+
+config MTK_I3C_MASTER
+   tristate "MediaTek I3C master driver"
+   depends on I3C
+   depends on HAS_IOMEM
+   depends on !(ALPHA || PARISC)
+   help
+ This selects the MediaTek(R) I3C master controller driver.
+ If you want to use MediaTek(R) I3C interface, say Y here.
+ If unsure, say N or M.
diff --git a/drivers/i3c/master/Makefile b/drivers/i3c/master/Makefile
index fc53939..fe7ccf5 100644
--- a/drivers/i3c/master/Makefile
+++ b/drivers/i3c/master/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_CDNS_I3C_MASTER)  += i3c-master-cdns.o
 obj-$(CONFIG_DW_I3C_MASTER)+= dw-i3c-master.o
+obj-$(CONFIG_MTK_I3C_MASTER)   += i3c-master-mtk.o
diff --git a/drivers/i3c/master/i3c-master-mtk.c 
b/drivers/i3c/master/i3c-master-mtk.c
new file mode 100644
index 000..3981149
--- /dev/null
+++ b/drivers/i3c/master/i3c-master-mtk.c
@@ -0,0 +1,1239 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Design Systems Inc.
+ *
+ * Author: Qii Wang 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DRV_NAME   "i3c-master-mtk"
+
+#define SLAVE_ADDR 0x04
+#define INTR_MASK  0x08
+#define INTR_STAT  0x0c
+#define INTR_TRANSAC_COMP  BIT(0)
+#define INTR_ACKERRGENMASK(2, 1)
+#define INTR_ARB_LOST  BIT(3)
+#define INTR_RS_MULTI  BIT(4)
+#define INTR_MAS_ERR   BIT(8)
+#define INTR_ALL   (INTR_MAS_ERR | INTR_ARB_LOST |\
+   INTR_ACKERR | INTR_TRANSAC_COMP)
+
+#define CONTROL0x10
+#define CONTROL_WRAPPERBIT(0)
+#define CONTROL_RS BIT(1)
+#define CONTROL_DMA_EN BIT(2)
+#define CONTROL_CLK_EXT_EN BIT(3)
+#define CONTROL_DIR_CHANGE BIT(4)
+#define CONTROL_ACKERR_DET_EN  BIT(5)
+#define CONTROL_LEN_CHANGE BIT(6)
+#define CONTROL_DMAACK_EN  BIT(8)
+#define CONTROL_ASYNC_MODE BIT(9)
+
+#define TRANSFER_LEN   0x14
+#define TRANSAC_LEN0x18
+#define TRANSAC_LEN_WRRD   0x0002
+#define TRANS_ONE_LEN  0x0001
+
+#define DELAY_LEN  0x1c
+#define DELAY_LEN_DEFAULT  0x000a
+
+#define TIMING 0x20
+#define TIMING_VALUE(sample_cnt, step_cnt) ({ \
+   typeof(sample_cnt) sample_cnt_ = (sample_cnt); \
+   typeof(step_cnt) step_cnt_ = (step_cnt); \
+   (((sample_cnt_) << 8) | (step_cnt_)); \
+})
+
+#define START  0x24
+#define START_EN   BIT(0)
+#define START_MUL_TRIG BIT(14)
+#define START_MUL_CNFG BIT(15)
+
+#define EXT_CONF   0x28
+#define EXT_CONF_DEFAULT   0x0a1f
+
+#define LTIMING0x2c
+#define LTIMING_VALUE(sample_cnt, step_cnt) ({ \
+   typeof(sample_cnt) sample_cnt_ = (sample_cnt); \
+   typeof(step_cnt) step_cnt_ = (step_cnt); \
+   (((sample_cnt_) << 6) | (step_cnt_) | \
+   ((sample_cnt_) << 12) | ((step_cnt_) << 9)); \
+})
+
+#define HS 0x30
+#define HS_CLR_VALUE   0x
+#define HS_DEFAULT_VALUE   0x0083
+#define HS_VALUE(sample_cnt, step_cnt) ({ \
+   typeof(sample_cnt) sample_cnt_ = (sample_cnt); \
+   typeof(step_cnt) step_cnt_ = (step_cnt); \
+   (HS_DEFAULT_VALUE | \
+   ((sample_cnt_) << 12) | ((step_cnt_) << 8)); \
+})
+
+#define IO_CONFIG  0x34
+#define IO_CONFIG_PUSH_PULL0x
+
+#define FIFO_ADDR_CLR  0x38
+#define FIFO_CLR   0x0003
+
+#define MCU_INTR   0x40
+#define MCU_INTR_ENBIT(0)
+
+#define TRANSFER_LEN_AUX   0x44
+#define CLOCK_DIV  0x48
+#define CLOCK_DIV_DEFAULT  ((INTER_CLK_DIV - 1) << 8 |\
+   (INTER_CLK_DIV - 1))
+
+#define SOFTRESET  0x50
+#define SOFT_RST   BIT(0)
+
+#define TRAFFIC0x54
+#define TRAFFIC_DAA_EN BIT(4)
+#define TRAFFIC_TBIT   BIT(7)
+#define TRAFFIC_HEAD_ONLY  BIT(9)
+#define TRAFFIC_SKIP_SLV_ADDR  BIT(10)
+#define TRAFFIC_HANDOFFBIT(14)
+
+#define DEF_DA 0x68
+#define DEF_DAA_SLV_PARITY BIT(8)
+
+#define SHAPE  0x6c

[PATCH v3 0/2] Add MediaTek I3C master controller driver

2019-07-09 Thread Qii Wang
This series are based on 5.2-rc1, we provide two patches to
support MediaTek I3C master controller.

Main changes compared to v2:
--modify the description of clock and interrupt in bindings
--use correct cells for I2C device in bindings

Main changes compared to v1:
--remove clock-div, let clock driver handle it
--let sample_cnt and step_cnt start from two

Qii Wang (2):
  dt-bindings: i3c: Document MediaTek I3C master bindings
  i3c: master: Add driver for MediaTek IP

 .../devicetree/bindings/i3c/mtk,i3c-master.txt |   48 +
 drivers/i3c/master/Kconfig |   10 +
 drivers/i3c/master/Makefile|1 +
 drivers/i3c/master/i3c-master-mtk.c| 1239 
 4 files changed, 1298 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
 create mode 100644 drivers/i3c/master/i3c-master-mtk.c

-- 
1.7.9.5


[PATCH v3 1/2] dt-bindings: i3c: Document MediaTek I3C master bindings

2019-07-09 Thread Qii Wang
Document MediaTek I3C master DT bindings.

Signed-off-by: Qii Wang 
---
 .../devicetree/bindings/i3c/mtk,i3c-master.txt |   48 
 1 file changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt

diff --git a/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt 
b/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
new file mode 100644
index 000..d32eda6
--- /dev/null
+++ b/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
@@ -0,0 +1,48 @@
+Bindings for MediaTek I3C master block
+=
+
+Required properties:
+
+- compatible: shall be "mediatek,i3c-master"
+- reg: physical base address of the controller and apdma base, length of
+  memory mapped region.
+- reg-names: shall be "main" for master controller and "dma" for apdma.
+- interrupts: the interrupt line connected to this I3C master.
+- clocks: shall reference the i3c and apdma clocks.
+- clock-names: shall include "main" and "dma".
+
+Mandatory properties defined by the generic binding (see
+Documentation/devicetree/bindings/i3c/i3c.txt for more details):
+
+- #address-cells: shall be set to 3
+- #size-cells: shall be set to 0
+
+Optional properties defined by the generic binding (see
+Documentation/devicetree/bindings/i3c/i3c.txt for more details):
+
+- i2c-scl-hz
+- i3c-scl-hz
+
+I3C device connected on the bus follow the generic description (see
+Documentation/devicetree/bindings/i3c/i3c.txt for more details).
+
+Example:
+
+   i3c0: i3c@1100d000 {
+   compatible = "mediatek,i3c-master";
+   reg = <0x1100d000 0x1000>,
+ <0x11000300 0x80>;
+   reg-names = "main", "dma";
+   interrupts = ;
+   clocks = <&infracfg CLK_INFRA_I3C0>,
+<&infracfg CLK_INFRA_AP_DMA>;
+   clock-names = "main", "dma";
+   #address-cells = <3>;
+   #size-cells = <0>;
+   i2c-scl-hz = <10>;
+
+   nunchuk: nunchuk@52 {
+   compatible = "nintendo,nunchuk";
+   reg = <0x52 0x0 0x10>;
+   };
+   };
-- 
1.7.9.5



Re: [PATCH v2 1/2] dt-bindings: i3c: Document MediaTek I3C master bindings

2019-06-27 Thread Qii Wang
On Wed, 2019-06-26 at 18:23 +0200, Boris Brezillon wrote:
> On Wed, 26 Jun 2019 13:36:27 +0800
> Qii Wang  wrote:
> 
> > Document MediaTek I3C master DT bindings.
> > 
> > Signed-off-by: Qii Wang 
> > ---
> >  .../devicetree/bindings/i3c/mtk,i3c-master.txt |   47 
> > 
> >  1 file changed, 47 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt 
> > b/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
> > new file mode 100644
> > index 000..3fd4f17
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
> > @@ -0,0 +1,47 @@
> > +Bindings for MediaTek I3C master block
> > +=
> > +
> > +Required properties:
> > +
> > +- compatible: shall be "mediatek,i3c-master"
> > +- reg: physical base address of the controller and apdma base, length of
> > +  memory mapped region.
> > +- reg-names: should be "main" for controller and "dma" for apdma.
> > +- interrupts: interrupt number to the cpu.
> 
> Depending on the interrupt controller, each interrupt cell might
> contain more than just the interrupt number.
> 

ok, I will modify it as "the interrupt line connected to this I3C
master"

> > +- clocks: clock name from clock manager.
> 
> This property does not contain clock names but clk references.
> 

ok, I will modify it as "shall reference the i3c and apdma clocks"

> > +- clock-names: must include "main" and "dma".
> > +
> > +Mandatory properties defined by the generic binding (see
> > +Documentation/devicetree/bindings/i3c/i3c.txt for more details):
> > +
> > +- #address-cells: shall be set to 3
> > +- #size-cells: shall be set to 0
> > +
> > +Optional properties defined by the generic binding (see
> > +Documentation/devicetree/bindings/i3c/i3c.txt for more details):
> > +
> > +- i2c-scl-hz
> > +- i3c-scl-hz
> > +
> > +I3C device connected on the bus follow the generic description (see
> > +Documentation/devicetree/bindings/i3c/i3c.txt for more details).
> > +
> > +Example:
> > +
> > +   i3c0: i3c@1100d000 {
> > +   compatible = "mediatek,i3c-master";
> > +   reg = <0x1100d000 0x100>,
> > + <0x11000300 0x80>;
> > +   reg-names = "main", "dma";
> > +   interrupts = ;
> > +   clocks = <&i3c0_ck>, <&ap_dma_ck>;
> > +   clock-names = "main", "dma";
> > +   #address-cells = <1>;
> > +   #size-cells = <0>;
> > +   i2c-scl-hz = <10>;
> > +
> > +   nunchuk: nunchuk@52 {
> > +   compatible = "nintendo,nunchuk";
> > +   reg = <0x52 0x8010 0>;
> 
> reg is wrong here, should be
> 
>   reg = <0x52 0x0 0x10>;
> 
> While at it, can you send a patch to fix the example in the cadence
> binding doc?
> 

ok, I will do it. Thanks for your review.

> > +   };
> > +   };
> 




[PATCH v2 0/2] Add MediaTek I3C master controller driver

2019-06-25 Thread Qii Wang
This series are based on 5.2-rc1, we provide two patches to
support MediaTek I3C master controller.

Main changes compared to v1:
--remove clock-div, let clock driver handle it
--let sample_cnt and step_cnt start from two

Qii Wang (2):
  dt-bindings: i3c: Document MediaTek I3C master bindings
  i3c: master: Add driver for MediaTek IP

 .../devicetree/bindings/i3c/mtk,i3c-master.txt |   47 +
 drivers/i3c/master/Kconfig |   10 +
 drivers/i3c/master/Makefile|1 +
 drivers/i3c/master/i3c-master-mtk.c| 1239 
 4 files changed, 1297 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
 create mode 100644 drivers/i3c/master/i3c-master-mtk.c

-- 
1.7.9.5


[PATCH v2 1/2] dt-bindings: i3c: Document MediaTek I3C master bindings

2019-06-25 Thread Qii Wang
Document MediaTek I3C master DT bindings.

Signed-off-by: Qii Wang 
---
 .../devicetree/bindings/i3c/mtk,i3c-master.txt |   47 
 1 file changed, 47 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt

diff --git a/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt 
b/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
new file mode 100644
index 000..3fd4f17
--- /dev/null
+++ b/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
@@ -0,0 +1,47 @@
+Bindings for MediaTek I3C master block
+=
+
+Required properties:
+
+- compatible: shall be "mediatek,i3c-master"
+- reg: physical base address of the controller and apdma base, length of
+  memory mapped region.
+- reg-names: should be "main" for controller and "dma" for apdma.
+- interrupts: interrupt number to the cpu.
+- clocks: clock name from clock manager.
+- clock-names: must include "main" and "dma".
+
+Mandatory properties defined by the generic binding (see
+Documentation/devicetree/bindings/i3c/i3c.txt for more details):
+
+- #address-cells: shall be set to 3
+- #size-cells: shall be set to 0
+
+Optional properties defined by the generic binding (see
+Documentation/devicetree/bindings/i3c/i3c.txt for more details):
+
+- i2c-scl-hz
+- i3c-scl-hz
+
+I3C device connected on the bus follow the generic description (see
+Documentation/devicetree/bindings/i3c/i3c.txt for more details).
+
+Example:
+
+   i3c0: i3c@1100d000 {
+   compatible = "mediatek,i3c-master";
+   reg = <0x1100d000 0x100>,
+ <0x11000300 0x80>;
+   reg-names = "main", "dma";
+   interrupts = ;
+   clocks = <&i3c0_ck>, <&ap_dma_ck>;
+   clock-names = "main", "dma";
+   #address-cells = <1>;
+   #size-cells = <0>;
+   i2c-scl-hz = <10>;
+
+   nunchuk: nunchuk@52 {
+   compatible = "nintendo,nunchuk";
+   reg = <0x52 0x8010 0>;
+   };
+   };
-- 
1.7.9.5



[PATCH v2 2/2] i3c: master: Add driver for MediaTek IP

2019-06-25 Thread Qii Wang
Add a driver for MediaTek I3C master IP.

Signed-off-by: Qii Wang 
---
 drivers/i3c/master/Kconfig  |   10 +
 drivers/i3c/master/Makefile |1 +
 drivers/i3c/master/i3c-master-mtk.c | 1239 +++
 3 files changed, 1250 insertions(+)
 create mode 100644 drivers/i3c/master/i3c-master-mtk.c

diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig
index 26c6b58..acc00d9 100644
--- a/drivers/i3c/master/Kconfig
+++ b/drivers/i3c/master/Kconfig
@@ -20,3 +20,13 @@ config DW_I3C_MASTER
 
  This driver can also be built as a module.  If so, the module
  will be called dw-i3c-master.
+
+config MTK_I3C_MASTER
+   tristate "MediaTek I3C master driver"
+   depends on I3C
+   depends on HAS_IOMEM
+   depends on !(ALPHA || PARISC)
+   help
+ This selects the MediaTek(R) I3C master controller driver.
+ If you want to use MediaTek(R) I3C interface, say Y here.
+ If unsure, say N or M.
diff --git a/drivers/i3c/master/Makefile b/drivers/i3c/master/Makefile
index fc53939..fe7ccf5 100644
--- a/drivers/i3c/master/Makefile
+++ b/drivers/i3c/master/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_CDNS_I3C_MASTER)  += i3c-master-cdns.o
 obj-$(CONFIG_DW_I3C_MASTER)+= dw-i3c-master.o
+obj-$(CONFIG_MTK_I3C_MASTER)   += i3c-master-mtk.o
diff --git a/drivers/i3c/master/i3c-master-mtk.c 
b/drivers/i3c/master/i3c-master-mtk.c
new file mode 100644
index 000..3981149
--- /dev/null
+++ b/drivers/i3c/master/i3c-master-mtk.c
@@ -0,0 +1,1239 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Design Systems Inc.
+ *
+ * Author: Qii Wang 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DRV_NAME   "i3c-master-mtk"
+
+#define SLAVE_ADDR 0x04
+#define INTR_MASK  0x08
+#define INTR_STAT  0x0c
+#define INTR_TRANSAC_COMP  BIT(0)
+#define INTR_ACKERRGENMASK(2, 1)
+#define INTR_ARB_LOST  BIT(3)
+#define INTR_RS_MULTI  BIT(4)
+#define INTR_MAS_ERR   BIT(8)
+#define INTR_ALL   (INTR_MAS_ERR | INTR_ARB_LOST |\
+   INTR_ACKERR | INTR_TRANSAC_COMP)
+
+#define CONTROL0x10
+#define CONTROL_WRAPPERBIT(0)
+#define CONTROL_RS BIT(1)
+#define CONTROL_DMA_EN BIT(2)
+#define CONTROL_CLK_EXT_EN BIT(3)
+#define CONTROL_DIR_CHANGE BIT(4)
+#define CONTROL_ACKERR_DET_EN  BIT(5)
+#define CONTROL_LEN_CHANGE BIT(6)
+#define CONTROL_DMAACK_EN  BIT(8)
+#define CONTROL_ASYNC_MODE BIT(9)
+
+#define TRANSFER_LEN   0x14
+#define TRANSAC_LEN0x18
+#define TRANSAC_LEN_WRRD   0x0002
+#define TRANS_ONE_LEN  0x0001
+
+#define DELAY_LEN  0x1c
+#define DELAY_LEN_DEFAULT  0x000a
+
+#define TIMING 0x20
+#define TIMING_VALUE(sample_cnt, step_cnt) ({ \
+   typeof(sample_cnt) sample_cnt_ = (sample_cnt); \
+   typeof(step_cnt) step_cnt_ = (step_cnt); \
+   (((sample_cnt_) << 8) | (step_cnt_)); \
+})
+
+#define START  0x24
+#define START_EN   BIT(0)
+#define START_MUL_TRIG BIT(14)
+#define START_MUL_CNFG BIT(15)
+
+#define EXT_CONF   0x28
+#define EXT_CONF_DEFAULT   0x0a1f
+
+#define LTIMING0x2c
+#define LTIMING_VALUE(sample_cnt, step_cnt) ({ \
+   typeof(sample_cnt) sample_cnt_ = (sample_cnt); \
+   typeof(step_cnt) step_cnt_ = (step_cnt); \
+   (((sample_cnt_) << 6) | (step_cnt_) | \
+   ((sample_cnt_) << 12) | ((step_cnt_) << 9)); \
+})
+
+#define HS 0x30
+#define HS_CLR_VALUE   0x
+#define HS_DEFAULT_VALUE   0x0083
+#define HS_VALUE(sample_cnt, step_cnt) ({ \
+   typeof(sample_cnt) sample_cnt_ = (sample_cnt); \
+   typeof(step_cnt) step_cnt_ = (step_cnt); \
+   (HS_DEFAULT_VALUE | \
+   ((sample_cnt_) << 12) | ((step_cnt_) << 8)); \
+})
+
+#define IO_CONFIG  0x34
+#define IO_CONFIG_PUSH_PULL0x
+
+#define FIFO_ADDR_CLR  0x38
+#define FIFO_CLR   0x0003
+
+#define MCU_INTR   0x40
+#define MCU_INTR_ENBIT(0)
+
+#define TRANSFER_LEN_AUX   0x44
+#define CLOCK_DIV  0x48
+#define CLOCK_DIV_DEFAULT  ((INTER_CLK_DIV - 1) << 8 |\
+   (INTER_CLK_DIV - 1))
+
+#define SOFTRESET  0x50
+#define SOFT_RST   BIT(0)
+
+#define TRAFFIC0x54
+#define TRAFFIC_DAA_EN BIT(4)
+#define TRAFFIC_TBIT   BIT(7)
+#define TRAFFIC_HEAD_ONLY  BIT(9)
+#define TRAFFIC_SKIP_SLV_ADDR  BIT(10)
+#define TRAFFIC_HANDOFFBIT(14)
+
+#define DEF_DA 0x68
+#define DEF_DAA_SLV_PARITY BIT(8)
+
+#define SHAPE  0x6c

Re: [PATCH 2/2] i3c: master: Add driver for MediaTek IP

2019-06-13 Thread Qii Wang
On Tue, 2019-06-11 at 14:28 +0200, Boris Brezillon wrote:
> On Tue, 11 Jun 2019 20:25:22 +0800
> Qii Wang  wrote:
> 
> > On Tue, 2019-06-04 at 20:26 +0800, Qii Wang wrote:
> > > On Tue, 2019-06-04 at 09:58 +0200, Boris Brezillon wrote:  
> > > > On Mon, 3 Jun 2019 11:51:03 +0800
> > > > Qii Wang  wrote:
> > > > 
> > > >   
> > > > > +static int mtk_i3c_master_probe(struct platform_device *pdev)
> > > > > +{
> > > > > + struct device *dev = &pdev->dev;
> > > > > + struct mtk_i3c_master *master;
> > > > > + struct resource *res;
> > > > > + int ret, irqnr;
> > > > > +
> > > > > + master = devm_kzalloc(dev, sizeof(*master), GFP_KERNEL);
> > > > > + if (!master)
> > > > > + return -ENOMEM;
> > > > > +
> > > > > + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 
> > > > > "main");
> > > > > + master->regs = devm_ioremap_resource(dev, res);
> > > > > + if (IS_ERR(master->regs))
> > > > > + return PTR_ERR(master->regs);
> > > > > +
> > > > > + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
> > > > > + master->dma_regs = devm_ioremap_resource(dev, res);
> > > > > + if (IS_ERR(master->dma_regs))
> > > > > + return PTR_ERR(master->dma_regs);
> > > > > +
> > > > > + irqnr = platform_get_irq(pdev, 0);
> > > > > + if (irqnr < 0)
> > > > > + return irqnr;
> > > > > +
> > > > > + ret = devm_request_irq(dev, irqnr, mtk_i3c_master_irq,
> > > > > +IRQF_TRIGGER_NONE, DRV_NAME, master);
> > > > > + if (ret < 0) {
> > > > > + dev_err(dev, "Request I3C IRQ %d fail\n", irqnr);
> > > > > + return ret;
> > > > > + }
> > > > > +
> > > > > + ret = of_property_read_u32(pdev->dev.of_node, "clock-div",
> > > > > +&master->clk_src_div);  
> > > > 
> > > > You say in one comment that this clock divider is fixed in HW but might
> > > > change on a per-SoC basis. If that's the case, you should get rid of
> > > > this clock-div prop and attach the divider to the compatible (using an
> > > > mtk_i3c_master_variant struct that contains a divider field).
> > > >   
> > > 
> > > ok, I will attach the divider to the compatible.
> > >   
> > I have rechecked your comment, maybe I have misunderstood what you mean.
> > "clock-div" changes according to i2c source clock, different project may
> > change i2c source clock, The previous dt-binding may be misleading, I
> > will modify it.
> 
> Is it fixed or configurable? Maybe it should be modeled as a clk
> driver. What's for sure is that we shouldn't have this divider defined
> in the DT.

ok, I have let the clk driver handle it, and remove it in DT and i3c
driver. Thanks!




Re: [PATCH 2/2] i3c: master: Add driver for MediaTek IP

2019-06-11 Thread Qii Wang
On Tue, 2019-06-04 at 20:26 +0800, Qii Wang wrote:
> On Tue, 2019-06-04 at 09:58 +0200, Boris Brezillon wrote:
> > On Mon, 3 Jun 2019 11:51:03 +0800
> > Qii Wang  wrote:
> > 
> > 
> > > +static int mtk_i3c_master_probe(struct platform_device *pdev)
> > > +{
> > > + struct device *dev = &pdev->dev;
> > > + struct mtk_i3c_master *master;
> > > + struct resource *res;
> > > + int ret, irqnr;
> > > +
> > > + master = devm_kzalloc(dev, sizeof(*master), GFP_KERNEL);
> > > + if (!master)
> > > + return -ENOMEM;
> > > +
> > > + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "main");
> > > + master->regs = devm_ioremap_resource(dev, res);
> > > + if (IS_ERR(master->regs))
> > > + return PTR_ERR(master->regs);
> > > +
> > > + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
> > > + master->dma_regs = devm_ioremap_resource(dev, res);
> > > + if (IS_ERR(master->dma_regs))
> > > + return PTR_ERR(master->dma_regs);
> > > +
> > > + irqnr = platform_get_irq(pdev, 0);
> > > + if (irqnr < 0)
> > > + return irqnr;
> > > +
> > > + ret = devm_request_irq(dev, irqnr, mtk_i3c_master_irq,
> > > +IRQF_TRIGGER_NONE, DRV_NAME, master);
> > > + if (ret < 0) {
> > > + dev_err(dev, "Request I3C IRQ %d fail\n", irqnr);
> > > + return ret;
> > > + }
> > > +
> > > + ret = of_property_read_u32(pdev->dev.of_node, "clock-div",
> > > +&master->clk_src_div);
> > 
> > You say in one comment that this clock divider is fixed in HW but might
> > change on a per-SoC basis. If that's the case, you should get rid of
> > this clock-div prop and attach the divider to the compatible (using an
> > mtk_i3c_master_variant struct that contains a divider field).
> > 
> 
> ok, I will attach the divider to the compatible.
> 
I have rechecked your comment, maybe I have misunderstood what you mean.
"clock-div" changes according to i2c source clock, different project may
change i2c source clock, The previous dt-binding may be misleading, I
will modify it.

> > > + if (ret < 0)
> > > + return -EINVAL;
> > > +
> > > + spin_lock_init(&master->xferqueue.lock);
> > > + INIT_LIST_HEAD(&master->xferqueue.list);
> > > +
> > > + if (dma_set_mask(dev, DMA_BIT_MASK(33))) {
> > > + dev_err(dev, "dma_set_mask return error.\n");
> > > + return -EINVAL;
> > > + }
> > > +
> > > + master->clk_main = devm_clk_get(dev, "main");
> > > + if (IS_ERR(master->clk_main)) {
> > > + dev_err(dev, "cannot get main clock\n");
> > > + return PTR_ERR(master->clk_main);
> > > + }
> > > + master->clk_dma = devm_clk_get(dev, "dma");
> > > + if (IS_ERR(master->clk_dma)) {
> > > + dev_err(dev, "cannot get dma clock\n");
> > > + return PTR_ERR(master->clk_dma);
> > > + }
> > > +
> > > + master->clk_arb = devm_clk_get_optional(dev, "arb");
> > > + if (IS_ERR(master->clk_arb))
> > > + return PTR_ERR(master->clk_arb);
> > > +
> > > + ret = mtk_i3c_master_clock_enable(master);
> > > + if (ret) {
> > > + dev_err(dev, "clock enable failed!\n");
> > > + return ret;
> > > + }
> > > +
> > > + master->dev = dev;
> > > + platform_set_drvdata(pdev, master);
> > > +
> > > + ret = i3c_master_register(&master->mas_ctrler, dev,
> > > +   &mtk_i3c_master_ops, false);
> > > + if (ret) {
> > > + dev_err(dev, "Failed to add i3c bus to i3c core\n");
> > > + mtk_i3c_master_clock_disable(master);
> > > + return ret;
> > > + }
> > > +
> > > + return 0;
> > > +}
> 




[PATCH 2/2] i2c: mediatek: Add i2c AC timing adjust support

2019-06-11 Thread Qii Wang
This patch adds some I2C timing registers to meet I2C spec, it
configures these registers according to information passed via DT.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c |   94 ++-
 1 file changed, 82 insertions(+), 12 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 745b0d0..f4bf753 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -134,6 +134,12 @@ enum I2C_REGS_OFFSET {
OFFSET_TRANSFER_LEN_AUX,
OFFSET_CLOCK_DIV,
OFFSET_LTIMING,
+   OFFSET_SCL_HIGH_LOW_RATIO,
+   OFFSET_HS_SCL_HIGH_LOW_RATIO,
+   OFFSET_SCL_MIS_COMP_POINT,
+   OFFSET_STA_STO_AC_TIMING,
+   OFFSET_HS_STA_STO_AC_TIMING,
+   OFFSET_SDA_TIMING,
 };
 
 static const u16 mt_i2c_regs_v1[] = {
@@ -161,6 +167,12 @@ enum I2C_REGS_OFFSET {
[OFFSET_DEBUGCTRL] = 0x68,
[OFFSET_TRANSFER_LEN_AUX] = 0x6c,
[OFFSET_CLOCK_DIV] = 0x70,
+   [OFFSET_SCL_HIGH_LOW_RATIO] = 0x74,
+   [OFFSET_HS_SCL_HIGH_LOW_RATIO] = 0x78,
+   [OFFSET_SCL_MIS_COMP_POINT] = 0x7C,
+   [OFFSET_STA_STO_AC_TIMING] = 0x80,
+   [OFFSET_HS_STA_STO_AC_TIMING] = 0x84,
+   [OFFSET_SDA_TIMING] = 0x88,
 };
 
 static const u16 mt_i2c_regs_v2[] = {
@@ -179,9 +191,11 @@ enum I2C_REGS_OFFSET {
[OFFSET_HS] = 0x30,
[OFFSET_IO_CONFIG] = 0x34,
[OFFSET_FIFO_ADDR_CLR] = 0x38,
+   [OFFSET_SDA_TIMING] = 0x3c,
[OFFSET_TRANSFER_LEN_AUX] = 0x44,
[OFFSET_CLOCK_DIV] = 0x48,
[OFFSET_SOFTRESET] = 0x50,
+   [OFFSET_SCL_MIS_COMP_POINT] = 0x90,
[OFFSET_DEBUGSTAT] = 0xe0,
[OFFSET_DEBUGCTRL] = 0xe8,
[OFFSET_FIFO_STAT] = 0xf4,
@@ -202,6 +216,17 @@ struct mtk_i2c_compatible {
unsigned char ltiming_adjust: 1;
 };
 
+struct mtk_i2c_ac_timing {
+   u16 ext;
+   u16 inter_clk_div;
+   u16 scl_hl_ratio;
+   u16 hs_scl_hl_ratio;
+   u16 scl_mis_comp;
+   u16 sta_stop;
+   u16 hs_sta_stop;
+   u16 sda_timing;
+};
+
 struct mtk_i2c {
struct i2c_adapter adap;/* i2c host adapter */
struct device *dev;
@@ -226,6 +251,7 @@ struct mtk_i2c {
u16 ltiming_reg;
unsigned char auto_restart;
bool ignore_restart_irq;
+   struct mtk_i2c_ac_timing ac_timing;
const struct mtk_i2c_compatible *dev_comp;
 };
 
@@ -403,13 +429,40 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
if (i2c->dev_comp->dcm)
mtk_i2c_writew(i2c, I2C_DCM_DISABLE, OFFSET_DCM_EN);
 
-   if (i2c->dev_comp->timing_adjust)
-   mtk_i2c_writew(i2c, I2C_DEFAULT_CLK_DIV - 1, OFFSET_CLOCK_DIV);
-
mtk_i2c_writew(i2c, i2c->timing_reg, OFFSET_TIMING);
mtk_i2c_writew(i2c, i2c->high_speed_reg, OFFSET_HS);
-   if (i2c->dev_comp->ltiming_adjust)
-   mtk_i2c_writew(i2c, i2c->ltiming_reg, OFFSET_LTIMING);
+
+   if (i2c->dev_comp->timing_adjust) {
+   mtk_i2c_writew(i2c, i2c->ac_timing.ext, OFFSET_EXT_CONF);
+   mtk_i2c_writew(i2c, i2c->ac_timing.inter_clk_div - 1,
+  OFFSET_CLOCK_DIV);
+   mtk_i2c_writew(i2c, i2c->ac_timing.scl_mis_comp,
+  OFFSET_SCL_MIS_COMP_POINT);
+   mtk_i2c_writew(i2c, i2c->ac_timing.sda_timing,
+  OFFSET_SDA_TIMING);
+
+   if (i2c->dev_comp->ltiming_adjust) {
+   mtk_i2c_writew(i2c, i2c->timing_reg -
+  i2c->ac_timing.scl_hl_ratio,
+  OFFSET_TIMING);
+   mtk_i2c_writew(i2c, i2c->high_speed_reg -
+  ((i2c->ac_timing.hs_scl_hl_ratio) << 8),
+  OFFSET_HS);
+   mtk_i2c_writew(i2c, i2c->ltiming_reg +
+  ((i2c->ac_timing.hs_scl_hl_ratio) << 9) +
+  i2c->ac_timing.scl_hl_ratio,
+  OFFSET_LTIMING);
+   } else {
+   mtk_i2c_writew(i2c, i2c->ac_timing.scl_hl_ratio,
+  OFFSET_SCL_HIGH_LOW_RATIO);
+   mtk_i2c_writew(i2c, i2c->ac_timing.hs_scl_hl_ratio,
+  OFFSET_HS_SCL_HIGH_LOW_RATIO);
+   mtk_i2c_writew(i2c, i2c->ac_timing.sta_stop,
+  OFFSET_STA_STO_AC_TIMING);
+   mtk_i2c_writew(i2c, i2c->ac_timing.hs_sta_stop,
+  OFFSET_HS_STA_STO_AC_TIMING);
+   }
+   }
 
/* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */
if (i2c->have_pmic)
@@ -592,12 +645,6 @@ stat

[PATCH 0/2] Add support for AC timing adjustment

2019-06-11 Thread Qii Wang
This series are based on 5.2-rc1, we provide two patches to
support AC timing adjustment.

Qii Wang (2):
  dt-bindings: i2c: Add MediaTek i2c AC timing binding
  i2c: mediatek: Add i2c AC timing adjust support

 .../devicetree/bindings/i2c/i2c-mt65xx.txt |   11 +++
 drivers/i2c/busses/i2c-mt65xx.c|   94 +---
 2 files changed, 93 insertions(+), 12 deletions(-)

-- 
1.7.9.5


[PATCH 1/2] dt-bindings: i2c: Add MediaTek i2c AC timing binding

2019-06-11 Thread Qii Wang
Add i2c AC timing binding to binding file. It can give the AC
timing parameters to meet I2C specification at different speed.

Signed-off-by: Qii Wang 
---
 .../devicetree/bindings/i2c/i2c-mt65xx.txt |   11 +++
 1 file changed, 11 insertions(+)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt 
b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
index 68f6d73..0f92813 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mt65xx.txt
@@ -30,6 +30,7 @@ Optional properties:
   - mediatek,have-pmic: platform can control i2c form special pmic side.
 Only mt6589 and mt8135 support this feature.
   - mediatek,use-push-pull: IO config use push-pull mode.
+  - ac-timing: give some AC timing parameters to meet i2c spec fully.
 
 Example:
 
@@ -43,5 +44,15 @@ Example:
clock-div = <16>;
clocks = <&i2c0_ck>, <&ap_dma_ck>;
clock-names = "main", "dma";
+   ac-timing =  /bits/ 16 <
+   0x8001  /* 0:ext */
+   0x0005  /* 1:inter_clk_div */
+   0x0102  /* 2:scl_hl_ratio */
+   0x0102  /* 3:hs_scl_hl_ratio */
+   0x0002  /* 4:scl_mis_comp */
+   0x0002  /* 5:sta_stop */
+   0x0002  /* 6:hs_sta_stop */
+   0x0002  /* 7:sda_timing */
+   >;
};
 
-- 
1.7.9.5



Re: [PATCH 2/2] i3c: master: Add driver for MediaTek IP

2019-06-04 Thread Qii Wang
On Tue, 2019-06-04 at 09:58 +0200, Boris Brezillon wrote:
> On Mon, 3 Jun 2019 11:51:03 +0800
> Qii Wang  wrote:
> 
> 
> > +static int mtk_i3c_master_probe(struct platform_device *pdev)
> > +{
> > +   struct device *dev = &pdev->dev;
> > +   struct mtk_i3c_master *master;
> > +   struct resource *res;
> > +   int ret, irqnr;
> > +
> > +   master = devm_kzalloc(dev, sizeof(*master), GFP_KERNEL);
> > +   if (!master)
> > +   return -ENOMEM;
> > +
> > +   res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "main");
> > +   master->regs = devm_ioremap_resource(dev, res);
> > +   if (IS_ERR(master->regs))
> > +   return PTR_ERR(master->regs);
> > +
> > +   res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
> > +   master->dma_regs = devm_ioremap_resource(dev, res);
> > +   if (IS_ERR(master->dma_regs))
> > +   return PTR_ERR(master->dma_regs);
> > +
> > +   irqnr = platform_get_irq(pdev, 0);
> > +   if (irqnr < 0)
> > +   return irqnr;
> > +
> > +   ret = devm_request_irq(dev, irqnr, mtk_i3c_master_irq,
> > +  IRQF_TRIGGER_NONE, DRV_NAME, master);
> > +   if (ret < 0) {
> > +   dev_err(dev, "Request I3C IRQ %d fail\n", irqnr);
> > +   return ret;
> > +   }
> > +
> > +   ret = of_property_read_u32(pdev->dev.of_node, "clock-div",
> > +  &master->clk_src_div);
> 
> You say in one comment that this clock divider is fixed in HW but might
> change on a per-SoC basis. If that's the case, you should get rid of
> this clock-div prop and attach the divider to the compatible (using an
> mtk_i3c_master_variant struct that contains a divider field).
> 

ok, I will attach the divider to the compatible.

> > +   if (ret < 0)
> > +   return -EINVAL;
> > +
> > +   spin_lock_init(&master->xferqueue.lock);
> > +   INIT_LIST_HEAD(&master->xferqueue.list);
> > +
> > +   if (dma_set_mask(dev, DMA_BIT_MASK(33))) {
> > +   dev_err(dev, "dma_set_mask return error.\n");
> > +   return -EINVAL;
> > +   }
> > +
> > +   master->clk_main = devm_clk_get(dev, "main");
> > +   if (IS_ERR(master->clk_main)) {
> > +   dev_err(dev, "cannot get main clock\n");
> > +   return PTR_ERR(master->clk_main);
> > +   }
> > +   master->clk_dma = devm_clk_get(dev, "dma");
> > +   if (IS_ERR(master->clk_dma)) {
> > +   dev_err(dev, "cannot get dma clock\n");
> > +   return PTR_ERR(master->clk_dma);
> > +   }
> > +
> > +   master->clk_arb = devm_clk_get_optional(dev, "arb");
> > +   if (IS_ERR(master->clk_arb))
> > +   return PTR_ERR(master->clk_arb);
> > +
> > +   ret = mtk_i3c_master_clock_enable(master);
> > +   if (ret) {
> > +   dev_err(dev, "clock enable failed!\n");
> > +   return ret;
> > +   }
> > +
> > +   master->dev = dev;
> > +   platform_set_drvdata(pdev, master);
> > +
> > +   ret = i3c_master_register(&master->mas_ctrler, dev,
> > + &mtk_i3c_master_ops, false);
> > +   if (ret) {
> > +   dev_err(dev, "Failed to add i3c bus to i3c core\n");
> > +   mtk_i3c_master_clock_disable(master);
> > +   return ret;
> > +   }
> > +
> > +   return 0;
> > +}




[PATCH 1/2] dt-bindings: i3c: Document MediaTek I3C master bindings

2019-06-02 Thread Qii Wang
Document MediaTek I3C master DT bindings.

Signed-off-by: Qii Wang 
---
 .../devicetree/bindings/i3c/mtk,i3c-master.txt |   50 
 1 file changed, 50 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt

diff --git a/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt 
b/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
new file mode 100644
index 000..89ec380
--- /dev/null
+++ b/Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
@@ -0,0 +1,50 @@
+Bindings for MediaTek I3C master block
+=
+
+Required properties:
+
+- compatible: shall be "mediatek,i3c-master"
+- reg: physical base address of the controller and apdma base, length of
+  memory mapped region.
+- reg-names: should be "main" for controller and "dma" for apdma.
+- interrupts: interrupt number to the cpu.
+- clock-div: the fixed value for frequency divider of clock source in i3c
+  module. Each IC may be different.
+- clocks: clock name from clock manager.
+- clock-names: must include "main" and "dma".
+
+Mandatory properties defined by the generic binding (see
+Documentation/devicetree/bindings/i3c/i3c.txt for more details):
+
+- #address-cells: shall be set to 3
+- #size-cells: shall be set to 0
+
+Optional properties defined by the generic binding (see
+Documentation/devicetree/bindings/i3c/i3c.txt for more details):
+
+- i2c-scl-hz
+- i3c-scl-hz
+
+I3C device connected on the bus follow the generic description (see
+Documentation/devicetree/bindings/i3c/i3c.txt for more details).
+
+Example:
+
+   i3c0: i3c@1100d000 {
+   compatible = "mediatek,i3c-master";
+   reg = <0x1100d000 0x100>,
+ <0x11000300 0x80>;
+   reg-names = "main", "dma";
+   interrupts = ;
+   clock-div = <16>;
+   clocks = <&i3c0_ck>, <&ap_dma_ck>;
+   clock-names = "main", "dma";
+   #address-cells = <1>;
+   #size-cells = <0>;
+   i2c-scl-hz = <10>;
+
+   nunchuk: nunchuk@52 {
+   compatible = "nintendo,nunchuk";
+   reg = <0x52 0x8010 0>;
+   };
+   };
-- 
1.7.9.5



[PATCH 2/2] i3c: master: Add driver for MediaTek IP

2019-06-02 Thread Qii Wang
Add a driver for MediaTek I3C master IP.

Signed-off-by: Qii Wang 
---
 drivers/i3c/master/Kconfig  |   10 +
 drivers/i3c/master/Makefile |1 +
 drivers/i3c/master/i3c-master-mtk.c | 1246 +++
 3 files changed, 1257 insertions(+)
 create mode 100644 drivers/i3c/master/i3c-master-mtk.c

diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig
index 26c6b58..acc00d9 100644
--- a/drivers/i3c/master/Kconfig
+++ b/drivers/i3c/master/Kconfig
@@ -20,3 +20,13 @@ config DW_I3C_MASTER
 
  This driver can also be built as a module.  If so, the module
  will be called dw-i3c-master.
+
+config MTK_I3C_MASTER
+   tristate "MediaTek I3C master driver"
+   depends on I3C
+   depends on HAS_IOMEM
+   depends on !(ALPHA || PARISC)
+   help
+ This selects the MediaTek(R) I3C master controller driver.
+ If you want to use MediaTek(R) I3C interface, say Y here.
+ If unsure, say N or M.
diff --git a/drivers/i3c/master/Makefile b/drivers/i3c/master/Makefile
index fc53939..fe7ccf5 100644
--- a/drivers/i3c/master/Makefile
+++ b/drivers/i3c/master/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_CDNS_I3C_MASTER)  += i3c-master-cdns.o
 obj-$(CONFIG_DW_I3C_MASTER)+= dw-i3c-master.o
+obj-$(CONFIG_MTK_I3C_MASTER)   += i3c-master-mtk.o
diff --git a/drivers/i3c/master/i3c-master-mtk.c 
b/drivers/i3c/master/i3c-master-mtk.c
new file mode 100644
index 000..a209bb6
--- /dev/null
+++ b/drivers/i3c/master/i3c-master-mtk.c
@@ -0,0 +1,1246 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Design Systems Inc.
+ *
+ * Author: Qii Wang 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DRV_NAME   "i3c-master-mtk"
+
+#define SLAVE_ADDR 0x04
+#define INTR_MASK  0x08
+#define INTR_STAT  0x0c
+#define INTR_TRANSAC_COMP  BIT(0)
+#define INTR_ACKERRGENMASK(2, 1)
+#define INTR_ARB_LOST  BIT(3)
+#define INTR_RS_MULTI  BIT(4)
+#define INTR_MAS_ERR   BIT(8)
+#define INTR_ALL   (INTR_MAS_ERR | INTR_ARB_LOST |\
+   INTR_ACKERR | INTR_TRANSAC_COMP)
+
+#define CONTROL0x10
+#define CONTROL_WRAPPERBIT(0)
+#define CONTROL_RS BIT(1)
+#define CONTROL_DMA_EN BIT(2)
+#define CONTROL_CLK_EXT_EN BIT(3)
+#define CONTROL_DIR_CHANGE  BIT(4)
+#define CONTROL_ACKERR_DET_EN  BIT(5)
+#define CONTROL_LEN_CHANGE BIT(6)
+#define CONTROL_DMAACK_EN  BIT(8)
+#define CONTROL_ASYNC_MODE BIT(9)
+
+#define TRANSFER_LEN   0x14
+#define TRANSAC_LEN0x18
+#define TRANSAC_LEN_WRRD   0x0002
+#define TRANS_ONE_LEN  0x0001
+
+#define DELAY_LEN  0x1c
+#define DELAY_LEN_DEFAULT  0x000a
+
+#define TIMING 0x20
+#define TIMING_VALUE(sample_cnt, step_cnt) ({ \
+   typeof(sample_cnt) sample_cnt_ = (sample_cnt); \
+   typeof(step_cnt) step_cnt_ = (step_cnt); \
+   (((sample_cnt_) << 8) | (step_cnt_)); \
+})
+
+#define START  0x24
+#define START_EN   BIT(0)
+#define START_MUL_TRIG BIT(14)
+#define START_MUL_CNFG BIT(15)
+
+#define EXT_CONF   0x28
+#define EXT_CONF_DEFAULT   0x0a1f
+
+#define LTIMING0x2c
+#define LTIMING_VALUE(sample_cnt, step_cnt) ({ \
+   typeof(sample_cnt) sample_cnt_ = (sample_cnt); \
+   typeof(step_cnt) step_cnt_ = (step_cnt); \
+   (((sample_cnt_) << 6) | (step_cnt_) | \
+   ((sample_cnt_) << 12) | ((step_cnt_) << 9)); \
+})
+
+#define HS 0x30
+#define HS_CLR_VALUE   0x
+#define HS_DEFAULT_VALUE   0x0083
+#define HS_VALUE(sample_cnt, step_cnt) ({ \
+   typeof(sample_cnt) sample_cnt_ = (sample_cnt); \
+   typeof(step_cnt) step_cnt_ = (step_cnt); \
+   (HS_DEFAULT_VALUE | \
+   ((sample_cnt_) << 12) | ((step_cnt_) << 8)); \
+})
+
+#define IO_CONFIG  0x34
+#define IO_CONFIG_PUSH_PULL0x
+
+#define FIFO_ADDR_CLR  0x38
+#define FIFO_CLR   0x0003
+
+#define MCU_INTR   0x40
+#define MCU_INTR_ENBIT(0)
+
+#define TRANSFER_LEN_AUX   0x44
+#define CLOCK_DIV  0x48
+#define CLOCK_DIV_DEFAULT  ((INTER_CLK_DIV - 1) << 8 |\
+   (INTER_CLK_DIV - 1))
+
+#define SOFTRESET  0x50
+#define SOFT_RST   BIT(0)
+
+#define TRAFFIC0x54
+#define TRAFFIC_DAA_EN BIT(4)
+#define TRAFFIC_TBIT   BIT(7)
+#define TRAFFIC_HEAD_ONLY  BIT(9)
+#define TRAFFIC_SKIP_SLV_ADDR  BIT(10)
+#define TRAFFIC_HANDOFFBIT(14)
+
+#define DEF_DA 0x68
+#define DEF_DAA_SLV_PARITY BIT(8)
+
+#define SHAPE  0x6

[PATCH 0/2] Add MediaTek I3C master controller driver

2019-06-02 Thread Qii Wang
This series are based on 5.2-rc1, we provide two patches to
support MediaTek I3C master controller.

Qii Wang (2):
  dt-bindings: i3c: Document MediaTek I3C master bindings
  i3c: master: Add driver for MediaTek IP

 .../devicetree/bindings/i3c/mtk,i3c-master.txt |   50 +
 drivers/i3c/master/Kconfig |   10 +
 drivers/i3c/master/Makefile|1 +
 drivers/i3c/master/i3c-master-mtk.c| 1246 
 4 files changed, 1307 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i3c/mtk,i3c-master.txt
 create mode 100644 drivers/i3c/master/i3c-master-mtk.c

-- 
1.7.9.5


[PATCH RESEND v6 1/6] i2c: mediatek: Add offsets array for new i2c registers

2019-04-02 Thread Qii Wang
New i2c registers would have different offsets, so we use different
offsets array to distinguish different i2c registers version.

Signed-off-by: Qii Wang 
Reviewed-by: Matthias Brugger 
---
 drivers/i2c/busses/i2c-mt65xx.c |  163 +--
 1 file changed, 104 insertions(+), 59 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 684d651..be36018 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -106,34 +106,62 @@ enum mtk_trans_op {
 };
 
 enum I2C_REGS_OFFSET {
-   OFFSET_DATA_PORT = 0x0,
-   OFFSET_SLAVE_ADDR = 0x04,
-   OFFSET_INTR_MASK = 0x08,
-   OFFSET_INTR_STAT = 0x0c,
-   OFFSET_CONTROL = 0x10,
-   OFFSET_TRANSFER_LEN = 0x14,
-   OFFSET_TRANSAC_LEN = 0x18,
-   OFFSET_DELAY_LEN = 0x1c,
-   OFFSET_TIMING = 0x20,
-   OFFSET_START = 0x24,
-   OFFSET_EXT_CONF = 0x28,
-   OFFSET_FIFO_STAT = 0x30,
-   OFFSET_FIFO_THRESH = 0x34,
-   OFFSET_FIFO_ADDR_CLR = 0x38,
-   OFFSET_IO_CONFIG = 0x40,
-   OFFSET_RSV_DEBUG = 0x44,
-   OFFSET_HS = 0x48,
-   OFFSET_SOFTRESET = 0x50,
-   OFFSET_DCM_EN = 0x54,
-   OFFSET_PATH_DIR = 0x60,
-   OFFSET_DEBUGSTAT = 0x64,
-   OFFSET_DEBUGCTRL = 0x68,
-   OFFSET_TRANSFER_LEN_AUX = 0x6c,
-   OFFSET_CLOCK_DIV = 0x70,
+   OFFSET_DATA_PORT,
+   OFFSET_SLAVE_ADDR,
+   OFFSET_INTR_MASK,
+   OFFSET_INTR_STAT,
+   OFFSET_CONTROL,
+   OFFSET_TRANSFER_LEN,
+   OFFSET_TRANSAC_LEN,
+   OFFSET_DELAY_LEN,
+   OFFSET_TIMING,
+   OFFSET_START,
+   OFFSET_EXT_CONF,
+   OFFSET_FIFO_STAT,
+   OFFSET_FIFO_THRESH,
+   OFFSET_FIFO_ADDR_CLR,
+   OFFSET_IO_CONFIG,
+   OFFSET_RSV_DEBUG,
+   OFFSET_HS,
+   OFFSET_SOFTRESET,
+   OFFSET_DCM_EN,
+   OFFSET_PATH_DIR,
+   OFFSET_DEBUGSTAT,
+   OFFSET_DEBUGCTRL,
+   OFFSET_TRANSFER_LEN_AUX,
+   OFFSET_CLOCK_DIV,
+};
+
+static const u16 mt_i2c_regs_v1[] = {
+   [OFFSET_DATA_PORT] = 0x0,
+   [OFFSET_SLAVE_ADDR] = 0x4,
+   [OFFSET_INTR_MASK] = 0x8,
+   [OFFSET_INTR_STAT] = 0xc,
+   [OFFSET_CONTROL] = 0x10,
+   [OFFSET_TRANSFER_LEN] = 0x14,
+   [OFFSET_TRANSAC_LEN] = 0x18,
+   [OFFSET_DELAY_LEN] = 0x1c,
+   [OFFSET_TIMING] = 0x20,
+   [OFFSET_START] = 0x24,
+   [OFFSET_EXT_CONF] = 0x28,
+   [OFFSET_FIFO_STAT] = 0x30,
+   [OFFSET_FIFO_THRESH] = 0x34,
+   [OFFSET_FIFO_ADDR_CLR] = 0x38,
+   [OFFSET_IO_CONFIG] = 0x40,
+   [OFFSET_RSV_DEBUG] = 0x44,
+   [OFFSET_HS] = 0x48,
+   [OFFSET_SOFTRESET] = 0x50,
+   [OFFSET_DCM_EN] = 0x54,
+   [OFFSET_PATH_DIR] = 0x60,
+   [OFFSET_DEBUGSTAT] = 0x64,
+   [OFFSET_DEBUGCTRL] = 0x68,
+   [OFFSET_TRANSFER_LEN_AUX] = 0x6c,
+   [OFFSET_CLOCK_DIV] = 0x70,
 };
 
 struct mtk_i2c_compatible {
const struct i2c_adapter_quirks *quirks;
+   const u16 *regs;
unsigned char pmic_i2c: 1;
unsigned char dcm: 1;
unsigned char auto_restart: 1;
@@ -181,6 +209,7 @@ struct mtk_i2c {
 };
 
 static const struct mtk_i2c_compatible mt2712_compat = {
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 1,
@@ -191,6 +220,7 @@ struct mtk_i2c {
 
 static const struct mtk_i2c_compatible mt6577_compat = {
.quirks = &mt6577_i2c_quirks,
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 0,
@@ -201,6 +231,7 @@ struct mtk_i2c {
 
 static const struct mtk_i2c_compatible mt6589_compat = {
.quirks = &mt6577_i2c_quirks,
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 1,
.dcm = 0,
.auto_restart = 0,
@@ -211,6 +242,7 @@ struct mtk_i2c {
 
 static const struct mtk_i2c_compatible mt7622_compat = {
.quirks = &mt7622_i2c_quirks,
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 1,
@@ -220,6 +252,7 @@ struct mtk_i2c {
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 1,
@@ -238,6 +271,17 @@ struct mtk_i2c {
 };
 MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
 
+static u16 mtk_i2c_readw(struct mtk_i2c *i2c, enum I2C_REGS_OFFSET reg)
+{
+   return readw(i2c->base + i2c->dev_comp->regs[reg]);
+}
+
+static void mtk_i2c_writew(struct mtk_i2c *i2c, u16 val,
+  enum I2C_REGS_OFFSET reg)
+{
+   writew(val, i2c->base + i2c->dev_comp->regs[reg]);
+}
+
 static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
 {
int ret;
@@ -278,31 +322,31 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 {
u16 control_reg;
 
-   writew(I2C_SOFT_RST, i2c->base + OFFSET_SOFTRESET);
+   mtk_i2c_writew(i2c, I2C_SOFT_RST, OFFSET_SOFTRESET);
 
/* Set ioconfig */
if (i2c->u

[PATCH RESEND v6 3/6] i2c: mediatek: Add arb clock in i2c driver

2019-04-02 Thread Qii Wang
When two i2c controllers are internally connected to the same
GPIO pins, the arb clock is needed to ensure that the waveforms
do not interfere with each other. And we also need to enable
the interrupt to find arb lost, old i2c controllers also have
the bit.

Signed-off-by: Qii Wang 
Reviewed-by: Nicolas Boichat 
---
 drivers/i2c/busses/i2c-mt65xx.c |   25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index be36018..1a7235e 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -35,6 +35,7 @@
 #include 
 
 #define I2C_RS_TRANSFER(1 << 4)
+#define I2C_ARB_LOST   (1 << 3)
 #define I2C_HS_NACKERR (1 << 2)
 #define I2C_ACKERR (1 << 1)
 #define I2C_TRANSAC_COMP   (1 << 0)
@@ -181,6 +182,7 @@ struct mtk_i2c {
struct clk *clk_main;   /* main clock for i2c bus */
struct clk *clk_dma;/* DMA clock for i2c via DMA */
struct clk *clk_pmic;   /* PMIC clock for i2c from PMIC */
+   struct clk *clk_arb;/* Arbitrator clock for i2c */
bool have_pmic; /* can use i2c pins from PMIC */
bool use_push_pull; /* IO config push-pull mode */
 
@@ -299,8 +301,18 @@ static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
if (ret)
goto err_pmic;
}
+
+   if (i2c->clk_arb) {
+   ret = clk_prepare_enable(i2c->clk_arb);
+   if (ret)
+   goto err_arb;
+   }
+
return 0;
 
+err_arb:
+   if (i2c->have_pmic)
+   clk_disable_unprepare(i2c->clk_pmic);
 err_pmic:
clk_disable_unprepare(i2c->clk_main);
 err_main:
@@ -311,6 +323,9 @@ static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
 
 static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
 {
+   if (i2c->clk_arb)
+   clk_disable_unprepare(i2c->clk_arb);
+
if (i2c->have_pmic)
clk_disable_unprepare(i2c->clk_pmic);
 
@@ -519,13 +534,13 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
struct i2c_msg *msgs,
 
/* Clear interrupt status */
mtk_i2c_writew(i2c, restart_flag | I2C_HS_NACKERR | I2C_ACKERR |
-  I2C_TRANSAC_COMP, OFFSET_INTR_STAT);
+   I2C_ARB_LOST | I2C_TRANSAC_COMP, OFFSET_INTR_STAT);
 
mtk_i2c_writew(i2c, I2C_FIFO_ADDR_CLR, OFFSET_FIFO_ADDR_CLR);
 
/* Enable interrupt */
mtk_i2c_writew(i2c, restart_flag | I2C_HS_NACKERR | I2C_ACKERR |
-  I2C_TRANSAC_COMP, OFFSET_INTR_MASK);
+   I2C_ARB_LOST | I2C_TRANSAC_COMP, OFFSET_INTR_MASK);
 
/* Set transfer and transaction len */
if (i2c->op == I2C_MASTER_WRRD) {
@@ -659,7 +674,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
 
/* Clear interrupt mask */
mtk_i2c_writew(i2c, ~(restart_flag | I2C_HS_NACKERR | I2C_ACKERR |
-  I2C_TRANSAC_COMP), OFFSET_INTR_MASK);
+   I2C_ARB_LOST | I2C_TRANSAC_COMP), OFFSET_INTR_MASK);
 
if (i2c->op == I2C_MASTER_WR) {
dma_unmap_single(i2c->dev, wpaddr,
@@ -884,6 +899,10 @@ static int mtk_i2c_probe(struct platform_device *pdev)
return PTR_ERR(i2c->clk_dma);
}
 
+   i2c->clk_arb = devm_clk_get(&pdev->dev, "arb");
+   if (IS_ERR(i2c->clk_arb))
+   i2c->clk_arb = NULL;
+
clk = i2c->clk_main;
if (i2c->have_pmic) {
i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic");
-- 
1.7.9.5



[PATCH RESEND v6 4/6] i2c: mediatek: Add i2c and apdma sync in i2c driver

2019-04-02 Thread Qii Wang
When i2c and apdma use different source clocks, we should enable
synchronization between them.

Signed-off-by: Qii Wang 
Reviewed-by: Nicolas Boichat 
---
 drivers/i2c/busses/i2c-mt65xx.c |   11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 1a7235e..6137ad7 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -77,6 +77,8 @@
 #define I2C_CONTROL_DIR_CHANGE  (0x1 << 4)
 #define I2C_CONTROL_ACKERR_DET_EN   (0x1 << 5)
 #define I2C_CONTROL_TRANSFER_LEN_CHANGE (0x1 << 6)
+#define I2C_CONTROL_DMAACK_EN   (0x1 << 8)
+#define I2C_CONTROL_ASYNC_MODE  (0x1 << 9)
 #define I2C_CONTROL_WRAPPER (0x1 << 0)
 
 #define I2C_DRV_NAME   "i2c-mt65xx"
@@ -169,6 +171,7 @@ struct mtk_i2c_compatible {
unsigned char aux_len_reg: 1;
unsigned char support_33bits: 1;
unsigned char timing_adjust: 1;
+   unsigned char dma_sync: 1;
 };
 
 struct mtk_i2c {
@@ -218,6 +221,7 @@ struct mtk_i2c {
.aux_len_reg = 1,
.support_33bits = 1,
.timing_adjust = 1,
+   .dma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt6577_compat = {
@@ -229,6 +233,7 @@ struct mtk_i2c {
.aux_len_reg = 0,
.support_33bits = 0,
.timing_adjust = 0,
+   .dma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
@@ -240,6 +245,7 @@ struct mtk_i2c {
.aux_len_reg = 0,
.support_33bits = 0,
.timing_adjust = 0,
+   .dma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt7622_compat = {
@@ -251,6 +257,7 @@ struct mtk_i2c {
.aux_len_reg = 1,
.support_33bits = 0,
.timing_adjust = 0,
+   .dma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
@@ -261,6 +268,7 @@ struct mtk_i2c {
.aux_len_reg = 1,
.support_33bits = 1,
.timing_adjust = 0,
+   .dma_sync = 0,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
@@ -360,6 +368,9 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 
control_reg = I2C_CONTROL_ACKERR_DET_EN |
  I2C_CONTROL_CLK_EXT_EN | I2C_CONTROL_DMA_EN;
+   if (i2c->dev_comp->dma_sync)
+   control_reg |= I2C_CONTROL_DMAACK_EN | I2C_CONTROL_ASYNC_MODE;
+
mtk_i2c_writew(i2c, control_reg, OFFSET_CONTROL);
mtk_i2c_writew(i2c, I2C_DELAY_LEN, OFFSET_DELAY_LEN);
 
-- 
1.7.9.5



[PATCH RESEND v6 6/6] dts: arm64: mt8183: Add I2C nodes

2019-04-02 Thread Qii Wang
This patch adds i2c nodes for I2C controllers

Signed-off-by: Qii Wang 
---
 arch/arm64/boot/dts/mediatek/mt8183.dtsi |  192 ++
 1 file changed, 192 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi 
b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index 75c4881..3dde2be 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -16,6 +16,21 @@
#address-cells = <2>;
#size-cells = <2>;
 
+   aliases {
+   i2c0 = &i2c0;
+   i2c1 = &i2c1;
+   i2c2 = &i2c2;
+   i2c3 = &i2c3;
+   i2c4 = &i2c4;
+   i2c5 = &i2c5;
+   i2c6 = &i2c6;
+   i2c7 = &i2c7;
+   i2c8 = &i2c8;
+   i2c9 = &i2c9;
+   i2c10 = &i2c10;
+   i2c11 = &i2c11;
+   };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -299,6 +314,183 @@
status = "disabled";
};
 
+   i2c6: i2c@11005000 {
+   compatible = "mediatek,mt8183-i2c";
+   reg = <0 0x11005000 0 0x1000>,
+   <0 0x11000600 0 0x80>;
+   interrupts = ;
+   clocks = <&infracfg CLK_INFRA_I2C6>,
+<&infracfg CLK_INFRA_AP_DMA>;
+   clock-names = "main", "dma";
+   clock-div = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   status = "disabled";
+   };
+
+   i2c0: i2c@11007000 {
+   compatible = "mediatek,mt8183-i2c";
+   reg = <0 0x11007000 0 0x1000>,
+   <0 0x1180 0 0x80>;
+   interrupts = ;
+   clocks = <&infracfg CLK_INFRA_I2C0>,
+<&infracfg CLK_INFRA_AP_DMA>;
+   clock-names = "main", "dma";
+   clock-div = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   status = "disabled";
+   };
+
+   i2c4: i2c@11008000 {
+   compatible = "mediatek,mt8183-i2c";
+   id = <4>;
+   reg = <0 0x11008000 0 0x1000>,
+   <0 0x11000100 0 0x80>;
+   interrupts = ;
+   clocks = <&infracfg CLK_INFRA_I2C1>,
+<&infracfg CLK_INFRA_AP_DMA>,
+<&infracfg CLK_INFRA_I2C1_ARBITER>;
+   clock-names = "main", "dma","arb";
+   clock-div = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   status = "disabled";
+   };
+
+   i2c2: i2c@11009000 {
+   compatible = "mediatek,mt8183-i2c";
+   reg = <0 0x11009000 0 0x1000>,
+   <0 0x11000280 0 0x80>;
+   interrupts = ;
+   clocks = <&infracfg CLK_INFRA_I2C2>,
+<&infracfg CLK_INFRA_AP_DMA>,
+<&infracfg CLK_INFRA_I2C2_ARBITER>;
+   clock-names = "main", "dma", "arb";
+   clock-div = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   status = "disabled";
+   };
+
+   i2c3: i2c@1100f000 {
+   compatible = "mediatek,mt8183-i2c";
+   reg = <0 0x1100f000 0 0x1000>,
+   <0 0x11000400 0 0x80>;
+   interrupts = ;
+   clocks = <&infracfg CLK_INFRA_I2C3>,
+<&infracfg CLK_INFRA_AP_DMA>;
+   clock-names = "main", "dma";
+   clock-div = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   status = "disabled";
+   };
+
+   i2c1: i2c@11011000 {
+   compatible = &qu

[PATCH RESEND v6 2/6] dt-bindings: i2c: Add Mediatek MT8183 i2c binding

2019-04-02 Thread Qii Wang
Add MT8183 i2c binding to binding file. Compare to MT2712 i2c
controller, MT8183 has different registers, offsets, and clock.

Signed-off-by: Qii Wang 
Reviewed-by: Matthias Brugger 
---
 Documentation/devicetree/bindings/i2c/i2c-mtk.txt |4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mtk.txt 
b/Documentation/devicetree/bindings/i2c/i2c-mtk.txt
index ee4c324..b052f29 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mtk.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mtk.txt
@@ -12,13 +12,15 @@ Required properties:
   "mediatek,mt7623-i2c", "mediatek,mt6577-i2c": for MediaTek MT7623
   "mediatek,mt7629-i2c", "mediatek,mt2712-i2c": for MediaTek MT7629
   "mediatek,mt8173-i2c": for MediaTek MT8173
+  "mediatek,mt8183-i2c": for MediaTek MT8183
   - reg: physical base address of the controller and dma base, length of memory
 mapped region.
   - interrupts: interrupt number to the cpu.
   - clock-div: the fixed value for frequency divider of clock source in i2c
 module. Each IC may be different.
   - clocks: clock name from clock manager
-  - clock-names: Must include "main" and "dma", if enable have-pmic need 
include
+  - clock-names: Must include "main" and "dma", "arb" is for multi-master that
+one bus has more than two i2c controllers, if enable have-pmic need include
 "pmic" extra.
 
 Optional properties:
-- 
1.7.9.5



[PATCH RESEND v6 0/6] add i2c support for mt8183

2019-04-02 Thread Qii Wang
This series are based on 5.1-rc1 and the patch
https://patchwork.kernel.org/patch/10856987/(for dts)
We provide six patches to support mt8183 IC.

Main changes compared to v5:
--add i2c controller nodes in mt8183.dtsi
--add a note that old i2c controllers also have I2C_ARB_LOST bit
--add a flag(ltiming_adjust) to avoid unnecessary settings
--add Reviewed-by from Rob Herring, Nicolas and Matthias

Main changes compared to v4:
--modify the commit of arb clock dt-binding
--split a patch(3/3) into three(3/5 4/5 5/5)

Main changes compared to v3:
--remove the patches which have been applied to for-next
--remove i2c fallback for i3c controller 

Main changes compared to v2:
--update commit message
--add Reviewed-by from Rob Herring, Nicolas and Sean

Main changes compared to v1:
--remove useless dt-binding for mt7629
--split a patch into two(2/6 3/6)
--muti-user feature was dropped

Qii Wang (6):
  i2c: mediatek: Add offsets array for new i2c registers
  dt-bindings: i2c: Add Mediatek MT8183 i2c binding
  i2c: mediatek: Add arb clock in i2c driver
  i2c: mediatek: Add i2c and apdma sync in i2c driver
  i2c: mediatek: Add i2c support for MediaTek MT8183
  dts: arm64: mt8183: Add I2C nodes

 Documentation/devicetree/bindings/i2c/i2c-mtk.txt |4 +-
 arch/arm64/boot/dts/mediatek/mt8183.dtsi  |  192 
 drivers/i2c/busses/i2c-mt65xx.c   |  255 -
 3 files changed, 389 insertions(+), 62 deletions(-)

-- 
1.7.9.5


[PATCH RESEND v6 5/6] i2c: mediatek: Add i2c support for MediaTek MT8183

2019-04-02 Thread Qii Wang
Add i2c compatible for MT8183. Compare to MT2712 i2c controller,
MT8183 has different register offsets. Ltiming_reg is added to
adjust low width of SCL. Arb clock and dma_sync are needed.

Signed-off-by: Qii Wang 
Reviewed-by: Nicolas Boichat 
---
 drivers/i2c/busses/i2c-mt65xx.c |   62 +--
 1 file changed, 60 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 6137ad7..745b0d0 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -133,6 +133,7 @@ enum I2C_REGS_OFFSET {
OFFSET_DEBUGCTRL,
OFFSET_TRANSFER_LEN_AUX,
OFFSET_CLOCK_DIV,
+   OFFSET_LTIMING,
 };
 
 static const u16 mt_i2c_regs_v1[] = {
@@ -162,6 +163,32 @@ enum I2C_REGS_OFFSET {
[OFFSET_CLOCK_DIV] = 0x70,
 };
 
+static const u16 mt_i2c_regs_v2[] = {
+   [OFFSET_DATA_PORT] = 0x0,
+   [OFFSET_SLAVE_ADDR] = 0x4,
+   [OFFSET_INTR_MASK] = 0x8,
+   [OFFSET_INTR_STAT] = 0xc,
+   [OFFSET_CONTROL] = 0x10,
+   [OFFSET_TRANSFER_LEN] = 0x14,
+   [OFFSET_TRANSAC_LEN] = 0x18,
+   [OFFSET_DELAY_LEN] = 0x1c,
+   [OFFSET_TIMING] = 0x20,
+   [OFFSET_START] = 0x24,
+   [OFFSET_EXT_CONF] = 0x28,
+   [OFFSET_LTIMING] = 0x2c,
+   [OFFSET_HS] = 0x30,
+   [OFFSET_IO_CONFIG] = 0x34,
+   [OFFSET_FIFO_ADDR_CLR] = 0x38,
+   [OFFSET_TRANSFER_LEN_AUX] = 0x44,
+   [OFFSET_CLOCK_DIV] = 0x48,
+   [OFFSET_SOFTRESET] = 0x50,
+   [OFFSET_DEBUGSTAT] = 0xe0,
+   [OFFSET_DEBUGCTRL] = 0xe8,
+   [OFFSET_FIFO_STAT] = 0xf4,
+   [OFFSET_FIFO_THRESH] = 0xf8,
+   [OFFSET_DCM_EN] = 0xf88,
+};
+
 struct mtk_i2c_compatible {
const struct i2c_adapter_quirks *quirks;
const u16 *regs;
@@ -172,6 +199,7 @@ struct mtk_i2c_compatible {
unsigned char support_33bits: 1;
unsigned char timing_adjust: 1;
unsigned char dma_sync: 1;
+   unsigned char ltiming_adjust: 1;
 };
 
 struct mtk_i2c {
@@ -195,6 +223,7 @@ struct mtk_i2c {
enum mtk_trans_op op;
u16 timing_reg;
u16 high_speed_reg;
+   u16 ltiming_reg;
unsigned char auto_restart;
bool ignore_restart_irq;
const struct mtk_i2c_compatible *dev_comp;
@@ -222,6 +251,7 @@ struct mtk_i2c {
.support_33bits = 1,
.timing_adjust = 1,
.dma_sync = 0,
+   .ltiming_adjust = 0,
 };
 
 static const struct mtk_i2c_compatible mt6577_compat = {
@@ -234,6 +264,7 @@ struct mtk_i2c {
.support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
+   .ltiming_adjust = 0,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
@@ -246,6 +277,7 @@ struct mtk_i2c {
.support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
+   .ltiming_adjust = 0,
 };
 
 static const struct mtk_i2c_compatible mt7622_compat = {
@@ -258,6 +290,7 @@ struct mtk_i2c {
.support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
+   .ltiming_adjust = 0,
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
@@ -269,6 +302,19 @@ struct mtk_i2c {
.support_33bits = 1,
.timing_adjust = 0,
.dma_sync = 0,
+   .ltiming_adjust = 0,
+};
+
+static const struct mtk_i2c_compatible mt8183_compat = {
+   .regs = mt_i2c_regs_v2,
+   .pmic_i2c = 0,
+   .dcm = 0,
+   .auto_restart = 1,
+   .aux_len_reg = 1,
+   .support_33bits = 1,
+   .timing_adjust = 1,
+   .dma_sync = 1,
+   .ltiming_adjust = 1,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
@@ -277,6 +323,7 @@ struct mtk_i2c {
{ .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
{ .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
{ .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
+   { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
{}
 };
 MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
@@ -361,6 +408,8 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 
mtk_i2c_writew(i2c, i2c->timing_reg, OFFSET_TIMING);
mtk_i2c_writew(i2c, i2c->high_speed_reg, OFFSET_HS);
+   if (i2c->dev_comp->ltiming_adjust)
+   mtk_i2c_writew(i2c, i2c->ltiming_reg, OFFSET_LTIMING);
 
/* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */
if (i2c->have_pmic)
@@ -460,6 +509,8 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned 
int parent_clk)
unsigned int clk_src;
unsigned int step_cnt;
unsigned int sample_cnt;
+   unsigned int l_step_cnt;
+   unsigned int l_sample_cnt;
unsigned int target_speed;
int ret;
 
@@ -469,11 +520,11 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, 
unsigned int parent_clk)
if (target_speed > MAX_FS_MODE_SPEED) {
/* Set ma

Re: [PATCH v6 6/6] dts: arm64: mt8183: Add I2C nodes

2019-03-11 Thread Qii Wang
On Mon, 2019-03-11 at 16:36 +0800, Nicolas Boichat wrote:
> On Mon, Mar 11, 2019 at 1:41 PM Qii Wang  wrote:
> >
> > This patch adds nodes for I2C controller.
> >
> > Signed-off-by: Qii Wang 
> > ---
> 
> This applies on top of some other uncommitted series, right? This is
> fine, but please say which one.
> 

https://patchwork.kernel.org/cover/10846715/
This series are based on 5.0-rc1(i2c/for-next) and these series
http://lists.infradead.org/pipermail/linux-mediatek/2019-February/017570.html
http://lists.infradead.org/pipermail/linux-mediatek/2019-February/017320.html

> >  arch/arm64/boot/dts/mediatek/mt8183.dtsi |  190 
> > ++
> >  1 file changed, 190 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi 
> > b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
> > index 165b859..f20f1af 100644
> > --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
> > +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
> > @@ -16,6 +16,21 @@
> > #address-cells = <2>;
> > #size-cells = <2>;
> >
> > +   aliases {
> > +   i2c0 = &i2c0;
> > +   i2c1 = &i2c1;
> > +   i2c2 = &i2c2;
> > +   i2c3 = &i2c3;
> > +   i2c4 = &i2c4;
> > +   i2c5 = &i2c5;
> > +   i2c6 = &i2c6;
> > +   i2c7 = &i2c7;
> > +   i2c8 = &i2c8;
> > +   i2c9 = &i2c9;
> > +   i2c10 = &i2c10;
> > +   i2c11 = &i2c11;
> > +   };
> > +
> > cpus {
> > #address-cells = <1>;
> > #size-cells = <0>;
> > @@ -268,6 +283,79 @@
> > status = "disabled";
> > };
> >
> > +   i2c6: i2c@11005000 {
> > +   compatible = "mediatek,mt8183-i2c";
> > +   reg = <0 0x11005000 0 0x1000>,
> > +   <0 0x11000600 0 0x80>;
> > +   interrupts = ;
> > +   clocks = <&infracfg CLK_INFRA_I2C6>,
> > +<&infracfg CLK_INFRA_AP_DMA>;
> > +   clock-names = "main", "dma";
> > +   clock-div = <1>;
> > +   #address-cells = <1>;
> > +   #size-cells = <0>;
> > +   status = "disabled";
> > +   };
> > +
> > +   i2c0: i2c@11007000 {
> > +   compatible = "mediatek,mt8183-i2c";
> > +   reg = <0 0x11007000 0 0x1000>,
> > +   <0 0x1180 0 0x80>;
> > +   interrupts = ;
> > +   clocks = <&infracfg CLK_INFRA_I2C0>,
> > +<&infracfg CLK_INFRA_AP_DMA>;
> > +   clock-names = "main", "dma";
> > +   clock-div = <1>;
> > +   #address-cells = <1>;
> > +   #size-cells = <0>;
> > +   status = "disabled";
> > +   };
> > +
> > +   i2c4: i2c@11008000 {
> > +   compatible = "mediatek,mt8183-i2c";
> > +   id = <4>;
> > +   reg = <0 0x11008000 0 0x1000>,
> > +   <0 0x11000100 0 0x80>;
> > +   interrupts = ;
> > +   clocks = <&infracfg CLK_INFRA_I2C1>,
> > +<&infracfg CLK_INFRA_AP_DMA>,
> > +<&infracfg CLK_INFRA_I2C1_ARBITER>;
> > +   clock-names = "main", "dma","arb";
> > +   clock-div = <1>;
> > +   #address-cells = <1>;
> > +   #size-cells = <0>;
> > +   status = "disabled";
> > +   };
> > +
> > +   i2c2: i2c@11009000 {
> > +   compatible = "mediatek,mt8183-i2c";
> > +   reg = <0 0x11009000 0 0x1000>,
> > +   <0 0x11000

[PATCH v6 0/6] add i2c support for mt8183

2019-03-10 Thread Qii Wang
This series are based on 5.0-rc1(i2c/for-next) and these series
http://lists.infradead.org/pipermail/linux-mediatek/2019-February/017570.html
http://lists.infradead.org/pipermail/linux-mediatek/2019-February/017320.html
http://lists.infradead.org/pipermail/linux-mediatek/2019-January/017196.html 

We provide six patches to support mt8183 IC.

Main changes compared to v5:
--add i2c controller nodes in mt8183.dtsi
--add a note that old i2c controllers also have I2C_ARB_LOST bit
--add a flag(ltiming_adjust) to avoid unnecessary settings
--add Reviewed-by from Rob Herring, Nicolas and Matthias

Main changes compared to v4:
--modify the commit of arb clock dt-binding
--split a patch(3/3) into three(3/5 4/5 5/5)

Main changes compared to v3:
--remove the patches which have been applied to for-next
--remove i2c fallback for i3c controller 

Main changes compared to v2:
--update commit message
--add Reviewed-by from Rob Herring, Nicolas and Sean

Main changes compared to v1:
--remove useless dt-binding for mt7629
--split a patch into two(2/6 3/6)
--muti-user feature was dropped

Qii Wang (6):
  i2c: mediatek: Add offsets array for new i2c registers
  dt-bindings: i2c: Add Mediatek MT8183 i2c binding
  i2c: mediatek: Add arb clock in i2c driver
  i2c: mediatek: Add i2c and apdma sync in i2c driver
  i2c: mediatek: Add i2c support for MediaTek MT8183
  dts: arm64: mt8183: Add I2C nodes

 Documentation/devicetree/bindings/i2c/i2c-mtk.txt |   4 +-
 arch/arm64/boot/dts/mediatek/mt8183.dtsi  | 190 
 drivers/i2c/busses/i2c-mt65xx.c   | 255 --
 3 files changed, 387 insertions(+), 62 deletions(-)

-- 
1.9.1


[PATCH v6 6/6] dts: arm64: mt8183: Add I2C nodes

2019-03-10 Thread Qii Wang
This patch adds nodes for I2C controller.

Signed-off-by: Qii Wang 
---
 arch/arm64/boot/dts/mediatek/mt8183.dtsi |  190 ++
 1 file changed, 190 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi 
b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
index 165b859..f20f1af 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
@@ -16,6 +16,21 @@
#address-cells = <2>;
#size-cells = <2>;
 
+   aliases {
+   i2c0 = &i2c0;
+   i2c1 = &i2c1;
+   i2c2 = &i2c2;
+   i2c3 = &i2c3;
+   i2c4 = &i2c4;
+   i2c5 = &i2c5;
+   i2c6 = &i2c6;
+   i2c7 = &i2c7;
+   i2c8 = &i2c8;
+   i2c9 = &i2c9;
+   i2c10 = &i2c10;
+   i2c11 = &i2c11;
+   };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -268,6 +283,79 @@
status = "disabled";
};
 
+   i2c6: i2c@11005000 {
+   compatible = "mediatek,mt8183-i2c";
+   reg = <0 0x11005000 0 0x1000>,
+   <0 0x11000600 0 0x80>;
+   interrupts = ;
+   clocks = <&infracfg CLK_INFRA_I2C6>,
+<&infracfg CLK_INFRA_AP_DMA>;
+   clock-names = "main", "dma";
+   clock-div = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   status = "disabled";
+   };
+
+   i2c0: i2c@11007000 {
+   compatible = "mediatek,mt8183-i2c";
+   reg = <0 0x11007000 0 0x1000>,
+   <0 0x1180 0 0x80>;
+   interrupts = ;
+   clocks = <&infracfg CLK_INFRA_I2C0>,
+<&infracfg CLK_INFRA_AP_DMA>;
+   clock-names = "main", "dma";
+   clock-div = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   status = "disabled";
+   };
+
+   i2c4: i2c@11008000 {
+   compatible = "mediatek,mt8183-i2c";
+   id = <4>;
+   reg = <0 0x11008000 0 0x1000>,
+   <0 0x11000100 0 0x80>;
+   interrupts = ;
+   clocks = <&infracfg CLK_INFRA_I2C1>,
+<&infracfg CLK_INFRA_AP_DMA>,
+<&infracfg CLK_INFRA_I2C1_ARBITER>;
+   clock-names = "main", "dma","arb";
+   clock-div = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   status = "disabled";
+   };
+
+   i2c2: i2c@11009000 {
+   compatible = "mediatek,mt8183-i2c";
+   reg = <0 0x11009000 0 0x1000>,
+   <0 0x11000280 0 0x80>;
+   interrupts = ;
+   clocks = <&infracfg CLK_INFRA_I2C2>,
+<&infracfg CLK_INFRA_AP_DMA>,
+<&infracfg CLK_INFRA_I2C2_ARBITER>;
+   clock-names = "main", "dma", "arb";
+   clock-div = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   status = "disabled";
+   };
+
+   i2c3: i2c@1100f000 {
+   compatible = "mediatek,mt8183-i2c";
+   reg = <0 0x1100f000 0 0x1000>,
+   <0 0x11000400 0 0x80>;
+   interrupts = ;
+   clocks = <&infracfg CLK_INFRA_I2C3>,
+<&infracfg CLK_INFRA_AP_DMA>;
+   clock-names = "main", "dma";
+   clock-div = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   status = "disabled";
+   };
+
spi0: spi@1100a000 {
compatible 

[PATCH v6 5/6] i2c: mediatek: Add i2c support for MediaTek MT8183

2019-03-10 Thread Qii Wang
Add i2c compatible for MT8183. Compare to MT2712 i2c controller,
MT8183 has different register offsets. Ltiming_reg is added to
adjust low width of SCL. Arb clock and dma_sync are needed.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c |   62 +--
 1 file changed, 60 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 6137ad7..745b0d0 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -133,6 +133,7 @@ enum I2C_REGS_OFFSET {
OFFSET_DEBUGCTRL,
OFFSET_TRANSFER_LEN_AUX,
OFFSET_CLOCK_DIV,
+   OFFSET_LTIMING,
 };
 
 static const u16 mt_i2c_regs_v1[] = {
@@ -162,6 +163,32 @@ enum I2C_REGS_OFFSET {
[OFFSET_CLOCK_DIV] = 0x70,
 };
 
+static const u16 mt_i2c_regs_v2[] = {
+   [OFFSET_DATA_PORT] = 0x0,
+   [OFFSET_SLAVE_ADDR] = 0x4,
+   [OFFSET_INTR_MASK] = 0x8,
+   [OFFSET_INTR_STAT] = 0xc,
+   [OFFSET_CONTROL] = 0x10,
+   [OFFSET_TRANSFER_LEN] = 0x14,
+   [OFFSET_TRANSAC_LEN] = 0x18,
+   [OFFSET_DELAY_LEN] = 0x1c,
+   [OFFSET_TIMING] = 0x20,
+   [OFFSET_START] = 0x24,
+   [OFFSET_EXT_CONF] = 0x28,
+   [OFFSET_LTIMING] = 0x2c,
+   [OFFSET_HS] = 0x30,
+   [OFFSET_IO_CONFIG] = 0x34,
+   [OFFSET_FIFO_ADDR_CLR] = 0x38,
+   [OFFSET_TRANSFER_LEN_AUX] = 0x44,
+   [OFFSET_CLOCK_DIV] = 0x48,
+   [OFFSET_SOFTRESET] = 0x50,
+   [OFFSET_DEBUGSTAT] = 0xe0,
+   [OFFSET_DEBUGCTRL] = 0xe8,
+   [OFFSET_FIFO_STAT] = 0xf4,
+   [OFFSET_FIFO_THRESH] = 0xf8,
+   [OFFSET_DCM_EN] = 0xf88,
+};
+
 struct mtk_i2c_compatible {
const struct i2c_adapter_quirks *quirks;
const u16 *regs;
@@ -172,6 +199,7 @@ struct mtk_i2c_compatible {
unsigned char support_33bits: 1;
unsigned char timing_adjust: 1;
unsigned char dma_sync: 1;
+   unsigned char ltiming_adjust: 1;
 };
 
 struct mtk_i2c {
@@ -195,6 +223,7 @@ struct mtk_i2c {
enum mtk_trans_op op;
u16 timing_reg;
u16 high_speed_reg;
+   u16 ltiming_reg;
unsigned char auto_restart;
bool ignore_restart_irq;
const struct mtk_i2c_compatible *dev_comp;
@@ -222,6 +251,7 @@ struct mtk_i2c {
.support_33bits = 1,
.timing_adjust = 1,
.dma_sync = 0,
+   .ltiming_adjust = 0,
 };
 
 static const struct mtk_i2c_compatible mt6577_compat = {
@@ -234,6 +264,7 @@ struct mtk_i2c {
.support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
+   .ltiming_adjust = 0,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
@@ -246,6 +277,7 @@ struct mtk_i2c {
.support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
+   .ltiming_adjust = 0,
 };
 
 static const struct mtk_i2c_compatible mt7622_compat = {
@@ -258,6 +290,7 @@ struct mtk_i2c {
.support_33bits = 0,
.timing_adjust = 0,
.dma_sync = 0,
+   .ltiming_adjust = 0,
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
@@ -269,6 +302,19 @@ struct mtk_i2c {
.support_33bits = 1,
.timing_adjust = 0,
.dma_sync = 0,
+   .ltiming_adjust = 0,
+};
+
+static const struct mtk_i2c_compatible mt8183_compat = {
+   .regs = mt_i2c_regs_v2,
+   .pmic_i2c = 0,
+   .dcm = 0,
+   .auto_restart = 1,
+   .aux_len_reg = 1,
+   .support_33bits = 1,
+   .timing_adjust = 1,
+   .dma_sync = 1,
+   .ltiming_adjust = 1,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
@@ -277,6 +323,7 @@ struct mtk_i2c {
{ .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
{ .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
{ .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
+   { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
{}
 };
 MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
@@ -361,6 +408,8 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 
mtk_i2c_writew(i2c, i2c->timing_reg, OFFSET_TIMING);
mtk_i2c_writew(i2c, i2c->high_speed_reg, OFFSET_HS);
+   if (i2c->dev_comp->ltiming_adjust)
+   mtk_i2c_writew(i2c, i2c->ltiming_reg, OFFSET_LTIMING);
 
/* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */
if (i2c->have_pmic)
@@ -460,6 +509,8 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned 
int parent_clk)
unsigned int clk_src;
unsigned int step_cnt;
unsigned int sample_cnt;
+   unsigned int l_step_cnt;
+   unsigned int l_sample_cnt;
unsigned int target_speed;
int ret;
 
@@ -469,11 +520,11 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, 
unsigned int parent_clk)
if (target_speed > MAX_FS_MODE_SPEED) {
/* Set master code speed register */

[PATCH v6 1/6] i2c: mediatek: Add offsets array for new i2c registers

2019-03-10 Thread Qii Wang
New i2c registers would have different offsets, so we use different
offsets array to distinguish different i2c registers version.

Signed-off-by: Qii Wang 
Reviewed-by: Matthias Brugger 
---
 drivers/i2c/busses/i2c-mt65xx.c |  163 +--
 1 file changed, 104 insertions(+), 59 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 684d651..be36018 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -106,34 +106,62 @@ enum mtk_trans_op {
 };
 
 enum I2C_REGS_OFFSET {
-   OFFSET_DATA_PORT = 0x0,
-   OFFSET_SLAVE_ADDR = 0x04,
-   OFFSET_INTR_MASK = 0x08,
-   OFFSET_INTR_STAT = 0x0c,
-   OFFSET_CONTROL = 0x10,
-   OFFSET_TRANSFER_LEN = 0x14,
-   OFFSET_TRANSAC_LEN = 0x18,
-   OFFSET_DELAY_LEN = 0x1c,
-   OFFSET_TIMING = 0x20,
-   OFFSET_START = 0x24,
-   OFFSET_EXT_CONF = 0x28,
-   OFFSET_FIFO_STAT = 0x30,
-   OFFSET_FIFO_THRESH = 0x34,
-   OFFSET_FIFO_ADDR_CLR = 0x38,
-   OFFSET_IO_CONFIG = 0x40,
-   OFFSET_RSV_DEBUG = 0x44,
-   OFFSET_HS = 0x48,
-   OFFSET_SOFTRESET = 0x50,
-   OFFSET_DCM_EN = 0x54,
-   OFFSET_PATH_DIR = 0x60,
-   OFFSET_DEBUGSTAT = 0x64,
-   OFFSET_DEBUGCTRL = 0x68,
-   OFFSET_TRANSFER_LEN_AUX = 0x6c,
-   OFFSET_CLOCK_DIV = 0x70,
+   OFFSET_DATA_PORT,
+   OFFSET_SLAVE_ADDR,
+   OFFSET_INTR_MASK,
+   OFFSET_INTR_STAT,
+   OFFSET_CONTROL,
+   OFFSET_TRANSFER_LEN,
+   OFFSET_TRANSAC_LEN,
+   OFFSET_DELAY_LEN,
+   OFFSET_TIMING,
+   OFFSET_START,
+   OFFSET_EXT_CONF,
+   OFFSET_FIFO_STAT,
+   OFFSET_FIFO_THRESH,
+   OFFSET_FIFO_ADDR_CLR,
+   OFFSET_IO_CONFIG,
+   OFFSET_RSV_DEBUG,
+   OFFSET_HS,
+   OFFSET_SOFTRESET,
+   OFFSET_DCM_EN,
+   OFFSET_PATH_DIR,
+   OFFSET_DEBUGSTAT,
+   OFFSET_DEBUGCTRL,
+   OFFSET_TRANSFER_LEN_AUX,
+   OFFSET_CLOCK_DIV,
+};
+
+static const u16 mt_i2c_regs_v1[] = {
+   [OFFSET_DATA_PORT] = 0x0,
+   [OFFSET_SLAVE_ADDR] = 0x4,
+   [OFFSET_INTR_MASK] = 0x8,
+   [OFFSET_INTR_STAT] = 0xc,
+   [OFFSET_CONTROL] = 0x10,
+   [OFFSET_TRANSFER_LEN] = 0x14,
+   [OFFSET_TRANSAC_LEN] = 0x18,
+   [OFFSET_DELAY_LEN] = 0x1c,
+   [OFFSET_TIMING] = 0x20,
+   [OFFSET_START] = 0x24,
+   [OFFSET_EXT_CONF] = 0x28,
+   [OFFSET_FIFO_STAT] = 0x30,
+   [OFFSET_FIFO_THRESH] = 0x34,
+   [OFFSET_FIFO_ADDR_CLR] = 0x38,
+   [OFFSET_IO_CONFIG] = 0x40,
+   [OFFSET_RSV_DEBUG] = 0x44,
+   [OFFSET_HS] = 0x48,
+   [OFFSET_SOFTRESET] = 0x50,
+   [OFFSET_DCM_EN] = 0x54,
+   [OFFSET_PATH_DIR] = 0x60,
+   [OFFSET_DEBUGSTAT] = 0x64,
+   [OFFSET_DEBUGCTRL] = 0x68,
+   [OFFSET_TRANSFER_LEN_AUX] = 0x6c,
+   [OFFSET_CLOCK_DIV] = 0x70,
 };
 
 struct mtk_i2c_compatible {
const struct i2c_adapter_quirks *quirks;
+   const u16 *regs;
unsigned char pmic_i2c: 1;
unsigned char dcm: 1;
unsigned char auto_restart: 1;
@@ -181,6 +209,7 @@ struct mtk_i2c {
 };
 
 static const struct mtk_i2c_compatible mt2712_compat = {
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 1,
@@ -191,6 +220,7 @@ struct mtk_i2c {
 
 static const struct mtk_i2c_compatible mt6577_compat = {
.quirks = &mt6577_i2c_quirks,
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 0,
@@ -201,6 +231,7 @@ struct mtk_i2c {
 
 static const struct mtk_i2c_compatible mt6589_compat = {
.quirks = &mt6577_i2c_quirks,
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 1,
.dcm = 0,
.auto_restart = 0,
@@ -211,6 +242,7 @@ struct mtk_i2c {
 
 static const struct mtk_i2c_compatible mt7622_compat = {
.quirks = &mt7622_i2c_quirks,
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 1,
@@ -220,6 +252,7 @@ struct mtk_i2c {
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 1,
@@ -238,6 +271,17 @@ struct mtk_i2c {
 };
 MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
 
+static u16 mtk_i2c_readw(struct mtk_i2c *i2c, enum I2C_REGS_OFFSET reg)
+{
+   return readw(i2c->base + i2c->dev_comp->regs[reg]);
+}
+
+static void mtk_i2c_writew(struct mtk_i2c *i2c, u16 val,
+  enum I2C_REGS_OFFSET reg)
+{
+   writew(val, i2c->base + i2c->dev_comp->regs[reg]);
+}
+
 static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
 {
int ret;
@@ -278,31 +322,31 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 {
u16 control_reg;
 
-   writew(I2C_SOFT_RST, i2c->base + OFFSET_SOFTRESET);
+   mtk_i2c_writew(i2c, I2C_SOFT_RST, OFFSET_SOFTRESET);
 
/* Set ioconfig */
if (i2c->u

[PATCH v6 3/6] i2c: mediatek: Add arb clock in i2c driver

2019-03-10 Thread Qii Wang
When two i2c controllers are internally connected to the same
GPIO pins, the arb clock is needed to ensure that the waveforms
do not interfere with each other. And we also need to enable
the interrupt to find arb lost, old i2c controllers also have
the bit.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c |   25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index be36018..1a7235e 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -35,6 +35,7 @@
 #include 
 
 #define I2C_RS_TRANSFER(1 << 4)
+#define I2C_ARB_LOST   (1 << 3)
 #define I2C_HS_NACKERR (1 << 2)
 #define I2C_ACKERR (1 << 1)
 #define I2C_TRANSAC_COMP   (1 << 0)
@@ -181,6 +182,7 @@ struct mtk_i2c {
struct clk *clk_main;   /* main clock for i2c bus */
struct clk *clk_dma;/* DMA clock for i2c via DMA */
struct clk *clk_pmic;   /* PMIC clock for i2c from PMIC */
+   struct clk *clk_arb;/* Arbitrator clock for i2c */
bool have_pmic; /* can use i2c pins from PMIC */
bool use_push_pull; /* IO config push-pull mode */
 
@@ -299,8 +301,18 @@ static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
if (ret)
goto err_pmic;
}
+
+   if (i2c->clk_arb) {
+   ret = clk_prepare_enable(i2c->clk_arb);
+   if (ret)
+   goto err_arb;
+   }
+
return 0;
 
+err_arb:
+   if (i2c->have_pmic)
+   clk_disable_unprepare(i2c->clk_pmic);
 err_pmic:
clk_disable_unprepare(i2c->clk_main);
 err_main:
@@ -311,6 +323,9 @@ static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
 
 static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
 {
+   if (i2c->clk_arb)
+   clk_disable_unprepare(i2c->clk_arb);
+
if (i2c->have_pmic)
clk_disable_unprepare(i2c->clk_pmic);
 
@@ -519,13 +534,13 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
struct i2c_msg *msgs,
 
/* Clear interrupt status */
mtk_i2c_writew(i2c, restart_flag | I2C_HS_NACKERR | I2C_ACKERR |
-  I2C_TRANSAC_COMP, OFFSET_INTR_STAT);
+   I2C_ARB_LOST | I2C_TRANSAC_COMP, OFFSET_INTR_STAT);
 
mtk_i2c_writew(i2c, I2C_FIFO_ADDR_CLR, OFFSET_FIFO_ADDR_CLR);
 
/* Enable interrupt */
mtk_i2c_writew(i2c, restart_flag | I2C_HS_NACKERR | I2C_ACKERR |
-  I2C_TRANSAC_COMP, OFFSET_INTR_MASK);
+   I2C_ARB_LOST | I2C_TRANSAC_COMP, OFFSET_INTR_MASK);
 
/* Set transfer and transaction len */
if (i2c->op == I2C_MASTER_WRRD) {
@@ -659,7 +674,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
 
/* Clear interrupt mask */
mtk_i2c_writew(i2c, ~(restart_flag | I2C_HS_NACKERR | I2C_ACKERR |
-  I2C_TRANSAC_COMP), OFFSET_INTR_MASK);
+   I2C_ARB_LOST | I2C_TRANSAC_COMP), OFFSET_INTR_MASK);
 
if (i2c->op == I2C_MASTER_WR) {
dma_unmap_single(i2c->dev, wpaddr,
@@ -884,6 +899,10 @@ static int mtk_i2c_probe(struct platform_device *pdev)
return PTR_ERR(i2c->clk_dma);
}
 
+   i2c->clk_arb = devm_clk_get(&pdev->dev, "arb");
+   if (IS_ERR(i2c->clk_arb))
+   i2c->clk_arb = NULL;
+
clk = i2c->clk_main;
if (i2c->have_pmic) {
i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic");
-- 
1.7.9.5



[PATCH v6 4/6] i2c: mediatek: Add i2c and apdma sync in i2c driver

2019-03-10 Thread Qii Wang
When i2c and apdma use different source clocks, we should enable
synchronization between them.

Signed-off-by: Qii Wang 
Reviewed-by: Nicolas Boichat 
---
 drivers/i2c/busses/i2c-mt65xx.c |   11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 1a7235e..6137ad7 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -77,6 +77,8 @@
 #define I2C_CONTROL_DIR_CHANGE  (0x1 << 4)
 #define I2C_CONTROL_ACKERR_DET_EN   (0x1 << 5)
 #define I2C_CONTROL_TRANSFER_LEN_CHANGE (0x1 << 6)
+#define I2C_CONTROL_DMAACK_EN   (0x1 << 8)
+#define I2C_CONTROL_ASYNC_MODE  (0x1 << 9)
 #define I2C_CONTROL_WRAPPER (0x1 << 0)
 
 #define I2C_DRV_NAME   "i2c-mt65xx"
@@ -169,6 +171,7 @@ struct mtk_i2c_compatible {
unsigned char aux_len_reg: 1;
unsigned char support_33bits: 1;
unsigned char timing_adjust: 1;
+   unsigned char dma_sync: 1;
 };
 
 struct mtk_i2c {
@@ -218,6 +221,7 @@ struct mtk_i2c {
.aux_len_reg = 1,
.support_33bits = 1,
.timing_adjust = 1,
+   .dma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt6577_compat = {
@@ -229,6 +233,7 @@ struct mtk_i2c {
.aux_len_reg = 0,
.support_33bits = 0,
.timing_adjust = 0,
+   .dma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
@@ -240,6 +245,7 @@ struct mtk_i2c {
.aux_len_reg = 0,
.support_33bits = 0,
.timing_adjust = 0,
+   .dma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt7622_compat = {
@@ -251,6 +257,7 @@ struct mtk_i2c {
.aux_len_reg = 1,
.support_33bits = 0,
.timing_adjust = 0,
+   .dma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
@@ -261,6 +268,7 @@ struct mtk_i2c {
.aux_len_reg = 1,
.support_33bits = 1,
.timing_adjust = 0,
+   .dma_sync = 0,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
@@ -360,6 +368,9 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 
control_reg = I2C_CONTROL_ACKERR_DET_EN |
  I2C_CONTROL_CLK_EXT_EN | I2C_CONTROL_DMA_EN;
+   if (i2c->dev_comp->dma_sync)
+   control_reg |= I2C_CONTROL_DMAACK_EN | I2C_CONTROL_ASYNC_MODE;
+
mtk_i2c_writew(i2c, control_reg, OFFSET_CONTROL);
mtk_i2c_writew(i2c, I2C_DELAY_LEN, OFFSET_DELAY_LEN);
 
-- 
1.7.9.5



[PATCH v6 2/6] dt-bindings: i2c: Add Mediatek MT8183 i2c binding

2019-03-10 Thread Qii Wang
Add MT8183 i2c binding to binding file. Compare to MT2712 i2c
controller, MT8183 has different registers, offsets, and clock.

Signed-off-by: Qii Wang 
Reviewed-by: Rob Herring 
---
 Documentation/devicetree/bindings/i2c/i2c-mtk.txt |4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mtk.txt 
b/Documentation/devicetree/bindings/i2c/i2c-mtk.txt
index ee4c324..b052f29 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mtk.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mtk.txt
@@ -12,13 +12,15 @@ Required properties:
   "mediatek,mt7623-i2c", "mediatek,mt6577-i2c": for MediaTek MT7623
   "mediatek,mt7629-i2c", "mediatek,mt2712-i2c": for MediaTek MT7629
   "mediatek,mt8173-i2c": for MediaTek MT8173
+  "mediatek,mt8183-i2c": for MediaTek MT8183
   - reg: physical base address of the controller and dma base, length of memory
 mapped region.
   - interrupts: interrupt number to the cpu.
   - clock-div: the fixed value for frequency divider of clock source in i2c
 module. Each IC may be different.
   - clocks: clock name from clock manager
-  - clock-names: Must include "main" and "dma", if enable have-pmic need 
include
+  - clock-names: Must include "main" and "dma", "arb" is for multi-master that
+one bus has more than two i2c controllers, if enable have-pmic need include
 "pmic" extra.
 
 Optional properties:
-- 
1.7.9.5



Re: [PATCH v5 5/5] i2c: mediatek: Add i2c support for MediaTek MT8183

2019-03-06 Thread Qii Wang
On Wed, 2019-03-06 at 18:52 +0800, Nicolas Boichat wrote:
> On Tue, Feb 26, 2019 at 9:11 PM Qii Wang  wrote:
> >
> > Add i2c compatible for MT8183. Compare to MT2712 i2c controller,
> > MT8183 has different register offsets. Ltiming_reg is added to
> > adjust low width of SCL. Arb clock and dma_sync are needed.
> >
> > Signed-off-by: Qii Wang 
> > ---
> >  drivers/i2c/busses/i2c-mt65xx.c |   53 
> > +--
> >  1 file changed, 51 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/i2c/busses/i2c-mt65xx.c 
> > b/drivers/i2c/busses/i2c-mt65xx.c
> > index 75d88e1..82eedbd 100644
> > --- a/drivers/i2c/busses/i2c-mt65xx.c
> > +++ b/drivers/i2c/busses/i2c-mt65xx.c
> > @@ -133,6 +133,8 @@ enum I2C_REGS_OFFSET {
> > OFFSET_DEBUGCTRL,
> > OFFSET_TRANSFER_LEN_AUX,
> > OFFSET_CLOCK_DIV,
> > +   /* MT8183 only regs */
> > +   OFFSET_LTIMING,
> >  };
> >
> >  static const u16 mt_i2c_regs_v1[] = {
> > @@ -162,6 +164,32 @@ enum I2C_REGS_OFFSET {
> > [OFFSET_CLOCK_DIV] = 0x70,
> >  };
> >
> > +static const u16 mt_i2c_regs_v2[] = {
> > +   [OFFSET_DATA_PORT] = 0x0,
> > +   [OFFSET_SLAVE_ADDR] = 0x4,
> > +   [OFFSET_INTR_MASK] = 0x8,
> > +   [OFFSET_INTR_STAT] = 0xc,
> > +   [OFFSET_CONTROL] = 0x10,
> > +   [OFFSET_TRANSFER_LEN] = 0x14,
> > +   [OFFSET_TRANSAC_LEN] = 0x18,
> > +   [OFFSET_DELAY_LEN] = 0x1c,
> > +   [OFFSET_TIMING] = 0x20,
> > +   [OFFSET_START] = 0x24,
> > +   [OFFSET_EXT_CONF] = 0x28,
> > +   [OFFSET_LTIMING] = 0x2c,
> > +   [OFFSET_HS] = 0x30,
> > +   [OFFSET_IO_CONFIG] = 0x34,
> > +   [OFFSET_FIFO_ADDR_CLR] = 0x38,
> > +   [OFFSET_TRANSFER_LEN_AUX] = 0x44,
> > +   [OFFSET_CLOCK_DIV] = 0x48,
> > +   [OFFSET_SOFTRESET] = 0x50,
> > +   [OFFSET_DEBUGSTAT] = 0xe0,
> > +   [OFFSET_DEBUGCTRL] = 0xe8,
> > +   [OFFSET_FIFO_STAT] = 0xf4,
> > +   [OFFSET_FIFO_THRESH] = 0xf8,
> > +   [OFFSET_DCM_EN] = 0xf88,
> > +};
> > +
> >  struct mtk_i2c_compatible {
> > const struct i2c_adapter_quirks *quirks;
> > const u16 *regs;
> > @@ -195,6 +223,7 @@ struct mtk_i2c {
> > enum mtk_trans_op op;
> > u16 timing_reg;
> > u16 high_speed_reg;
> > +   u16 ltiming_reg;
> > unsigned char auto_restart;
> > bool ignore_restart_irq;
> > const struct mtk_i2c_compatible *dev_comp;
> > @@ -271,12 +300,24 @@ struct mtk_i2c {
> > .dma_sync = 0,
> >  };
> >
> > +static const struct mtk_i2c_compatible mt8183_compat = {
> > +   .regs = mt_i2c_regs_v2,
> > +   .pmic_i2c = 0,
> > +   .dcm = 0,
> > +   .auto_restart = 1,
> > +   .aux_len_reg = 1,
> > +   .support_33bits = 1,
> > +   .timing_adjust = 1,
> > +   .dma_sync = 1,
> > +};
> > +
> >  static const struct of_device_id mtk_i2c_of_match[] = {
> > { .compatible = "mediatek,mt2712-i2c", .data = &mt2712_compat },
> > { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
> > { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
> > { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
> > { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
> > +   { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
> > {}
> >  };
> >  MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
> > @@ -361,6 +402,8 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
> >
> > mtk_i2c_writew(i2c, i2c->timing_reg, OFFSET_TIMING);
> > mtk_i2c_writew(i2c, i2c->high_speed_reg, OFFSET_HS);
> > +   if (i2c->dev_comp->regs == mt_i2c_regs_v2)
> > +   mtk_i2c_writew(i2c, i2c->ltiming_reg, OFFSET_LTIMING);
> 
> Matthias wasn't super happy with this. One way is to add another field
> in the compatible string. Another may be to have
> mt_i2c_regs_v1[OFFSET_LTIMING] point at, say 0x (#define this as
> I2C_REG_INVALID or something), and test for that?
> 
> Either way would scale better if we end up with more than 2 versions
> of the register set in the future.
> 

ok, I will add a flag(ltiming_adjust) in mtk_i2c_compatible.

> > /* If use i2c pin from PMIC m

Re: [PATCH v5 3/5] i2c: mediatek: Add arb clock in i2c driver

2019-03-06 Thread Qii Wang
On Wed, 2019-03-06 at 18:49 +0800, Nicolas Boichat wrote:
> One thing I missed from Matthias' comment on v4:
> https://patchwork.kernel.org/patch/10822083/
> 
> On Wed, Mar 6, 2019 at 6:44 PM Nicolas Boichat  wrote:
> >
> > On Tue, Feb 26, 2019 at 9:11 PM Qii Wang  wrote:
> > >
> > > When two i2c controllers are internally connected to the same
> > > GPIO pins, the arb clock is needed to ensure that the waveforms
> > > do not interfere with each other.
> > >
> > > Signed-off-by: Qii Wang 
> >
> > Reviewed-by: Nicolas Boichat 
> >
> > > ---
> > >  drivers/i2c/busses/i2c-mt65xx.c |   25 ++---
> > >  1 file changed, 22 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/i2c/busses/i2c-mt65xx.c 
> > > b/drivers/i2c/busses/i2c-mt65xx.c
> > > index 428ac99..14d6b38 100644
> > > --- a/drivers/i2c/busses/i2c-mt65xx.c
> > > +++ b/drivers/i2c/busses/i2c-mt65xx.c
> > > @@ -35,6 +35,7 @@
> > >  #include 
> > >
> > >  #define I2C_RS_TRANSFER(1 << 4)
> > > +#define I2C_ARB_LOST   (1 << 3)
> > >  #define I2C_HS_NACKERR (1 << 2)
> > >  #define I2C_ACKERR (1 << 1)
> > >  #define I2C_TRANSAC_COMP   (1 << 0)
> > > @@ -181,6 +182,7 @@ struct mtk_i2c {
> > > struct clk *clk_main;   /* main clock for i2c bus */
> > > struct clk *clk_dma;/* DMA clock for i2c via DMA */
> > > struct clk *clk_pmic;   /* PMIC clock for i2c from PMIC */
> > > +   struct clk *clk_arb;/* Arbitrator clock for i2c */
> > > bool have_pmic; /* can use i2c pins from PMIC */
> > > bool use_push_pull; /* IO config push-pull mode */
> > >
> > > @@ -299,8 +301,18 @@ static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
> > > if (ret)
> > > goto err_pmic;
> > > }
> > > +
> > > +   if (i2c->clk_arb) {
> > > +   ret = clk_prepare_enable(i2c->clk_arb);
> > > +   if (ret)
> > > +   goto err_arb;
> > > +   }
> > > +
> > > return 0;
> > >
> > > +err_arb:
> > > +   if (i2c->have_pmic)
> > > +   clk_disable_unprepare(i2c->clk_pmic);
> > >  err_pmic:
> > > clk_disable_unprepare(i2c->clk_main);
> > >  err_main:
> > > @@ -311,6 +323,9 @@ static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
> > >
> > >  static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
> > >  {
> > > +   if (i2c->clk_arb)
> > > +   clk_disable_unprepare(i2c->clk_arb);
> > > +
> > > if (i2c->have_pmic)
> > > clk_disable_unprepare(i2c->clk_pmic);
> > >
> > > @@ -519,13 +534,13 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
> > > struct i2c_msg *msgs,
> > >
> > > /* Clear interrupt status */
> > > mtk_i2c_writew(i2c, restart_flag | I2C_HS_NACKERR | I2C_ACKERR |
> > > -  I2C_TRANSAC_COMP, OFFSET_INTR_STAT);
> > > +   I2C_ARB_LOST | I2C_TRANSAC_COMP, 
> > > OFFSET_INTR_STAT);
> 
> Is it ok to set I2C_ARB_LOST on _all_ SoC that this driver supports?
> If so, please at least say so in the commit message.
> 

Yes, old and new SoC have the I2C_ARB_LOST bit, but there was no need
for multi-master before, so we didn't set it up specifically, I have
test the patch on the old SoCs. I will add a note in the commit message.

> > >
> > > mtk_i2c_writew(i2c, I2C_FIFO_ADDR_CLR, OFFSET_FIFO_ADDR_CLR);
> > >
> > > /* Enable interrupt */
> > > mtk_i2c_writew(i2c, restart_flag | I2C_HS_NACKERR | I2C_ACKERR |
> > > -  I2C_TRANSAC_COMP, OFFSET_INTR_MASK);
> > > +   I2C_ARB_LOST | I2C_TRANSAC_COMP, 
> > > OFFSET_INTR_MASK);
> > >
> > > /* Set transfer and transaction len */
> > > if (i2c->op == I2C_MASTER_WRRD) {
> > > @@ -659,7 +674,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
> > > struct i2c_msg *msgs,
> > >
> > > /* Clear interrupt mask */
> > > mtk_i2c_writew(i2c, ~(restart_flag | I2C_HS_NACKERR | I2C_ACKERR |
> > > -  I2C_TRANSAC_COMP), OFFSET_INTR_MASK);
> > > +   I2C_ARB_LOST | I2C_TRANSAC_COMP), 
> > > OFFSET_INTR_MASK);
> > >
> > > if (i2c->op == I2C_MASTER_WR) {
> > > dma_unmap_single(i2c->dev, wpaddr,
> > > @@ -884,6 +899,10 @@ static int mtk_i2c_probe(struct platform_device 
> > > *pdev)
> > > return PTR_ERR(i2c->clk_dma);
> > > }
> > >
> > > +   i2c->clk_arb = devm_clk_get(&pdev->dev, "arb");
> > > +   if (IS_ERR(i2c->clk_arb))
> > > +   i2c->clk_arb = NULL;
> > > +
> > > clk = i2c->clk_main;
> > > if (i2c->have_pmic) {
> > > i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic");
> > > --
> > > 1.7.9.5
> > >




Re: [PATCH v4 3/3] i2c: mediatek: Add i2c support for MediaTek MT8183

2019-03-06 Thread Qii Wang
I am sorry to have missed some comment, and reply the mail again.

On Wed, 2019-02-20 at 15:41 +0100, Matthias Brugger wrote:
> 
> On 20/02/2019 13:33, Qii Wang wrote:
> > Add i2c compatible for MT8183. Compare to MT2712 i2c controller,
> > MT8183 has different registers, offsets and clock.
> > 
> > Signed-off-by: Qii Wang 
> 
> So you introduce arb clock, ltiming (what is this exactly) and the new SoC in
> one commit. I'd prefer to split that up and explain shortly in the commit
> message why they are needed. More comments inline.
> 

I have split this patch into three in V5.

> > ---
> >  drivers/i2c/busses/i2c-mt65xx.c |   89 
> > ---
> >  1 file changed, 84 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/i2c/busses/i2c-mt65xx.c 
> > b/drivers/i2c/busses/i2c-mt65xx.c
> > index 428ac99..82eedbd 100644
> > --- a/drivers/i2c/busses/i2c-mt65xx.c
> > +++ b/drivers/i2c/busses/i2c-mt65xx.c
> > @@ -35,6 +35,7 @@
> >  #include 
> >  
> >  #define I2C_RS_TRANSFER(1 << 4)
> > +#define I2C_ARB_LOST   (1 << 3)
> >  #define I2C_HS_NACKERR (1 << 2)
> >  #define I2C_ACKERR (1 << 1)
> >  #define I2C_TRANSAC_COMP   (1 << 0)
> > @@ -76,6 +77,8 @@
> >  #define I2C_CONTROL_DIR_CHANGE  (0x1 << 4)
> >  #define I2C_CONTROL_ACKERR_DET_EN   (0x1 << 5)
> >  #define I2C_CONTROL_TRANSFER_LEN_CHANGE (0x1 << 6)
> > +#define I2C_CONTROL_DMAACK_EN   (0x1 << 8)
> > +#define I2C_CONTROL_ASYNC_MODE  (0x1 << 9)
> >  #define I2C_CONTROL_WRAPPER (0x1 << 0)
> >  
> >  #define I2C_DRV_NAME   "i2c-mt65xx"
> > @@ -130,6 +133,8 @@ enum I2C_REGS_OFFSET {
> > OFFSET_DEBUGCTRL,
> > OFFSET_TRANSFER_LEN_AUX,
> > OFFSET_CLOCK_DIV,
> > +   /* MT8183 only regs */
> > +   OFFSET_LTIMING,
> >  };
> >  
> >  static const u16 mt_i2c_regs_v1[] = {
> > @@ -159,6 +164,32 @@ enum I2C_REGS_OFFSET {
> > [OFFSET_CLOCK_DIV] = 0x70,
> >  };
> >  
> > +static const u16 mt_i2c_regs_v2[] = {
> > +   [OFFSET_DATA_PORT] = 0x0,
> > +   [OFFSET_SLAVE_ADDR] = 0x4,
> > +   [OFFSET_INTR_MASK] = 0x8,
> > +   [OFFSET_INTR_STAT] = 0xc,
> > +   [OFFSET_CONTROL] = 0x10,
> > +   [OFFSET_TRANSFER_LEN] = 0x14,
> > +   [OFFSET_TRANSAC_LEN] = 0x18,
> > +   [OFFSET_DELAY_LEN] = 0x1c,
> > +   [OFFSET_TIMING] = 0x20,
> > +   [OFFSET_START] = 0x24,
> > +   [OFFSET_EXT_CONF] = 0x28,
> > +   [OFFSET_LTIMING] = 0x2c,
> > +   [OFFSET_HS] = 0x30,
> > +   [OFFSET_IO_CONFIG] = 0x34,
> > +   [OFFSET_FIFO_ADDR_CLR] = 0x38,
> > +   [OFFSET_TRANSFER_LEN_AUX] = 0x44,
> > +   [OFFSET_CLOCK_DIV] = 0x48,
> > +   [OFFSET_SOFTRESET] = 0x50,
> > +   [OFFSET_DEBUGSTAT] = 0xe0,
> > +   [OFFSET_DEBUGCTRL] = 0xe8,
> > +   [OFFSET_FIFO_STAT] = 0xf4,
> > +   [OFFSET_FIFO_THRESH] = 0xf8,
> > +   [OFFSET_DCM_EN] = 0xf88,
> > +};
> > +
> >  struct mtk_i2c_compatible {
> > const struct i2c_adapter_quirks *quirks;
> > const u16 *regs;
> > @@ -168,6 +199,7 @@ struct mtk_i2c_compatible {
> > unsigned char aux_len_reg: 1;
> > unsigned char support_33bits: 1;
> > unsigned char timing_adjust: 1;
> > +   unsigned char dma_sync: 1;
> >  };
> >  
> >  struct mtk_i2c {
> > @@ -181,6 +213,7 @@ struct mtk_i2c {
> > struct clk *clk_main;   /* main clock for i2c bus */
> > struct clk *clk_dma;/* DMA clock for i2c via DMA */
> > struct clk *clk_pmic;   /* PMIC clock for i2c from PMIC */
> > +   struct clk *clk_arb;/* Arbitrator clock for i2c */
> > bool have_pmic; /* can use i2c pins from PMIC */
> > bool use_push_pull; /* IO config push-pull mode */
> >  
> > @@ -190,6 +223,7 @@ struct mtk_i2c {
> > enum mtk_trans_op op;
> > u16 timing_reg;
> > u16 high_speed_reg;
> > +   u16 ltiming_reg;
> > unsigned char auto_restart;
> > bool ignore_restart_irq;
> > const struct mtk_i2c_compatible *dev_comp;
> > @@ -216,6 +250,7 @@ struct mtk_i2c {
> > .aux_len_reg = 1,
> > .support_33bits = 1,
> > .timing_adjust = 1,
> > +   .dma_sync = 0,
> >  };
> >  
> >  static const struct mtk_i2c_compatible mt6577_compat = {
> > @@ -227,6 +262,7 @@ struct mtk_i2c {
> >

[PATCH v5 4/5] i2c: mediatek: Add i2c and apdma sync in i2c driver

2019-02-26 Thread Qii Wang
When i2c and apdma use different source clocks, we should enable
synchronization between them.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c |   11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 14d6b38..75d88e1 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -77,6 +77,8 @@
 #define I2C_CONTROL_DIR_CHANGE  (0x1 << 4)
 #define I2C_CONTROL_ACKERR_DET_EN   (0x1 << 5)
 #define I2C_CONTROL_TRANSFER_LEN_CHANGE (0x1 << 6)
+#define I2C_CONTROL_DMAACK_EN   (0x1 << 8)
+#define I2C_CONTROL_ASYNC_MODE  (0x1 << 9)
 #define I2C_CONTROL_WRAPPER (0x1 << 0)
 
 #define I2C_DRV_NAME   "i2c-mt65xx"
@@ -169,6 +171,7 @@ struct mtk_i2c_compatible {
unsigned char aux_len_reg: 1;
unsigned char support_33bits: 1;
unsigned char timing_adjust: 1;
+   unsigned char dma_sync: 1;
 };
 
 struct mtk_i2c {
@@ -218,6 +221,7 @@ struct mtk_i2c {
.aux_len_reg = 1,
.support_33bits = 1,
.timing_adjust = 1,
+   .dma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt6577_compat = {
@@ -229,6 +233,7 @@ struct mtk_i2c {
.aux_len_reg = 0,
.support_33bits = 0,
.timing_adjust = 0,
+   .dma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt6589_compat = {
@@ -240,6 +245,7 @@ struct mtk_i2c {
.aux_len_reg = 0,
.support_33bits = 0,
.timing_adjust = 0,
+   .dma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt7622_compat = {
@@ -251,6 +257,7 @@ struct mtk_i2c {
.aux_len_reg = 1,
.support_33bits = 0,
.timing_adjust = 0,
+   .dma_sync = 0,
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
@@ -261,6 +268,7 @@ struct mtk_i2c {
.aux_len_reg = 1,
.support_33bits = 1,
.timing_adjust = 0,
+   .dma_sync = 0,
 };
 
 static const struct of_device_id mtk_i2c_of_match[] = {
@@ -360,6 +368,9 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 
control_reg = I2C_CONTROL_ACKERR_DET_EN |
  I2C_CONTROL_CLK_EXT_EN | I2C_CONTROL_DMA_EN;
+   if (i2c->dev_comp->dma_sync)
+   control_reg |= I2C_CONTROL_DMAACK_EN | I2C_CONTROL_ASYNC_MODE;
+
mtk_i2c_writew(i2c, control_reg, OFFSET_CONTROL);
mtk_i2c_writew(i2c, I2C_DELAY_LEN, OFFSET_DELAY_LEN);
 
-- 
1.7.9.5



[PATCH v5 2/5] dt-bindings: i2c: Add Mediatek MT8183 i2c binding

2019-02-26 Thread Qii Wang
Add MT8183 i2c binding to binding file. Compare to MT2712 i2c
controller, MT8183 has different registers, offsets, and clock.

Signed-off-by: Qii Wang 
---
 Documentation/devicetree/bindings/i2c/i2c-mtk.txt |4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-mtk.txt 
b/Documentation/devicetree/bindings/i2c/i2c-mtk.txt
index ee4c324..b052f29 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mtk.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mtk.txt
@@ -12,13 +12,15 @@ Required properties:
   "mediatek,mt7623-i2c", "mediatek,mt6577-i2c": for MediaTek MT7623
   "mediatek,mt7629-i2c", "mediatek,mt2712-i2c": for MediaTek MT7629
   "mediatek,mt8173-i2c": for MediaTek MT8173
+  "mediatek,mt8183-i2c": for MediaTek MT8183
   - reg: physical base address of the controller and dma base, length of memory
 mapped region.
   - interrupts: interrupt number to the cpu.
   - clock-div: the fixed value for frequency divider of clock source in i2c
 module. Each IC may be different.
   - clocks: clock name from clock manager
-  - clock-names: Must include "main" and "dma", if enable have-pmic need 
include
+  - clock-names: Must include "main" and "dma", "arb" is for multi-master that
+one bus has more than two i2c controllers, if enable have-pmic need include
 "pmic" extra.
 
 Optional properties:
-- 
1.7.9.5



[PATCH v5 5/5] i2c: mediatek: Add i2c support for MediaTek MT8183

2019-02-26 Thread Qii Wang
Add i2c compatible for MT8183. Compare to MT2712 i2c controller,
MT8183 has different register offsets. Ltiming_reg is added to
adjust low width of SCL. Arb clock and dma_sync are needed.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c |   53 +--
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 75d88e1..82eedbd 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -133,6 +133,8 @@ enum I2C_REGS_OFFSET {
OFFSET_DEBUGCTRL,
OFFSET_TRANSFER_LEN_AUX,
OFFSET_CLOCK_DIV,
+   /* MT8183 only regs */
+   OFFSET_LTIMING,
 };
 
 static const u16 mt_i2c_regs_v1[] = {
@@ -162,6 +164,32 @@ enum I2C_REGS_OFFSET {
[OFFSET_CLOCK_DIV] = 0x70,
 };
 
+static const u16 mt_i2c_regs_v2[] = {
+   [OFFSET_DATA_PORT] = 0x0,
+   [OFFSET_SLAVE_ADDR] = 0x4,
+   [OFFSET_INTR_MASK] = 0x8,
+   [OFFSET_INTR_STAT] = 0xc,
+   [OFFSET_CONTROL] = 0x10,
+   [OFFSET_TRANSFER_LEN] = 0x14,
+   [OFFSET_TRANSAC_LEN] = 0x18,
+   [OFFSET_DELAY_LEN] = 0x1c,
+   [OFFSET_TIMING] = 0x20,
+   [OFFSET_START] = 0x24,
+   [OFFSET_EXT_CONF] = 0x28,
+   [OFFSET_LTIMING] = 0x2c,
+   [OFFSET_HS] = 0x30,
+   [OFFSET_IO_CONFIG] = 0x34,
+   [OFFSET_FIFO_ADDR_CLR] = 0x38,
+   [OFFSET_TRANSFER_LEN_AUX] = 0x44,
+   [OFFSET_CLOCK_DIV] = 0x48,
+   [OFFSET_SOFTRESET] = 0x50,
+   [OFFSET_DEBUGSTAT] = 0xe0,
+   [OFFSET_DEBUGCTRL] = 0xe8,
+   [OFFSET_FIFO_STAT] = 0xf4,
+   [OFFSET_FIFO_THRESH] = 0xf8,
+   [OFFSET_DCM_EN] = 0xf88,
+};
+
 struct mtk_i2c_compatible {
const struct i2c_adapter_quirks *quirks;
const u16 *regs;
@@ -195,6 +223,7 @@ struct mtk_i2c {
enum mtk_trans_op op;
u16 timing_reg;
u16 high_speed_reg;
+   u16 ltiming_reg;
unsigned char auto_restart;
bool ignore_restart_irq;
const struct mtk_i2c_compatible *dev_comp;
@@ -271,12 +300,24 @@ struct mtk_i2c {
.dma_sync = 0,
 };
 
+static const struct mtk_i2c_compatible mt8183_compat = {
+   .regs = mt_i2c_regs_v2,
+   .pmic_i2c = 0,
+   .dcm = 0,
+   .auto_restart = 1,
+   .aux_len_reg = 1,
+   .support_33bits = 1,
+   .timing_adjust = 1,
+   .dma_sync = 1,
+};
+
 static const struct of_device_id mtk_i2c_of_match[] = {
{ .compatible = "mediatek,mt2712-i2c", .data = &mt2712_compat },
{ .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
{ .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
{ .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
{ .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
+   { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
{}
 };
 MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
@@ -361,6 +402,8 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 
mtk_i2c_writew(i2c, i2c->timing_reg, OFFSET_TIMING);
mtk_i2c_writew(i2c, i2c->high_speed_reg, OFFSET_HS);
+   if (i2c->dev_comp->regs == mt_i2c_regs_v2)
+   mtk_i2c_writew(i2c, i2c->ltiming_reg, OFFSET_LTIMING);
 
/* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */
if (i2c->have_pmic)
@@ -460,6 +503,8 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned 
int parent_clk)
unsigned int clk_src;
unsigned int step_cnt;
unsigned int sample_cnt;
+   unsigned int l_step_cnt;
+   unsigned int l_sample_cnt;
unsigned int target_speed;
int ret;
 
@@ -469,11 +514,11 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, 
unsigned int parent_clk)
if (target_speed > MAX_FS_MODE_SPEED) {
/* Set master code speed register */
ret = mtk_i2c_calculate_speed(i2c, clk_src, MAX_FS_MODE_SPEED,
- &step_cnt, &sample_cnt);
+ &l_step_cnt, &l_sample_cnt);
if (ret < 0)
return ret;
 
-   i2c->timing_reg = (sample_cnt << 8) | step_cnt;
+   i2c->timing_reg = (l_sample_cnt << 8) | l_step_cnt;
 
/* Set the high speed mode register */
ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed,
@@ -483,6 +528,8 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned 
int parent_clk)
 
i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE |
(sample_cnt << 12) | (step_cnt << 8);
+   i2c->ltiming_reg = (l_sample_cnt << 6) | l_step_cnt |
+  (sample_cnt << 12) | (step_cnt << 9);
} else

[PATCH v5 1/5] i2c: mediatek: Add offsets array for new i2c registers

2019-02-26 Thread Qii Wang
New i2c registers would have different offsets, so we use different
offsets array to distinguish different i2c registers version.

Signed-off-by: Qii Wang 
Reviewed-by: Matthias Brugger 
---
 drivers/i2c/busses/i2c-mt65xx.c |  163 +--
 1 file changed, 104 insertions(+), 59 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 660de1e..428ac99 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -106,34 +106,62 @@ enum mtk_trans_op {
 };
 
 enum I2C_REGS_OFFSET {
-   OFFSET_DATA_PORT = 0x0,
-   OFFSET_SLAVE_ADDR = 0x04,
-   OFFSET_INTR_MASK = 0x08,
-   OFFSET_INTR_STAT = 0x0c,
-   OFFSET_CONTROL = 0x10,
-   OFFSET_TRANSFER_LEN = 0x14,
-   OFFSET_TRANSAC_LEN = 0x18,
-   OFFSET_DELAY_LEN = 0x1c,
-   OFFSET_TIMING = 0x20,
-   OFFSET_START = 0x24,
-   OFFSET_EXT_CONF = 0x28,
-   OFFSET_FIFO_STAT = 0x30,
-   OFFSET_FIFO_THRESH = 0x34,
-   OFFSET_FIFO_ADDR_CLR = 0x38,
-   OFFSET_IO_CONFIG = 0x40,
-   OFFSET_RSV_DEBUG = 0x44,
-   OFFSET_HS = 0x48,
-   OFFSET_SOFTRESET = 0x50,
-   OFFSET_DCM_EN = 0x54,
-   OFFSET_PATH_DIR = 0x60,
-   OFFSET_DEBUGSTAT = 0x64,
-   OFFSET_DEBUGCTRL = 0x68,
-   OFFSET_TRANSFER_LEN_AUX = 0x6c,
-   OFFSET_CLOCK_DIV = 0x70,
+   OFFSET_DATA_PORT,
+   OFFSET_SLAVE_ADDR,
+   OFFSET_INTR_MASK,
+   OFFSET_INTR_STAT,
+   OFFSET_CONTROL,
+   OFFSET_TRANSFER_LEN,
+   OFFSET_TRANSAC_LEN,
+   OFFSET_DELAY_LEN,
+   OFFSET_TIMING,
+   OFFSET_START,
+   OFFSET_EXT_CONF,
+   OFFSET_FIFO_STAT,
+   OFFSET_FIFO_THRESH,
+   OFFSET_FIFO_ADDR_CLR,
+   OFFSET_IO_CONFIG,
+   OFFSET_RSV_DEBUG,
+   OFFSET_HS,
+   OFFSET_SOFTRESET,
+   OFFSET_DCM_EN,
+   OFFSET_PATH_DIR,
+   OFFSET_DEBUGSTAT,
+   OFFSET_DEBUGCTRL,
+   OFFSET_TRANSFER_LEN_AUX,
+   OFFSET_CLOCK_DIV,
+};
+
+static const u16 mt_i2c_regs_v1[] = {
+   [OFFSET_DATA_PORT] = 0x0,
+   [OFFSET_SLAVE_ADDR] = 0x4,
+   [OFFSET_INTR_MASK] = 0x8,
+   [OFFSET_INTR_STAT] = 0xc,
+   [OFFSET_CONTROL] = 0x10,
+   [OFFSET_TRANSFER_LEN] = 0x14,
+   [OFFSET_TRANSAC_LEN] = 0x18,
+   [OFFSET_DELAY_LEN] = 0x1c,
+   [OFFSET_TIMING] = 0x20,
+   [OFFSET_START] = 0x24,
+   [OFFSET_EXT_CONF] = 0x28,
+   [OFFSET_FIFO_STAT] = 0x30,
+   [OFFSET_FIFO_THRESH] = 0x34,
+   [OFFSET_FIFO_ADDR_CLR] = 0x38,
+   [OFFSET_IO_CONFIG] = 0x40,
+   [OFFSET_RSV_DEBUG] = 0x44,
+   [OFFSET_HS] = 0x48,
+   [OFFSET_SOFTRESET] = 0x50,
+   [OFFSET_DCM_EN] = 0x54,
+   [OFFSET_PATH_DIR] = 0x60,
+   [OFFSET_DEBUGSTAT] = 0x64,
+   [OFFSET_DEBUGCTRL] = 0x68,
+   [OFFSET_TRANSFER_LEN_AUX] = 0x6c,
+   [OFFSET_CLOCK_DIV] = 0x70,
 };
 
 struct mtk_i2c_compatible {
const struct i2c_adapter_quirks *quirks;
+   const u16 *regs;
unsigned char pmic_i2c: 1;
unsigned char dcm: 1;
unsigned char auto_restart: 1;
@@ -181,6 +209,7 @@ struct mtk_i2c {
 };
 
 static const struct mtk_i2c_compatible mt2712_compat = {
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 1,
@@ -191,6 +220,7 @@ struct mtk_i2c {
 
 static const struct mtk_i2c_compatible mt6577_compat = {
.quirks = &mt6577_i2c_quirks,
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 0,
@@ -201,6 +231,7 @@ struct mtk_i2c {
 
 static const struct mtk_i2c_compatible mt6589_compat = {
.quirks = &mt6577_i2c_quirks,
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 1,
.dcm = 0,
.auto_restart = 0,
@@ -211,6 +242,7 @@ struct mtk_i2c {
 
 static const struct mtk_i2c_compatible mt7622_compat = {
.quirks = &mt7622_i2c_quirks,
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 1,
@@ -220,6 +252,7 @@ struct mtk_i2c {
 };
 
 static const struct mtk_i2c_compatible mt8173_compat = {
+   .regs = mt_i2c_regs_v1,
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 1,
@@ -238,6 +271,17 @@ struct mtk_i2c {
 };
 MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
 
+static u16 mtk_i2c_readw(struct mtk_i2c *i2c, enum I2C_REGS_OFFSET reg)
+{
+   return readw(i2c->base + i2c->dev_comp->regs[reg]);
+}
+
+static void mtk_i2c_writew(struct mtk_i2c *i2c, u16 val,
+  enum I2C_REGS_OFFSET reg)
+{
+   writew(val, i2c->base + i2c->dev_comp->regs[reg]);
+}
+
 static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
 {
int ret;
@@ -278,31 +322,31 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 {
u16 control_reg;
 
-   writew(I2C_SOFT_RST, i2c->base + OFFSET_SOFTRESET);
+   mtk_i2c_writew(i2c, I2C_SOFT_RST, OFFSET_SOFTRESET);
 
/* Set ioconfig */
if (i2c->u

[PATCH v5 3/5] i2c: mediatek: Add arb clock in i2c driver

2019-02-26 Thread Qii Wang
When two i2c controllers are internally connected to the same
GPIO pins, the arb clock is needed to ensure that the waveforms
do not interfere with each other.

Signed-off-by: Qii Wang 
---
 drivers/i2c/busses/i2c-mt65xx.c |   25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 428ac99..14d6b38 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -35,6 +35,7 @@
 #include 
 
 #define I2C_RS_TRANSFER(1 << 4)
+#define I2C_ARB_LOST   (1 << 3)
 #define I2C_HS_NACKERR (1 << 2)
 #define I2C_ACKERR (1 << 1)
 #define I2C_TRANSAC_COMP   (1 << 0)
@@ -181,6 +182,7 @@ struct mtk_i2c {
struct clk *clk_main;   /* main clock for i2c bus */
struct clk *clk_dma;/* DMA clock for i2c via DMA */
struct clk *clk_pmic;   /* PMIC clock for i2c from PMIC */
+   struct clk *clk_arb;/* Arbitrator clock for i2c */
bool have_pmic; /* can use i2c pins from PMIC */
bool use_push_pull; /* IO config push-pull mode */
 
@@ -299,8 +301,18 @@ static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
if (ret)
goto err_pmic;
}
+
+   if (i2c->clk_arb) {
+   ret = clk_prepare_enable(i2c->clk_arb);
+   if (ret)
+   goto err_arb;
+   }
+
return 0;
 
+err_arb:
+   if (i2c->have_pmic)
+   clk_disable_unprepare(i2c->clk_pmic);
 err_pmic:
clk_disable_unprepare(i2c->clk_main);
 err_main:
@@ -311,6 +323,9 @@ static int mtk_i2c_clock_enable(struct mtk_i2c *i2c)
 
 static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
 {
+   if (i2c->clk_arb)
+   clk_disable_unprepare(i2c->clk_arb);
+
if (i2c->have_pmic)
clk_disable_unprepare(i2c->clk_pmic);
 
@@ -519,13 +534,13 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, 
struct i2c_msg *msgs,
 
/* Clear interrupt status */
mtk_i2c_writew(i2c, restart_flag | I2C_HS_NACKERR | I2C_ACKERR |
-  I2C_TRANSAC_COMP, OFFSET_INTR_STAT);
+   I2C_ARB_LOST | I2C_TRANSAC_COMP, OFFSET_INTR_STAT);
 
mtk_i2c_writew(i2c, I2C_FIFO_ADDR_CLR, OFFSET_FIFO_ADDR_CLR);
 
/* Enable interrupt */
mtk_i2c_writew(i2c, restart_flag | I2C_HS_NACKERR | I2C_ACKERR |
-  I2C_TRANSAC_COMP, OFFSET_INTR_MASK);
+   I2C_ARB_LOST | I2C_TRANSAC_COMP, OFFSET_INTR_MASK);
 
/* Set transfer and transaction len */
if (i2c->op == I2C_MASTER_WRRD) {
@@ -659,7 +674,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct 
i2c_msg *msgs,
 
/* Clear interrupt mask */
mtk_i2c_writew(i2c, ~(restart_flag | I2C_HS_NACKERR | I2C_ACKERR |
-  I2C_TRANSAC_COMP), OFFSET_INTR_MASK);
+   I2C_ARB_LOST | I2C_TRANSAC_COMP), OFFSET_INTR_MASK);
 
if (i2c->op == I2C_MASTER_WR) {
dma_unmap_single(i2c->dev, wpaddr,
@@ -884,6 +899,10 @@ static int mtk_i2c_probe(struct platform_device *pdev)
return PTR_ERR(i2c->clk_dma);
}
 
+   i2c->clk_arb = devm_clk_get(&pdev->dev, "arb");
+   if (IS_ERR(i2c->clk_arb))
+   i2c->clk_arb = NULL;
+
clk = i2c->clk_main;
if (i2c->have_pmic) {
i2c->clk_pmic = devm_clk_get(&pdev->dev, "pmic");
-- 
1.7.9.5



  1   2   >