Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH v11 08/14] usb: otg: add OTG/dual-role core
From: Vivek Gautam @ 2017-01-19 11:56 UTC (permalink / raw)
  To: Roger Quadros, Felipe Balbi
  Cc: Peter Chen, Yoshihiro Shimoda, peter.chen, Tony Lindgren, Greg KH,
	dan.j.williams, Mathias Nyman, Joao.Pinto, Sergei Shtylyov,
	jun.li, grygorii.strashko, Rob Herring, nsekhar, b-liu,
	Joe Perches, Linux USB Mailing List, linux-omap@vger.kernel.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org
In-Reply-To: <576A4C95.4080202@ti.com>

Hi,


On Wed, Jun 22, 2016 at 2:00 PM, Roger Quadros <rogerq@ti.com> wrote:

Luckily hit this thread while checking about DRD role functionality for DWC3.

> On 22/06/16 11:14, Felipe Balbi wrote:
>>
>> Hi,
>>
>> Roger Quadros <rogerq@ti.com> writes:
>>>>>>>>>>> For the real use case, some Carplay platforms need it.
>>>>>>>>>>
>>>>>>>>>> Carplay does *NOT* rely on OTG. Apple has its own proprietary and closed
>>>>>>>>>> specification which is not OTG-compliant.
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Yes, it is not OTG-compliant, but it can co-work with some standard OTG FSM
>>>>>>>>> states to finish role swap.
>>>>>>>>
>>>>>>>> What are you referring to as "finish role swap"? I don't get that.
>>>>>>>
>>>>>>> Change current role from host to peripheral.
>>>>>>
>>>>>> Okay, we have two scenarios here:
>>>>>>
>>>>>> 1. You need full OTG compliance
>>>>>>
>>>>>>   For this, granted, you need the state machine if your HW doesn't
>>>>>>   track it. This is a given. With only one user, however, perhaps
>>>>>>   we don't need a generic layer. There are not enough different
>>>>>>   setups to design a good enough generic layer. We will end up
>>>>>>   with a pseudo-generic framework which is coupled with its only
>>>>>>   user.
>>>>>>
>>>>>> 2. Dual-role support, without OTG compliance
>>>>>>
>>>>>>   In this case, you don't need a stack. All you need is a signal
>>>>>>   to tell you state of ID pin and another to tell you state of
>>>>>>   VBUS level. If you have those, you don't need to walk an OTG
>>>>>>   state machine at all. You don't need any of those quirky OTG
>>>>>>   timers, agreed?
>>>>>>
>>>>>>   Given the above, why would you even want to use a subset of OTG
>>>>>>   state machine to implement something that's _usually_ as simple
>>>>>>   as:
>>>>>>
>>>>>> 8<----------------------------------------------------------------------
>>>>>>   vbus = read(VBUS_STATE); /* could be a gpio_get_value() */
>>>>>>         id = read(ID_STATE); /* could be a gpio_get_value() */
>>>>>>
>>>>>>         set_role(id);
>>>>>>         set_vbus(vbus);
>>>>>> ------------------------------------------------------------------------
>>>>>>
>>>>>
>>>>> In fact, the individual driver can do it by itself. The chipidea driver
>>>>> handles OTG and dual-role well currently. By considering this OTG/DRD
>>>>> framework is worthwhile or not, we would like to see if it can
>>>>> simplify DRD design for each driver, and can benefit the platforms which
>>>>> has different drivers for host and peripheral to finish the role switch
>>>>> well.
>>>>
>>>> simplify how?  By adding unnecessary workqueues and a level indirection
>>>> that just goes back to the same driver?
>>>
>>> What do you mean by same driver?
>>
>> dwc3 registers to OTG layer. dwc3 also registers as UDC to UDC
>> layer. When dwc3 OTG IRQ fires, dwc3 tells OTG layer about it and OTG
>> layer jumps to a callback that goes back to dwc3 to e.g. start
>> peripheral side.
>>
>> See ?!? Starts on dwc3, goes to OTG layer, goes back to DWC3.
>>
>>> Gadget driver, host driver and PHY (or MUX) driver (for ID/VBUS) can
>>> be 3 totally independent drivers unlike dwc3 where you have a single
>>> driver in control of both host and gadget.
>>
>> That's a totally different issue and one not being tackled by OTG
>> layer, because there are no such users yet. We can't design anything
>> based solely on speculation of what might happen.
>>
>> If there aren't enough users, there is no way to design a good generic
>> layer.
>>
>>> Questions not clear to me are:
>>>
>>> 1) Which driver handles ID/VBUS events and makes a decision to do the
>>> role swap?  Probably the PHY/MUX driver?
>>
>> This is implementation dependent. For TI's USB subsystem, we have PMIC
>> sampling VBUS/ID that and using EXTCON to tell dwc3-omap to program UTMI
>> mailbox. The same mailbox can be used in HW-mode (see AM437x) where SW
>> has no intervention.
>>
>> For Intel's USB subsystem, we have PMIC sampling VBUS/ID with an
>> internal mux (much like TI's UTMI mailbox, but slightly different) to
>> switch between a separate XHCI or a separate dwc3. The same mux can be
>> put in HW-mode where SW has no intervention.
>>
>> In any case, for Intel's stuff most of the magic happens in ASL. Our PHY
>> driver just detects role (at least for Type-C based plats) and executes
>> _DSM with correct arguments [1]. _DSM will program internal MUX, toggle
>> VBUS and, for type-C, toggle VCONN when needed.
>>
>>> 2) How does it perform the role swap? Probably a register write to the
>>> PHY/MUX without needing to stop/start controllers? Easy case is both
>>> controllers can run in co-existence without interference. Is there any
>>> platform other than dwc3 where this is not the case?
>>
>> Again speculation. But to answer your question, only dwc3 is in such a
>> case today. But even for dwc3 we can have DRD with a much, much simpler
>> setup as I have already explained.
>>
>>> 3) Even if host and gadget controllers can operate in coexistence,
>>> there is no need for both to be running for embedded applications
>>> which are usually power conservative.  How can we achieve that?
>>
>> Now you're also speculating that you're running on embedded applications
>> and that we _can_ power off parts of the IP. I happen to know that we
>> can't power off XHCI part of dwc3 in TI's SoC because that's fed by same
>> Clocks and power rails as the peripheral side.
>>
>> [1] https://lkml.org/lkml/2016/6/21/658
>>
> For TI's case it is dwc3 and you are implementing the role swap in the dwc3
> driver where you do intend to remove the XHCI platform device. So I'm not
> much concerned about that.
>
> I was concerned about other platforms. I guess I'll let the other platform
> people speak up as to what they need.

I will talk about the msm platforms using dwc3 hardware.
DWC3 controller on msm doesn't seem to have full otg functionality,
and the driver makes use of switching between host and device
using PRTCAPDIR register in of the core [1].

We plan to support this DRD role switching (swapping host and device
functionality based on id/vbus interrupts) in upstream.

Do we see a valid case to have this framework?
Or, may be add a 'drd' layer for dwc3 that handles
role switching (using PRTCAPDIR) based on the id/vbus extcon notifications.


[1] https://source.codeaurora.org/quic/la/kernel/msm-3.18/tree/drivers/usb/dwc3/dwc3-msm.c?h=msm-3.18
     "dwc3_otg_start_host()"
     "dwc3_otg_start_peripheral()"


Regards
Vivek
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* Re: [PATCH v8 2/4] arm64: arch_timer: Introduce a generic erratum handing mechanism for fsl-a008585
From: Marc Zyngier @ 2017-01-19 11:59 UTC (permalink / raw)
  To: Ding Tianhong, catalin.marinas, will.deacon, mark.rutland, oss,
	devicetree, shawnguo, stuart.yoder, linux-arm-kernel, linuxarm
In-Reply-To: <1484824474-12172-3-git-send-email-dingtianhong@huawei.com>

On 19/01/17 11:14, Ding Tianhong wrote:
> The workaround for hisilicon,161010101 will check the return value of the system counter
> by different way, in order to distinguish with the fsl-a008585 workaround, introduce
> a new generic erratum handing mechanism for fsl-a008585 and rename some functions.
> 
> After discussion with Marc and Will, a consensus decision was made to remove the commandline
> parameter for enabling fsl,erratum-a008585 erratum.
> 
> Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
> ---
>  Documentation/admin-guide/kernel-parameters.txt |   9 --
>  arch/arm64/include/asm/arch_timer.h             |  38 +++------
>  drivers/clocksource/Kconfig                     |   8 ++
>  drivers/clocksource/arm_arch_timer.c            | 105 ++++++++++++++----------
>  4 files changed, 84 insertions(+), 76 deletions(-)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 21e2d88..76437ad 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -539,15 +539,6 @@
>  			loops can be debugged more effectively on production
>  			systems.
>  
> -	clocksource.arm_arch_timer.fsl-a008585=
> -			[ARM64]
> -			Format: <bool>
> -			Enable/disable the workaround of Freescale/NXP
> -			erratum A-008585.  This can be useful for KVM
> -			guests, if the guest device tree doesn't show the
> -			erratum.  If unspecified, the workaround is
> -			enabled based on the device tree.
> -
>  	clearcpuid=BITNUM [X86]
>  			Disable CPUID feature X for the kernel. See
>  			arch/x86/include/asm/cpufeatures.h for the valid bit
> diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
> index eaa5bbe..b4b3400 100644
> --- a/arch/arm64/include/asm/arch_timer.h
> +++ b/arch/arm64/include/asm/arch_timer.h
> @@ -29,41 +29,29 @@
>  
>  #include <clocksource/arm_arch_timer.h>
>  
> -#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585)
> +#if IS_ENABLED(CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND)
>  extern struct static_key_false arch_timer_read_ool_enabled;
> -#define needs_fsl_a008585_workaround() \
> +#define needs_unstable_timer_counter_workaround() \
>  	static_branch_unlikely(&arch_timer_read_ool_enabled)
>  #else
> -#define needs_fsl_a008585_workaround()  false
> +#define needs_unstable_timer_counter_workaround()  false
>  #endif
>  
> -u32 __fsl_a008585_read_cntp_tval_el0(void);
> -u32 __fsl_a008585_read_cntv_tval_el0(void);
> -u64 __fsl_a008585_read_cntvct_el0(void);
>  
> -/*
> - * The number of retries is an arbitrary value well beyond the highest number
> - * of iterations the loop has been observed to take.
> - */
> -#define __fsl_a008585_read_reg(reg) ({			\
> -	u64 _old, _new;					\
> -	int _retries = 200;				\
> -							\
> -	do {						\
> -		_old = read_sysreg(reg);		\
> -		_new = read_sysreg(reg);		\
> -		_retries--;				\
> -	} while (unlikely(_old != _new) && _retries);	\
> -							\
> -	WARN_ON_ONCE(!_retries);			\
> -	_new;						\
> -})
> +struct arch_timer_erratum_workaround {
> +	const char *id;		/* Indicate the Erratum ID */
> +	u32 (*read_cntp_tval_el0)(void);
> +	u32 (*read_cntv_tval_el0)(void);
> +	u64 (*read_cntvct_el0)(void);
> +};
> +
> +extern const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround;
>  
>  #define arch_timer_reg_read_stable(reg) 		\
>  ({							\
>  	u64 _val;					\
> -	if (needs_fsl_a008585_workaround())		\
> -		_val = __fsl_a008585_read_##reg();	\
> +	if (needs_unstable_timer_counter_workaround())		\
> +		_val = timer_unstable_counter_workaround->read_##reg();\
>  	else						\
>  		_val = read_sysreg(reg);		\
>  	_val;						\
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 4866f7a..04c2b93 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -325,10 +325,18 @@ config ARM_ARCH_TIMER_EVTSTREAM
>  	  This must be disabled for hardware validation purposes to detect any
>  	  hardware anomalies of missing events.
>  
> +config ARM_ARCH_TIMER_OOL_WORKAROUND
> +	bool "Workaround for arm arch timer unstable counter"

Please drop the message. We don't want that option to be selectable by a
user, but only selected if an erratum that depends on it is enabled.

> +	depends on FSL_ERRATUM_A008585
> +	help
> +	  This option would only be enabled by Freescale/NXP Erratum A-008585
> +	  or something else chip has similar erratum.
> +
>  config FSL_ERRATUM_A008585
>  	bool "Workaround for Freescale/NXP Erratum A-008585"
>  	default y
>  	depends on ARM_ARCH_TIMER && ARM64
> +	select ARM_ARCH_TIMER_OOL_WORKAROUND
>  	help
>  	  This option enables a workaround for Freescale/NXP Erratum
>  	  A-008585 ("ARM generic timer may contain an erroneous

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* Re: [PATCH 2/4] ARM: dts: imx7d-sdp: Fix watchdog and pwm pinmux
From: Fabio Estevam @ 2017-01-19 12:02 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	Fabio Estevam, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Shawn Guo, Sascha Hauer
In-Reply-To: <20170119090924.19636-3-s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

On Thu, Jan 19, 2017 at 7:09 AM, Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> wrote:
> The watchdog pin and the pwm output pin are controlled by the
> iomuxc_lpsr, not the regular iomux, so move the pins there.
>
> Signed-off-by: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Reviewed-by: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>

Just two minor nits that probably Shawn can take care while applying it"

in Subject there is a typo "sdb".

> ---
>  arch/arm/boot/dts/imx7d-sdb.dts | 26 ++++++++++++++------------
>  1 file changed, 14 insertions(+), 12 deletions(-)
>
> diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts
> index 2f33c463cbce..84f35a6cbb30 100644
> --- a/arch/arm/boot/dts/imx7d-sdb.dts
> +++ b/arch/arm/boot/dts/imx7d-sdb.dts
> @@ -502,12 +502,6 @@
>                         >;
>                 };
>
> -               pinctrl_pwm1: pwm1grp {
> -                       fsl,pins = <
> -                               MX7D_PAD_GPIO1_IO01__PWM1_OUT           0x110b0
> -                       >;
> -               };
> -
>                 pinctrl_tsc2046_pendown: tsc2046_pendown {
>                         fsl,pins = <
>                                 MX7D_PAD_EPDC_BDR1__GPIO2_IO29          0x59
> @@ -635,11 +629,19 @@
>                                 MX7D_PAD_SD3_STROBE__SD3_STROBE         0x1b
>                         >;
>                 };
> -
> -               pinctrl_wdog: wdoggrp {
> -                       fsl,pins = <
> -                               MX7D_PAD_GPIO1_IO00__WDOD1_WDOG_B       0x74
> -                       >;
> -               };
>         };
>  };
> +
> +&iomuxc_lpsr {
> +       pinctrl_wdog: wdoggrp {
> +               fsl,pins = <
> +                       MX7D_PAD_GPIO1_IO00__WDOD1_WDOG_B       0x74
> +               >;
> +       };
> +
> +       pinctrl_pwm1: pwm1grp {
> +               fsl,pins = <
> +                       MX7D_PAD_GPIO1_IO01__PWM1_OUT           0x110b0
> +               >;
> +       };
> +};
> \ No newline at end of file

This could be fixed as well.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 3/4] ARM: dts: imx7d-cl-som: Fix OTG power pinctrl
From: Fabio Estevam @ 2017-01-19 12:02 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	Fabio Estevam, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Shawn Guo, Sascha Hauer
In-Reply-To: <20170119090924.19636-4-s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

On Thu, Jan 19, 2017 at 7:09 AM, Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> wrote:
> GPIO01_IO05 is controlled by the LPSR iomux controller, so attach
> the corresponding pin to this controller.
>
> Signed-off-by: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Reviewed-by: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 4/4] ARM: dts: imx7: Add "LPSR" to LPSR iomux pin names
From: Fabio Estevam @ 2017-01-19 12:03 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	Fabio Estevam, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Shawn Guo, Sascha Hauer
In-Reply-To: <20170119090924.19636-5-s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

On Thu, Jan 19, 2017 at 7:09 AM, Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> wrote:
> The i.MX7 has two iomux controllers. the iomuxc and the iomuxc_lpsr.
> In a board dts we have to make sure that both controllers are supplied
> with the correct pins. It's way too easy to do this wrong since only
> a look into the reference manual can reveal which pins belong to which
> controller. To make this clearer add "LPSR" to the pin names which
> belong to the LPSR controller.
>
> Signed-off-by: Sascha Hauer <s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

I like this idea!

Reviewed-by: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH RESEND v8 1/4] arm64: arch_timer: Add device tree binding for hisilicon-161010101 erratum
From: Mark Rutland @ 2017-01-19 12:10 UTC (permalink / raw)
  To: Ding Tianhong
  Cc: devicetree, marc.zyngier, catalin.marinas, will.deacon,
	stuart.yoder, linuxarm, oss, shawnguo, linux-arm-kernel
In-Reply-To: <1484826406-16348-2-git-send-email-dingtianhong@huawei.com>

On Thu, Jan 19, 2017 at 07:46:43PM +0800, Ding Tianhong wrote:
> This erratum describes a bug in logic outside the core, so MIDR can't be
> used to identify its presence, and reading an SoC-specific revision
> register from common arch timer code would be awkward.  So, describe it
> in the device tree.
> 
> Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
>  Documentation/devicetree/bindings/arm/arch_timer.txt | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
> index ad440a2..9116934 100644
> --- a/Documentation/devicetree/bindings/arm/arch_timer.txt
> +++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
> @@ -31,6 +31,14 @@ to deliver its interrupts via SPIs.
>    This also affects writes to the tval register, due to the implicit
>    counter read.
>  
> +- hisilicon,erratum-161010101 : A boolean property. Indicates the presence of
> +  erratum 161010101, which says that reading the counter is unreliable unless
> +  reading twice on the register and the value of the second read is larger
> +  than the first by less than 32. If the verification is unsuccessful, then
> +  discard the value of this read and repeat this procedure until the verification
> +  is successful.  This also affects writes to the tval register, due to the
> +  implicit counter read.

This describes the workaround, which shouldn't be necessary.

My understanding (from the cover letter) is that reads of the
{virtual,physical} counters may return a value precisely 32 above the
true value.

So it would be better to say:

- hisilicon,erratum-161010101 : A boolean property. Indicates the
  presence of Hisilicon erratum 161010101, which says that reading the
  counters is unreliable in some cases, and reads may return a value 32
  beyond the correct value. This also affects writes to the tval
  registers, due to the implicit counter read.

Thanks,
Mark.

^ permalink raw reply

* Re: [PATCH v11 08/14] usb: otg: add OTG/dual-role core
From: Roger Quadros @ 2017-01-19 12:15 UTC (permalink / raw)
  To: Vivek Gautam, Felipe Balbi
  Cc: Peter Chen, Yoshihiro Shimoda, peter.chen, Tony Lindgren, Greg KH,
	dan.j.williams, Mathias Nyman, Joao.Pinto, Sergei Shtylyov,
	jun.li, grygorii.strashko, Rob Herring, nsekhar, b-liu,
	Joe Perches, Linux USB Mailing List, linux-omap@vger.kernel.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org
In-Reply-To: <CAFp+6iEpnHTWQe196zWPJu3vqb+L=47rfU_8nfuUNC=Gjvc8Gg@mail.gmail.com>

Vivek,

On 19/01/17 13:56, Vivek Gautam wrote:
> Hi,
> 
> 
> On Wed, Jun 22, 2016 at 2:00 PM, Roger Quadros <rogerq@ti.com> wrote:
> 
> Luckily hit this thread while checking about DRD role functionality for DWC3.
> 
>> On 22/06/16 11:14, Felipe Balbi wrote:
>>>
>>> Hi,
>>>
>>> Roger Quadros <rogerq@ti.com> writes:
>>>>>>>>>>>> For the real use case, some Carplay platforms need it.
>>>>>>>>>>>
>>>>>>>>>>> Carplay does *NOT* rely on OTG. Apple has its own proprietary and closed
>>>>>>>>>>> specification which is not OTG-compliant.
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Yes, it is not OTG-compliant, but it can co-work with some standard OTG FSM
>>>>>>>>>> states to finish role swap.
>>>>>>>>>
>>>>>>>>> What are you referring to as "finish role swap"? I don't get that.
>>>>>>>>
>>>>>>>> Change current role from host to peripheral.
>>>>>>>
>>>>>>> Okay, we have two scenarios here:
>>>>>>>
>>>>>>> 1. You need full OTG compliance
>>>>>>>
>>>>>>>   For this, granted, you need the state machine if your HW doesn't
>>>>>>>   track it. This is a given. With only one user, however, perhaps
>>>>>>>   we don't need a generic layer. There are not enough different
>>>>>>>   setups to design a good enough generic layer. We will end up
>>>>>>>   with a pseudo-generic framework which is coupled with its only
>>>>>>>   user.
>>>>>>>
>>>>>>> 2. Dual-role support, without OTG compliance
>>>>>>>
>>>>>>>   In this case, you don't need a stack. All you need is a signal
>>>>>>>   to tell you state of ID pin and another to tell you state of
>>>>>>>   VBUS level. If you have those, you don't need to walk an OTG
>>>>>>>   state machine at all. You don't need any of those quirky OTG
>>>>>>>   timers, agreed?
>>>>>>>
>>>>>>>   Given the above, why would you even want to use a subset of OTG
>>>>>>>   state machine to implement something that's _usually_ as simple
>>>>>>>   as:
>>>>>>>
>>>>>>> 8<----------------------------------------------------------------------
>>>>>>>   vbus = read(VBUS_STATE); /* could be a gpio_get_value() */
>>>>>>>         id = read(ID_STATE); /* could be a gpio_get_value() */
>>>>>>>
>>>>>>>         set_role(id);
>>>>>>>         set_vbus(vbus);
>>>>>>> ------------------------------------------------------------------------
>>>>>>>
>>>>>>
>>>>>> In fact, the individual driver can do it by itself. The chipidea driver
>>>>>> handles OTG and dual-role well currently. By considering this OTG/DRD
>>>>>> framework is worthwhile or not, we would like to see if it can
>>>>>> simplify DRD design for each driver, and can benefit the platforms which
>>>>>> has different drivers for host and peripheral to finish the role switch
>>>>>> well.
>>>>>
>>>>> simplify how?  By adding unnecessary workqueues and a level indirection
>>>>> that just goes back to the same driver?
>>>>
>>>> What do you mean by same driver?
>>>
>>> dwc3 registers to OTG layer. dwc3 also registers as UDC to UDC
>>> layer. When dwc3 OTG IRQ fires, dwc3 tells OTG layer about it and OTG
>>> layer jumps to a callback that goes back to dwc3 to e.g. start
>>> peripheral side.
>>>
>>> See ?!? Starts on dwc3, goes to OTG layer, goes back to DWC3.
>>>
>>>> Gadget driver, host driver and PHY (or MUX) driver (for ID/VBUS) can
>>>> be 3 totally independent drivers unlike dwc3 where you have a single
>>>> driver in control of both host and gadget.
>>>
>>> That's a totally different issue and one not being tackled by OTG
>>> layer, because there are no such users yet. We can't design anything
>>> based solely on speculation of what might happen.
>>>
>>> If there aren't enough users, there is no way to design a good generic
>>> layer.
>>>
>>>> Questions not clear to me are:
>>>>
>>>> 1) Which driver handles ID/VBUS events and makes a decision to do the
>>>> role swap?  Probably the PHY/MUX driver?
>>>
>>> This is implementation dependent. For TI's USB subsystem, we have PMIC
>>> sampling VBUS/ID that and using EXTCON to tell dwc3-omap to program UTMI
>>> mailbox. The same mailbox can be used in HW-mode (see AM437x) where SW
>>> has no intervention.
>>>
>>> For Intel's USB subsystem, we have PMIC sampling VBUS/ID with an
>>> internal mux (much like TI's UTMI mailbox, but slightly different) to
>>> switch between a separate XHCI or a separate dwc3. The same mux can be
>>> put in HW-mode where SW has no intervention.
>>>
>>> In any case, for Intel's stuff most of the magic happens in ASL. Our PHY
>>> driver just detects role (at least for Type-C based plats) and executes
>>> _DSM with correct arguments [1]. _DSM will program internal MUX, toggle
>>> VBUS and, for type-C, toggle VCONN when needed.
>>>
>>>> 2) How does it perform the role swap? Probably a register write to the
>>>> PHY/MUX without needing to stop/start controllers? Easy case is both
>>>> controllers can run in co-existence without interference. Is there any
>>>> platform other than dwc3 where this is not the case?
>>>
>>> Again speculation. But to answer your question, only dwc3 is in such a
>>> case today. But even for dwc3 we can have DRD with a much, much simpler
>>> setup as I have already explained.
>>>
>>>> 3) Even if host and gadget controllers can operate in coexistence,
>>>> there is no need for both to be running for embedded applications
>>>> which are usually power conservative.  How can we achieve that?
>>>
>>> Now you're also speculating that you're running on embedded applications
>>> and that we _can_ power off parts of the IP. I happen to know that we
>>> can't power off XHCI part of dwc3 in TI's SoC because that's fed by same
>>> Clocks and power rails as the peripheral side.
>>>
>>> [1] https://lkml.org/lkml/2016/6/21/658
>>>
>> For TI's case it is dwc3 and you are implementing the role swap in the dwc3
>> driver where you do intend to remove the XHCI platform device. So I'm not
>> much concerned about that.
>>
>> I was concerned about other platforms. I guess I'll let the other platform
>> people speak up as to what they need.
> 
> I will talk about the msm platforms using dwc3 hardware.
> DWC3 controller on msm doesn't seem to have full otg functionality,
> and the driver makes use of switching between host and device
> using PRTCAPDIR register in of the core [1].
> 
> We plan to support this DRD role switching (swapping host and device
> functionality based on id/vbus interrupts) in upstream.
> 
> Do we see a valid case to have this framework?

Felipe wanted to have a minimal dual-role logic inside dwc3 which is
independent of any DRD/OTG framework.

I have implemented this and will send out patches today for review.

> Or, may be add a 'drd' layer for dwc3 that handles
> role switching (using PRTCAPDIR) based on the id/vbus extcon notifications.
> 
> 
> [1] https://source.codeaurora.org/quic/la/kernel/msm-3.18/tree/drivers/usb/dwc3/dwc3-msm.c?h=msm-3.18
>      "dwc3_otg_start_host()"
>      "dwc3_otg_start_peripheral()"
> 
> 

regards,
-roger

^ permalink raw reply

* Re: [PATCH v8 2/4] arm64: arch_timer: Introduce a generic erratum handing mechanism for fsl-a008585
From: Ding Tianhong @ 2017-01-19 12:16 UTC (permalink / raw)
  To: Marc Zyngier, catalin.marinas, will.deacon, mark.rutland, oss,
	devicetree, shawnguo, stuart.yoder, linux-arm-kernel, linuxarm
In-Reply-To: <eeab7907-77c3-163c-f489-319012a13913@arm.com>



On 2017/1/19 19:59, Marc Zyngier wrote:
> On 19/01/17 11:14, Ding Tianhong wrote:
>> The workaround for hisilicon,161010101 will check the return value of the system counter
>> by different way, in order to distinguish with the fsl-a008585 workaround, introduce
>> a new generic erratum handing mechanism for fsl-a008585 and rename some functions.
>>
>> After discussion with Marc and Will, a consensus decision was made to remove the commandline
>> parameter for enabling fsl,erratum-a008585 erratum.
>>
>> Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
>> ---
>>  Documentation/admin-guide/kernel-parameters.txt |   9 --
>>  arch/arm64/include/asm/arch_timer.h             |  38 +++------
>>  drivers/clocksource/Kconfig                     |   8 ++
>>  drivers/clocksource/arm_arch_timer.c            | 105 ++++++++++++++----------
>>  4 files changed, 84 insertions(+), 76 deletions(-)
>>
>> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
>> index 21e2d88..76437ad 100644
>> --- a/Documentation/admin-guide/kernel-parameters.txt
>> +++ b/Documentation/admin-guide/kernel-parameters.txt
>> @@ -539,15 +539,6 @@
>>  			loops can be debugged more effectively on production
>>  			systems.
>>  
>> -	clocksource.arm_arch_timer.fsl-a008585=
>> -			[ARM64]
>> -			Format: <bool>
>> -			Enable/disable the workaround of Freescale/NXP
>> -			erratum A-008585.  This can be useful for KVM
>> -			guests, if the guest device tree doesn't show the
>> -			erratum.  If unspecified, the workaround is
>> -			enabled based on the device tree.
>> -
>>  	clearcpuid=BITNUM [X86]
>>  			Disable CPUID feature X for the kernel. See
>>  			arch/x86/include/asm/cpufeatures.h for the valid bit
>> diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
>> index eaa5bbe..b4b3400 100644
>> --- a/arch/arm64/include/asm/arch_timer.h
>> +++ b/arch/arm64/include/asm/arch_timer.h
>> @@ -29,41 +29,29 @@
>>  
>>  #include <clocksource/arm_arch_timer.h>
>>  
>> -#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585)
>> +#if IS_ENABLED(CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND)
>>  extern struct static_key_false arch_timer_read_ool_enabled;
>> -#define needs_fsl_a008585_workaround() \
>> +#define needs_unstable_timer_counter_workaround() \
>>  	static_branch_unlikely(&arch_timer_read_ool_enabled)
>>  #else
>> -#define needs_fsl_a008585_workaround()  false
>> +#define needs_unstable_timer_counter_workaround()  false
>>  #endif
>>  
>> -u32 __fsl_a008585_read_cntp_tval_el0(void);
>> -u32 __fsl_a008585_read_cntv_tval_el0(void);
>> -u64 __fsl_a008585_read_cntvct_el0(void);
>>  
>> -/*
>> - * The number of retries is an arbitrary value well beyond the highest number
>> - * of iterations the loop has been observed to take.
>> - */
>> -#define __fsl_a008585_read_reg(reg) ({			\
>> -	u64 _old, _new;					\
>> -	int _retries = 200;				\
>> -							\
>> -	do {						\
>> -		_old = read_sysreg(reg);		\
>> -		_new = read_sysreg(reg);		\
>> -		_retries--;				\
>> -	} while (unlikely(_old != _new) && _retries);	\
>> -							\
>> -	WARN_ON_ONCE(!_retries);			\
>> -	_new;						\
>> -})
>> +struct arch_timer_erratum_workaround {
>> +	const char *id;		/* Indicate the Erratum ID */
>> +	u32 (*read_cntp_tval_el0)(void);
>> +	u32 (*read_cntv_tval_el0)(void);
>> +	u64 (*read_cntvct_el0)(void);
>> +};
>> +
>> +extern const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround;
>>  
>>  #define arch_timer_reg_read_stable(reg) 		\
>>  ({							\
>>  	u64 _val;					\
>> -	if (needs_fsl_a008585_workaround())		\
>> -		_val = __fsl_a008585_read_##reg();	\
>> +	if (needs_unstable_timer_counter_workaround())		\
>> +		_val = timer_unstable_counter_workaround->read_##reg();\
>>  	else						\
>>  		_val = read_sysreg(reg);		\
>>  	_val;						\
>> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
>> index 4866f7a..04c2b93 100644
>> --- a/drivers/clocksource/Kconfig
>> +++ b/drivers/clocksource/Kconfig
>> @@ -325,10 +325,18 @@ config ARM_ARCH_TIMER_EVTSTREAM
>>  	  This must be disabled for hardware validation purposes to detect any
>>  	  hardware anomalies of missing events.
>>  
>> +config ARM_ARCH_TIMER_OOL_WORKAROUND
>> +	bool "Workaround for arm arch timer unstable counter"
> 
> Please drop the message. We don't want that option to be selectable by a
> user, but only selected if an erratum that depends on it is enabled.
> 
OK

Thanks
Ding

>> +	depends on FSL_ERRATUM_A008585
>> +	help
>> +	  This option would only be enabled by Freescale/NXP Erratum A-008585
>> +	  or something else chip has similar erratum.
>> +
>>  config FSL_ERRATUM_A008585
>>  	bool "Workaround for Freescale/NXP Erratum A-008585"
>>  	default y
>>  	depends on ARM_ARCH_TIMER && ARM64
>> +	select ARM_ARCH_TIMER_OOL_WORKAROUND
>>  	help
>>  	  This option enables a workaround for Freescale/NXP Erratum
>>  	  A-008585 ("ARM generic timer may contain an erroneous
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply

* Re: [PATCH RESEND v8 1/4] arm64: arch_timer: Add device tree binding for hisilicon-161010101 erratum
From: Ding Tianhong @ 2017-01-19 12:18 UTC (permalink / raw)
  To: Mark Rutland
  Cc: devicetree, marc.zyngier, catalin.marinas, will.deacon,
	stuart.yoder, linuxarm, oss, shawnguo, linux-arm-kernel
In-Reply-To: <20170119121008.GE11176@leverpostej>



On 2017/1/19 20:10, Mark Rutland wrote:
> On Thu, Jan 19, 2017 at 07:46:43PM +0800, Ding Tianhong wrote:
>> This erratum describes a bug in logic outside the core, so MIDR can't be
>> used to identify its presence, and reading an SoC-specific revision
>> register from common arch timer code would be awkward.  So, describe it
>> in the device tree.
>>
>> Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
>> Acked-by: Rob Herring <robh@kernel.org>
>> ---
>>  Documentation/devicetree/bindings/arm/arch_timer.txt | 8 ++++++++
>>  1 file changed, 8 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
>> index ad440a2..9116934 100644
>> --- a/Documentation/devicetree/bindings/arm/arch_timer.txt
>> +++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
>> @@ -31,6 +31,14 @@ to deliver its interrupts via SPIs.
>>    This also affects writes to the tval register, due to the implicit
>>    counter read.
>>  
>> +- hisilicon,erratum-161010101 : A boolean property. Indicates the presence of
>> +  erratum 161010101, which says that reading the counter is unreliable unless
>> +  reading twice on the register and the value of the second read is larger
>> +  than the first by less than 32. If the verification is unsuccessful, then
>> +  discard the value of this read and repeat this procedure until the verification
>> +  is successful.  This also affects writes to the tval register, due to the
>> +  implicit counter read.
> 
> This describes the workaround, which shouldn't be necessary.
> 
> My understanding (from the cover letter) is that reads of the
> {virtual,physical} counters may return a value precisely 32 above the
> true value.
> 
> So it would be better to say:
> 
> - hisilicon,erratum-161010101 : A boolean property. Indicates the
>   presence of Hisilicon erratum 161010101, which says that reading the
>   counters is unreliable in some cases, and reads may return a value 32
>   beyond the correct value. This also affects writes to the tval
>   registers, due to the implicit counter read.
> 
> Thanks,
> Mark.

Looks more accurate.

Thanks.
Ding

> 
> .
> 

^ permalink raw reply

* Re: [PATCH 2/6] usb: mtu3: add reference clock
From: Matthias Brugger @ 2017-01-19 12:22 UTC (permalink / raw)
  To: Chunfeng Yun, Mathias Nyman, Felipe Balbi
  Cc: Greg Kroah-Hartman, Rob Herring, Mark Rutland, Ian Campbell,
	linux-kernel, linux-arm-kernel, linux-usb, linux-mediatek,
	devicetree
In-Reply-To: <1484719707-12107-2-git-send-email-chunfeng.yun@mediatek.com>



On 18/01/17 07:08, Chunfeng Yun wrote:
> usually, the reference clock comes from 26M oscillator directly,
> but some SoCs are not, add it for compatibility.
>
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
>  drivers/usb/mtu3/mtu3.h      |    1 +
>  drivers/usb/mtu3/mtu3_plat.c |   21 +++++++++++++++++++--
>  2 files changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/usb/mtu3/mtu3.h b/drivers/usb/mtu3/mtu3.h
> index ba9df71..aa6fd6a 100644
> --- a/drivers/usb/mtu3/mtu3.h
> +++ b/drivers/usb/mtu3/mtu3.h
> @@ -225,6 +225,7 @@ struct ssusb_mtk {
>  	/* common power & clock */
>  	struct regulator *vusb33;
>  	struct clk *sys_clk;
> +	struct clk *ref_clk;
>  	/* otg */
>  	struct otg_switch_mtk otg_switch;
>  	enum usb_dr_mode dr_mode;
> diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
> index 6344859..19a345d 100644
> --- a/drivers/usb/mtu3/mtu3_plat.c
> +++ b/drivers/usb/mtu3/mtu3_plat.c
> @@ -123,7 +123,13 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb)
>  	ret = clk_prepare_enable(ssusb->sys_clk);
>  	if (ret) {
>  		dev_err(ssusb->dev, "failed to enable sys_clk\n");
> -		goto clk_err;
> +		goto sys_clk_err;
> +	}
> +
> +	ret = clk_prepare_enable(ssusb->ref_clk);
> +	if (ret) {
> +		dev_err(ssusb->dev, "failed to enable ref_clk\n");
> +		goto ref_clk_err;
>  	}
>
>  	ret = ssusb_phy_init(ssusb);
> @@ -143,8 +149,10 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb)
>  phy_err:
>  	ssusb_phy_exit(ssusb);
>  phy_init_err:
> +	clk_disable_unprepare(ssusb->ref_clk);
> +ref_clk_err:
>  	clk_disable_unprepare(ssusb->sys_clk);
> -clk_err:
> +sys_clk_err:
>  	regulator_disable(ssusb->vusb33);
>  vusb33_err:
>
> @@ -154,6 +162,7 @@ static int ssusb_rscs_init(struct ssusb_mtk *ssusb)
>  static void ssusb_rscs_exit(struct ssusb_mtk *ssusb)
>  {
>  	clk_disable_unprepare(ssusb->sys_clk);
> +	clk_disable_unprepare(ssusb->ref_clk);
>  	regulator_disable(ssusb->vusb33);
>  	ssusb_phy_power_off(ssusb);
>  	ssusb_phy_exit(ssusb);
> @@ -216,6 +225,12 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
>  		return PTR_ERR(ssusb->sys_clk);
>  	}
>
> +	ssusb->ref_clk = devm_clk_get(dev, "ref_ck");
> +	if (IS_ERR(ssusb->ref_clk)) {
> +		dev_err(dev, "failed to get ref clock\n");
> +		return PTR_ERR(ssusb->ref_clk);
> +	}
> +

That would break older dts bindings, right?
ref_ck must be optional for the code.

Regards,
Matthias

^ permalink raw reply

* Re: [PATCH 4/6] arm64: dts: mt8173: add reference clock for usb
From: Matthias Brugger @ 2017-01-19 12:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Chunfeng Yun
  Cc: Mathias Nyman, Felipe Balbi, Rob Herring, Mark Rutland,
	Ian Campbell, linux-kernel, linux-arm-kernel, linux-usb,
	linux-mediatek, devicetree
In-Reply-To: <20170119093747.GA17213@kroah.com>



On 19/01/17 10:37, Greg Kroah-Hartman wrote:
> On Wed, Jan 18, 2017 at 02:08:25PM +0800, Chunfeng Yun wrote:
>> add 26M reference clock for ssusb and xhci nodes
>>
>> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
>> ---
>>  arch/arm64/boot/dts/mediatek/mt8173.dtsi |    6 ++++--
>>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> This patch doesn't apply to my tree :(
>

This patch should go through my tree, but take into account my comment 
on patch 3/6. From my point of view this series is not ready to be merged.

Regards,
Matthias

^ permalink raw reply

* [PATCH] ARM: dts: fix SolidRun iMX6 platforms
From: Russell King @ 2017-01-19 12:44 UTC (permalink / raw)
  To: Fabio Estevam, Sascha Hauer
  Cc: Mark Rutland, devicetree, Rob Herring, Shawn Guo,
	linux-arm-kernel

Removal of skeleton.dtsi from imx6qdl.dtsi caused a regression on
SolidRun platforms as the /chosen and /memory nodes are no longer
populated.  Fix this by adding the nodes into the platform .dtsi
files.

Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 4.10.0-rc3+ (rmk@rmk-PC.arm.linux.org.uk) (gcc version 4.7.4 (GCC) ) #2066 SMP Thu Jan 19 12:31:19 GMT 2017
CPU: ARMv7 Processor [412fc09a] revision 10 (ARMv7), cr=10c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
OF: fdt:Machine model: SolidRun Cubox-i Dual/Quad
INITRD: 0x20000000+0x001cd000 is not a memory region - disabling initrd
cma: Failed to reserve 256 MiB
Memory policy: Data cache writealloc
Kernel panic - not syncing: ERROR: Failed to allocate 0x2000 bytes below 0x0.

CPU: 0 PID: 0 Comm: swapper Not tainted 4.10.0-rc3+ #2066
Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
Backtrace: invalid frame pointer 0xc09e5e44c
---[ end Kernel panic - not syncing: ERROR: Failed to allocate 0x2000 bytes below 0x0.

Fixes: 7f107887d199 ("ARM: dts: imx: Remove skeleton.dtsi")
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 arch/arm/boot/dts/imx6qdl-cubox-i.dtsi      | 6 ++++++
 arch/arm/boot/dts/imx6qdl-hummingboard.dtsi | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
index ff41f83551de..69e3a848ee74 100644
--- a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
@@ -44,6 +44,12 @@
 #include <dt-bindings/gpio/gpio.h>
 
 / {
+	chosen {
+		stdout-path = &uart1;
+	};
+
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	ir_recv: ir-receiver {
 		compatible = "gpio-ir-receiver";
 		gpios = <&gpio3 9 1>;
diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi b/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
index a5e5356cdc6a..ae2feb882193 100644
--- a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
@@ -46,6 +46,8 @@
 		stdout-path = &uart1;
 	};
 
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	ir_recv: ir-receiver {
 		compatible = "gpio-ir-receiver";
 		gpios = <&gpio3 5 GPIO_ACTIVE_LOW>;
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH v3 2/2] mmc: pwrseq: add support for Marvell SD8787 chip
From: Ulf Hansson @ 2017-01-19 12:50 UTC (permalink / raw)
  To: Matt Ranostay
  Cc: Shawn Lin, linux-wireless-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Linux Kernel, linux-mmc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Tony Lindgren
In-Reply-To: <CAJ_EiSSQF_2pRaYdUBbKzbHt=1pn3NBrz8C5B7Dta9x7xqZ8oA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On 18 January 2017 at 08:50, Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org> wrote:
> On Sun, Jan 15, 2017 at 6:35 PM, Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org> wrote:
>> On 2017/1/16 5:41, Matt Ranostay wrote:
>>>
>>> On Thu, Jan 12, 2017 at 11:16 PM, Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
>>> wrote:
>>>>
>>>> On 2017/1/13 13:29, Matt Ranostay wrote:
>>>>>
>>>>>
>>>>> Allow power sequencing for the Marvell SD8787 Wifi/BT chip.
>>>>> This can be abstracted to other chipsets if needed in the future.
>>>>>
>>>>> Cc: Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
>>>>> Cc: Ulf Hansson <ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>>>> Signed-off-by: Matt Ranostay <matt-sk+viVC6FLCDq+mSdOJa79kegs52MxvZ@public.gmane.org>
>>>>> ---
>>>>>  drivers/mmc/core/Kconfig         |  10 ++++
>>>>>  drivers/mmc/core/Makefile        |   1 +
>>>>>  drivers/mmc/core/pwrseq_sd8787.c | 117
>>>>> +++++++++++++++++++++++++++++++++++++++
>>>>>  3 files changed, 128 insertions(+)
>>>>>  create mode 100644 drivers/mmc/core/pwrseq_sd8787.c
>>>>>
>>>>> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
>>>>> index cdfa8520a4b1..fc1ecdaaa9ca 100644
>>>>> --- a/drivers/mmc/core/Kconfig
>>>>> +++ b/drivers/mmc/core/Kconfig
>>>>> @@ -12,6 +12,16 @@ config PWRSEQ_EMMC
>>>>>           This driver can also be built as a module. If so, the module
>>>>>           will be called pwrseq_emmc.
>>>>>
>>>>> +config PWRSEQ_SD8787
>>>>> +       tristate "HW reset support for SD8787 BT + Wifi module"
>>>>> +       depends on OF && (MWIFIEX || BT_MRVL_SDIO)
>>>>> +       help
>>>>> +         This selects hardware reset support for the SD8787 BT + Wifi
>>>>> +         module. By default this option is set to n.
>>>>> +
>>>>> +         This driver can also be built as a module. If so, the module
>>>>> +         will be called pwrseq_sd8787.
>>>>> +
>>>>
>>>>
>>>>
>>>> I don't like this way, as we have a chance to list lots
>>>> configure options here. wifi A,B,C,D...Z, all of them need a
>>>> new section here if needed?
>>>>
>>>> Instead, could you just extent pwrseq_simple.c and add you
>>>> .compatible = "mmc-pwrseq-sd8787", "mmc-pwrseq-simple"?
>>>
>>>
>>> You mean all the chipset pwrseqs linked into the pwrseq-simple module?
>>
>>
>> What I mean was if you just extent the pwrseq-simple a bit, you could
>> just add your chipset pwrseqs linked into the pwrseq-simple. But if you
>> need a different *pattern* of pwrseqs, you should need a new name, for
>> instance, pwrseq-sdio.c etc... But please don't use the name of
>> sd8787? So if I use a wifi named ABC but using the same pwrseq pattenr,
>> should I include your "mmc-pwrseq- sd8787" for that or I need a new
>> mmc-pwrseq-ABC.c?
>
> Ah so pwrseq-sdio.c seems reasonable and having chipsets functions
> defined in a structure. That could be abstracted out for other
> chipsets that could needed in the future.

I think get the idea and it seems reasonable. With that in mind, I
have looked at the code once more and I got some new ideas on how to
adopt pwrseq-simple for your case.

I post the comments separately.

Kind regards
Uffe
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v3 09/13] sata: ahci: export ahci_do_hardreset() locally
From: Tejun Heo @ 2017-01-19 12:52 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Kevin Hilman, Sekhar Nori, Patrick Titiano, Michael Turquette,
	Rob Herring, Mark Rutland, Russell King, David Lechner,
	linux-ide-u79uwXL29TY76Z2rM5mHXA, linux-devicetree, LKML, arm-soc
In-Reply-To: <CAMpxmJULuF3cB7+Vy_qeWkTjooHvx8yk70w59Q=XNd0aAREcuw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On Thu, Jan 19, 2017 at 11:55:24AM +0100, Bartosz Golaszewski wrote:
> 2017-01-18 19:28 GMT+01:00 Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>:
> > Hello, Bartosz.
> >
> > On Wed, Jan 18, 2017 at 02:19:57PM +0100, Bartosz Golaszewski wrote:
> >> We need a way to retrieve the information about the online state of
> >> the link in the ahci-da850 driver.
> >>
> >> Create a new function: ahci_do_hardreset() which is called from
> >> ahci_hardreset() for backwards compatibility, but has an additional
> >> argument: 'online' - which can be used to check if the link is online
> >> after this function returns.
> >
> > Please just add @online to ahci_hardreset() and update the callers.
> > Other than that, the sata changes look good to me.
> >
> 
> Are you sure? There are 23 places in drivers/ata/ where the .hardreset
> callback is assigned. I'd prefer not to change the drivers I can't
> test. Besides all other **reset callbacks take three arguments -
> should we really only change one of them for a single driver's needs?

Ah, didn't realize this was the callback, sorry.  What you did is
perfect.  Please disregard my comment.

Thanks.

-- 
tejun
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 1/3] ARM: dts: Add support for phyCORE-AM335x PCM-953 carrier board
From: Teresa Remmet @ 2017-01-19 13:07 UTC (permalink / raw)
  To: linux-omap, devicetree, linux-arm-kernel
  Cc: Tony Lindgren, Mark Rutland, Rob Herring, Wadim Egorov,
	Benoît Cousson

The phyCORE-AM335x development kit is a combination of the
phyCORE-AM335x SoM and a PCM-953 carrier board. The features
of the PCM-953 are:
* ETH phy on carrier board: 1x RGMII
* 1x CAN
* Up to 4x UART
* USB0 (otg)
* USB1 (host)
* SD slot
* User gpio-keys
* User LEDs

Signed-off-by: Teresa Remmet <t.remmet@phytec.de>
Reviewed-by: Wadim Egorov <w.egorov@phytec.de>
---
 .../devicetree/bindings/arm/omap/omap.txt          |   3 +
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/am335x-pcm-953.dtsi              | 303 +++++++++++++++++++++
 arch/arm/boot/dts/am335x-phycore-rdk.dts           |  27 ++
 4 files changed, 334 insertions(+)
 create mode 100644 arch/arm/boot/dts/am335x-pcm-953.dtsi
 create mode 100644 arch/arm/boot/dts/am335x-phycore-rdk.dts

diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
index 05f95c3..8219b2c 100644
--- a/Documentation/devicetree/bindings/arm/omap/omap.txt
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -151,6 +151,9 @@ Boards:
 - AM335X SBC-T335 : single board computer, built around the Sitara AM3352/4
   compatible = "compulab,sbc-t335", "compulab,cm-t335", "ti,am33xx"
 
+- AM335X phyCORE-AM335x: Development kit
+  compatible = "phytec,am335x-pcm-953", "phytec,am335x-phycore-som", "ti,am33xx"
+
 - OMAP5 EVM : Evaluation Module
   compatible = "ti,omap5-evm", "ti,omap5"
 
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 7327250..dd71afe 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -573,6 +573,7 @@ dtb-$(CONFIG_SOC_AM33XX) += \
 	am335x-lxm.dtb \
 	am335x-nano.dtb \
 	am335x-pepper.dtb \
+	am335x-phycore-rdk.dtb \
 	am335x-shc.dtb \
 	am335x-sbc-t335.dtb \
 	am335x-sl50.dtb \
diff --git a/arch/arm/boot/dts/am335x-pcm-953.dtsi b/arch/arm/boot/dts/am335x-pcm-953.dtsi
new file mode 100644
index 0000000..54a171d
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-pcm-953.dtsi
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2014-2017 Phytec Messtechnik GmbH
+ * Author: Wadim Egorov <w.egorov@phytec.de>
+ *	   Teresa Remmet <t.remmet@phytec.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Phytec AM335x PCM-953";
+	compatible = "phytec,am335x-pcm-953", "phytec,am335x-phycore-som", "ti,am33xx";
+
+	user_leds: user_leds {
+		compatible = "gpio-leds";
+	};
+
+	user_buttons: user_buttons {
+		compatible = "gpio-keys";
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		vcc3v3: fixedregulator@1 {
+			compatible = "regulator-fixed";
+		};
+
+		vcc1v8: fixedregulator@2 {
+			compatible = "regulator-fixed";
+		};
+	};
+};
+
+/* CAN */
+&am33xx_pinmux {
+	dcan1_pins: pinmux_dcan1 {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x980, PIN_OUTPUT_PULLUP | MUX_MODE2)	/* uart1_rxd.dcan1_tx_mux2 */
+			AM33XX_IOPAD(0x984, PIN_INPUT_PULLUP | MUX_MODE2)	/* uart1_txd.dcan1_rx_mux2 */
+		>;
+	};
+};
+
+&dcan1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&dcan1_pins>;
+	status = "okay";
+};
+
+/* Ethernet */
+&am33xx_pinmux {
+	ethernet1_pins: pinmux_ethernet1 {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a0.rgmii2_tctl */
+			AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a1.rgmii2_rctl */
+			AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a2.rgmii2_td3 */
+			AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a3.rgmii2_td2 */
+			AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a4.rgmii2_td1 */
+			AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a5.rgmii2_td0 */
+			AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a6.rgmii2_tclk */
+			AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a7.rgmii2_rclk */
+			AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a8.rgmii2_rd3 */
+			AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a9.rgmii2_rd2 */
+			AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a10.rgmii2_rd1 */
+			AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a11.rgmii2_rd0 */
+		>;
+	};
+};
+
+&cpsw_emac1 {
+	phy-handle = <&phy1>;
+	phy-mode = "rgmii-id";
+	dual_emac_res_vlan = <2>;
+	status = "okay";
+};
+
+&davinci_mdio {
+	phy1: ethernet-phy@1 {
+		reg = <2>;
+
+		/* Register 260 (104h) – RGMII Clock and Control Pad Skew */
+		rxc-skew-ps = <1400>;
+		rxdv-skew-ps = <0>;
+		txc-skew-ps = <1400>;
+		txen-skew-ps = <0>;
+		/* Register 261 (105h) – RGMII RX Data Pad Skew */
+		rxd3-skew-ps = <0>;
+		rxd2-skew-ps = <0>;
+		rxd1-skew-ps = <0>;
+		rxd0-skew-ps = <0>;
+		/* Register 262 (106h) – RGMII TX Data Pad Skew */
+		txd3-skew-ps = <0>;
+		txd2-skew-ps = <0>;
+		txd1-skew-ps = <0>;
+		txd0-skew-ps = <0>;
+	};
+};
+
+&mac {
+	slaves = <2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&ethernet0_pins &ethernet1_pins>;
+	dual_emac;
+};
+
+/* Misc */
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&cb_gpio_pins>;
+
+	cb_gpio_pins: pinmux_cb_gpio {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x968, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* uart0_ctsn.gpio1_8 */
+			AM33XX_IOPAD(0x96c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* uart0_rtsn.gpio1_9 */
+		>;
+	};
+};
+
+/* MMC */
+&am33xx_pinmux {
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat3.mmc0_dat3 */
+			AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat2.mmc0_dat2 */
+			AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat1.mmc0_dat1 */
+			AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat0.mmc0_dat0 */
+			AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_clk.mmc0_clk */
+			AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_cmd.mmc0_cmd */
+			AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE7)	/* spi0_cs1.mmc0_sdcd */
+		>;
+	};
+};
+
+&mmc1 {
+	vmmc-supply = <&vcc3v3>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+/* Power */
+&vcc3v3 {
+	regulator-name = "vcc3v3";
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-boot-on;
+};
+
+&vcc1v8 {
+	regulator-name = "vcc1v8";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-boot-on;
+};
+
+/* UARTs */
+&am33xx_pinmux {
+	uart0_pins: pinmux_uart0 {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	uart1_pins: pinmux_uart1 {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart1_rxd.uart1_rxd */
+			AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart1_txd.uart1_txd */
+			AM33XX_IOPAD(0x978, PIN_INPUT | MUX_MODE0)		/* uart1_ctsn.uart1_ctsn */
+			AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart1_rtsn.uart1_rtsn */
+		>;
+	};
+
+	uart2_pins: pinmux_uart2 {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE1)	/* mii1_tx_clk.uart2_rxd */
+			AM33XX_IOPAD(0x930, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_rx_clk.uart2_txd */
+		>;
+	};
+
+	uart3_pins: pinmux_uart3 {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE1)	/* mii1_rxd3.uart3_rxd */
+			AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_rxd2.uart3_txd */
+		>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+	status = "okay";
+};
+
+/* USB */
+&cppi41dma {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+/* User IO */
+&am33xx_pinmux {
+	user_buttons_pins: pinmux_user_buttons {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9e4, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* emu0.gpio3_7 */
+			AM33XX_IOPAD(0x9e8, PIN_INPUT_PULLDOWN | MUX_MODE7)	/* emu1.gpio3_8 */
+		>;
+	};
+
+	user_leds_pins: pinmux_user_leds {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x880, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_csn1.gpio1_30 */
+			AM33XX_IOPAD(0x884, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_csn2.gpio1_31 */
+		>;
+	};
+};
+
+&user_buttons {
+	pinctrl-names = "default";
+	pinctrl-0 = <&user_buttons_pins>;
+	status = "okay";
+
+	button@0 {
+		label = "home";
+		linux,code = <KEY_HOME>;
+		gpios = <&gpio3 7 GPIO_ACTIVE_HIGH>;
+		gpio-key,wakeup;
+	};
+
+	button@1 {
+		label = "menu";
+		linux,code = <KEY_MENU>;
+		gpios = <&gpio3 8 GPIO_ACTIVE_HIGH>;
+		gpio-key,wakeup;
+	};
+};
+
+&user_leds {
+	pinctrl-names = "default";
+	pinctrl-0 = <&user_leds_pins>;
+	status = "okay";
+
+	green {
+		label = "green:user";
+		gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>;
+		linux,default-trigger = "gpio";
+		default-state = "on";
+	};
+
+	yellow {
+		label = "yellow:user";
+		gpios = <&gpio1 31 GPIO_ACTIVE_LOW>;
+		linux,default-trigger = "gpio";
+		default-state = "on";
+	};
+};
diff --git a/arch/arm/boot/dts/am335x-phycore-rdk.dts b/arch/arm/boot/dts/am335x-phycore-rdk.dts
new file mode 100644
index 0000000..305f0b3
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-phycore-rdk.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2014 PHYTEC Messtechnik GmbH
+ * Author: Wadim Egorov <w.egorov@phytec.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include "am335x-phycore-som.dtsi"
+#include "am335x-pcm-953.dtsi"
+
+/* SoM */
+&i2c_eeprom {
+	status = "okay";
+};
+
+&i2c_rtc {
+	status = "okay";
+};
+
+&serial_flash {
+	status = "okay";
+
+};
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH 2/3] ARM: configs: omap2plus_defconfig: Enable support for micrell phys
From: Teresa Remmet @ 2017-01-19 13:07 UTC (permalink / raw)
  To: linux-omap, devicetree, linux-arm-kernel
  Cc: Tony Lindgren, Mark Rutland, Rob Herring, Wadim Egorov,
	Benoît Cousson
In-Reply-To: <1484831270-7251-1-git-send-email-t.remmet@phytec.de>

The phyCORE-AM335x SoM with PCM-953 carrierboard has a
KSZ9021 phy mounted. To add support for this we need to enable
the micrell phy driver in the config.

Signed-off-by: Teresa Remmet <t.remmet@phytec.de>
---
 arch/arm/configs/omap2plus_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index 195c98b..0c2bf2d 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -168,6 +168,7 @@ CONFIG_TI_CPTS=y
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_AT803X_PHY=y
+CONFIG_MICREL_PHY=y
 CONFIG_SMSC_PHY=y
 CONFIG_USB_USBNET=m
 CONFIG_USB_NET_SMSC75XX=m
-- 
1.9.1

^ permalink raw reply related

* [PATCH 3/3] ARM: configs: omap2plus_defconfig: Enable support for RTC M41T80
From: Teresa Remmet @ 2017-01-19 13:07 UTC (permalink / raw)
  To: linux-omap, devicetree, linux-arm-kernel
  Cc: Tony Lindgren, Mark Rutland, Rob Herring, Wadim Egorov,
	Benoît Cousson
In-Reply-To: <1484831270-7251-1-git-send-email-t.remmet@phytec.de>

The phyCORE-AM335x SoM has a RV4162 RTC populated which is supported
by the M41T80 driver. Enabled it so make the RTC support on the SoM
available.

Signed-off-by: Teresa Remmet <t.remmet@phytec.de>
---
 arch/arm/configs/omap2plus_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index 0c2bf2d..75b5b73 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -414,6 +414,7 @@ CONFIG_LEDS_TRIGGER_GPIO=m
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_M41T80=m
 CONFIG_RTC_DRV_TWL92330=y
 CONFIG_RTC_DRV_TWL4030=m
 CONFIG_RTC_DRV_PALMAS=m
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH v3] iio: max5481: Add support for Maxim digital potentiometers
From: Rob Herring @ 2017-01-19 13:09 UTC (permalink / raw)
  To: Slawomir Stepien
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
	matthew.weber-lFk7bPDcGtkY5TsXZYaR1UEOCMrvLtNR,
	maury.anderson-lFk7bPDcGtkY5TsXZYaR1UEOCMrvLtNR,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mark Rutland
In-Reply-To: <20170114212139.GA3418-SwUeJysX96B82hYKe6nXyg@public.gmane.org>

On Sat, Jan 14, 2017 at 10:21:39PM +0100, Slawomir Stepien wrote:
> From: Matt Weber <matthew.weber-lFk7bPDcGtkY5TsXZYaR1UEOCMrvLtNR@public.gmane.org>
> 
> Add implementation for Maxim Integrated 5481, 5482, 5483,
> and 5484 digital potentiometer devices.
> 
> Datasheet:
> http://datasheets.maximintegrated.com/en/ds/MAX5481-MAX5484.pdf
> 
> Signed-off-by: Maury Anderson <maury.anderson-lFk7bPDcGtkY5TsXZYaR1UEOCMrvLtNR@public.gmane.org>
> Signed-off-by: Matthew Weber <matthew.weber-lFk7bPDcGtkY5TsXZYaR1UEOCMrvLtNR@public.gmane.org>
> Signed-off-by: Slawomir Stepien <sst-IjDXvh/HVVUAvxtiuMwx3w@public.gmane.org>
> ---
> 
> This is my resubmission of this patch after original authors decided not to
> pursuit it inclusion into kernel.
> 
> Tested using signal analyzer.
> 
> Changes since v2:
> * spi write buffer moved to struct max5481_data and ____cacheline_aligned.
> * max5481_write_cmd now uses pointer to struct max5481_data as a first argument.
> 
> Changes since v1:
> * removed not needed '``' and 'c' chars
> * includes are now sorted
> * added coma to last item in enum max5481_variant
> * removed maxpos from struct max5481_cfg
> * max5481_CHANNEL is no MAX5481_CHANNEL and it does not have 'ch' argument
> * max5481_write_cmd is now based around switch
> * removed not needed cast in max5481_write_cmd
> * wpier state is saved after iio_device_unregister
> * changed names in spi_device_id and acpi_device_id to be equal to names in of_device_id
> 
> ---
>  .../bindings/iio/potentiometer/max5481.txt         |  23 +++

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

>  drivers/iio/potentiometer/Kconfig                  |  11 ++
>  drivers/iio/potentiometer/Makefile                 |   1 +
>  drivers/iio/potentiometer/max5481.c                | 216 +++++++++++++++++++++
>  4 files changed, 251 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/potentiometer/max5481.txt
>  create mode 100644 drivers/iio/potentiometer/max5481.c

^ permalink raw reply

* Re: [PATCH v2] Documentation: usb: fix wrong documentation paths
From: Rob Herring @ 2017-01-19 13:11 UTC (permalink / raw)
  To: Yegor Yefremov
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170115121428.3255-1-yegorslists-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

On Sun, Jan 15, 2017 at 01:14:28PM +0100, Yegor Yefremov wrote:
> Fixes wrong spelled "pinctrl-bindings.txt" and "qcom-dwc3-usb-phy.txt"
> file names as also wrong specified "mt8173-mtu3.txt" file name.
> 
> Signed-off-by: Yegor Yefremov <yegorslists-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
> ---
> Changes:
> 	v1 -> v2: add changelog text (Greg Kroah-Hartman)
> 
>  Documentation/devicetree/bindings/usb/dwc3-st.txt     | 4 ++--
>  Documentation/devicetree/bindings/usb/ehci-st.txt     | 2 +-
>  Documentation/devicetree/bindings/usb/mt8173-mtu3.txt | 2 +-
>  Documentation/devicetree/bindings/usb/mt8173-xhci.txt | 4 ++--
>  Documentation/devicetree/bindings/usb/qcom,dwc3.txt   | 2 +-
>  5 files changed, 7 insertions(+), 7 deletions(-)

Applied, thanks.

Rob
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 4/5] fbdev/ssd1307fb: add support to enable VBAT
From: Tomi Valkeinen @ 2017-01-19 13:15 UTC (permalink / raw)
  To: Rob Herring, Jyri Sarha
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	b.zolnierkie-Sze3O3UU22JBDgjK7y7TUQ,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	bcousson-rdvid1DuHRBWk0Htik3J/w
In-Reply-To: <20170118223310.kxbgq47v7cl33ls3@rob-hp-laptop>


[-- Attachment #1.1: Type: text/plain, Size: 1572 bytes --]

On 19/01/17 00:33, Rob Herring wrote:
> On Fri, Jan 13, 2017 at 12:35:48PM +0200, Jyri Sarha wrote:
>> From: Tomi Valkeinen <tomi.valkeinen-l0cyMroinI0@public.gmane.org>
>>
>> SSD1306 needs VBAT when it is wired in charge pump configuration. This
>> patch adds support to the driver to enable VBAT regulator at init time.
>>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen-l0cyMroinI0@public.gmane.org>
>> Reviewed-by: Roger Quadros <rogerq-l0cyMroinI0@public.gmane.org>
>> Signed-off-by: Jyri Sarha <jsarha-l0cyMroinI0@public.gmane.org>
>> ---
>>  .../devicetree/bindings/display/ssd1307fb.txt        |  1 +
>>  drivers/video/fbdev/ssd1307fb.c                      | 20 +++++++++++++++++++-
>>  2 files changed, 20 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/devicetree/bindings/display/ssd1307fb.txt b/Documentation/devicetree/bindings/display/ssd1307fb.txt
>> index 6617df6..209d931 100644
>> --- a/Documentation/devicetree/bindings/display/ssd1307fb.txt
>> +++ b/Documentation/devicetree/bindings/display/ssd1307fb.txt
>> @@ -16,6 +16,7 @@ Required properties:
>>  Optional properties:
>>    - reset-gpios: The GPIO used to reset the OLED display, if available. See
>>                   Documentation/devicetree/bindings/gpio/gpio.txt for details.
>> +  - vbat-supply: The supply for VBAT
> 
> According to the datasheet, SSD1307 has 2 supplies: Vdd and Vcc
> 
> I don't see any mention of a charge pump, so that must be an external 
> component.

VBAT is for SSD1306. Perhaps the DT doc should mention it.

 Tomi


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* [PATCH v10 0/5] Add support for the STM32F4 I2C
From: M'boumba Cedric Madianga @ 2017-01-19 13:25 UTC (permalink / raw)
  To: wsa, robh+dt, mcoquelin.stm32, alexandre.torgue, linus.walleij,
	patrice.chotard, linux, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel, u.kleine-koenig
  Cc: M'boumba Cedric Madianga

This patchset adds support for the I2C controller embedded in STM32F4xx SoC.
It enables I2C transfer in interrupt mode with Standard-mode and Fast-mode bus
speed.

Changes since v9:
- Fix minor typo in some comments
- Add some comments to explain how the driver check TRISE and CCR value have
  no chance of overflow

Changes since v8:
- Rework I2C Clock Control Register computation (Uwe)
- Save register accesses as often as possible (Uwe)
- Don't use mask before saving rx buffer (Uwe)
- Add more comments to explain hardware way of working (Uwe)
- Rename stm32f4_i2c_handle_rx_btf function by stm32f4_i2c_handle_rx_done (Uwe)
- Set/Clear Ack position bit during address match phase

Changes since v7:
- Remove unneeded parenthesis in some macro definitions (Uwe)
- Fix some typo (s/KhzkHZ, s/PEC/POC) (Uwe)
- Fix alignment issues in some structures declaration (Uwe)
- Clarify comments to argue i2c_timing values chosen (Uwe)
- Raise an error if parent clk rate is out of scope during I2C hw config (Uwe)
- Use dev_dbg instead of dev_err message when I2C bus is busy  (Uwe)
- Add more comments about stuff done by stm32f4_i2c_handle_rx_btf() (Uwe)
- Simplify stm32f4_i2c_isr_error() routine implementation by removing possible
  status checking (Uwe)
- Rework stm32f4_i2c_isr_error() routine by removing the loop to check which
  status occured  (Uwe)
- Add open-drain property for SCL pins  (Uwe)
- Rework unneeded mul_ccr field from i2c_timing structure
- Remove min_ccr field from i2c_timing structure as default scl_period is chosen
  to have a correct minimal ccr value
- Execute hw_config once during probe
- Remove soft_reset after an I2C error as all errors are now handled and
  hw_config is done once during probe
- Generate STOP by software when Acknowledge failure occurs
- Set the max speed mode for I2C pins
- Add bias-disable property for I2C pins
- Use intrinsic limitation of APB bus to set I2C max input clk

Changes since v6:
- Add commit message for the patches in defconfig, .dtsi and .dts files (Alex)
- Order I2C instance base address in .dtsi file (Alex)
- Add commit message for the patch in stm32429i-eval.dts  (Alex)
- Add link to the STM32F4 Soc ref manual where I2C device is described (Uwe)
- Use more usal way to define constants with several lines (Uwe)
- Remove rate variable from stm32f4_i2c_timings as it is not used (Uwe)
- Remove irq variable from stm32f4_i2c_dev struct are they are only needed
  during probe (Uwe)
- Add comment from datasheet to explain stm32f4_i2c_timings values (Uwe)
- Rework i2c soft_reset implementation (Uwe)
- Replace "it" by "irq" as it is a more usual abbreviation for interrupt (Uwe)
- Add comment from datasheet to explain periph clk freq calculation (Uwe)
- Use DIV_ROUND_UP instead of plain division when required (Uwe)
- Add comment from datasheet to explain timing rise calculation (Uwe)
- Rework timing rise calculation by using shorter computation (Uwe)
- Remove (u8) cast when reading I2C data register (Uwe)
- Rework isr_event routine to handle several events during one call of the
  routine (Uwe)
- Precise which type of irq is failed when a irq request error occurs (Uwe)
- Use devm_request_irq() instead of devm_request_threaded_irq() to avoid
  spurious evt irq when clearing status registers in threaded context

Changes since v5:
- Change commit header from "ARM: dts:" to "ARM: dts: stm32:" (Alex)
- Change commit header from "ARM: configs:" to "ARM: configs: stm32:" (Alex)
- Fix warnings due to variable set but unused (Wolfram)
- Remove double space in Kconfig (Wolfram)
- Fix warning due to bad type parameter when using clamp() function
  (build-bot)

Changes since v4:
- Use clamp() function to use a value in a given range as it was missed in V4

Changes since v3 after Wolfram's review:
- Add COMPILE_TEST flag in Kconfig
- Use correct driver name in Kconfig i.e i2c-stm32f4 instead of i2c-st
- Use more comprehensible name stm32f4_i2c_msg for client specific data
- Don't store reset control node as just needed in probe
- Use clamp() function to test value between 2 ranges
- Use new "i2c_8bit_addr_from_msg() function to build I2C address
- Don't write error messages for timeout
- Remove error message when i2c_add_adapter() fails as it is already handled by
  the i2c core driver

Changes since v2:
- remove interrupt configuration management from DT
- remove FIFO configuration management from DT except threshold as it is very
  hard to handle it in the driver due to many possible combinations according
  to burst and bus width
- update DMA client message in DT documentation file
- specify the order to be used to set per-channel DMA interrupts in the DT
- remove unused enumerations for channel and request ids
- keep as soon as possible 80 lines char for more readability
- replace unsigned int by u32
- return error if burst is not supported in stm32_dma_get_burst()
- return error if bus_width is not supported in stm32_dma_get_width()
- add FIFO configuration management inside the driver except for threshold
- add interrupt configuration management inside the driver
- rework stm32_dma_chan_irq() to handle error interrupt in one way
- rework stm32_dma_set_xfer_param() to be easier to read
- update stm32_dma_tx_status() to always return status from dma_cookie_status()
- disable clk if we don't manage to stop the DMA channel during channel
  resources allocation
- set driver as built-in as DMA will be required by other built-in driver

Changes since v1:
- use compatible st,stm32f4-i2c instead of st,i2c-stm32f4 (Rob)
- fix typo s/enmpty/empty (Maxime)
- use one function to handle TX fifo empty and byte xfer finished IT (Maxime)
- set duty cycle in timing struct in Fast mode
- Rework clock management (call prepare/unprepare at probe and remove, call
  clk_enable/clk_disable for each I2C transfer)

M'boumba Cedric Madianga (5):
  dt-bindings: Document the STM32 I2C bindings
  i2c: Add STM32F4 I2C driver
  ARM: dts: stm32: Add I2C1 support for STM32F429 SoC
  ARM: dts: stm32: Add I2C1 support for STM32429 eval board
  ARM: configs: stm32: Add I2C support for STM32 defconfig

 .../devicetree/bindings/i2c/i2c-stm32.txt          |  33 +
 arch/arm/boot/dts/stm32429i-eval.dts               |   6 +
 arch/arm/boot/dts/stm32f429.dtsi                   |  23 +
 arch/arm/configs/stm32_defconfig                   |   3 +
 drivers/i2c/busses/Kconfig                         |  10 +
 drivers/i2c/busses/Makefile                        |   1 +
 drivers/i2c/busses/i2c-stm32f4.c                   | 897 +++++++++++++++++++++
 7 files changed, 973 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-stm32.txt
 create mode 100644 drivers/i2c/busses/i2c-stm32f4.c

-- 
1.9.1

^ permalink raw reply

* [PATCH v10 1/5] dt-bindings: Document the STM32 I2C bindings
From: M'boumba Cedric Madianga @ 2017-01-19 13:25 UTC (permalink / raw)
  To: wsa, robh+dt, mcoquelin.stm32, alexandre.torgue, linus.walleij,
	patrice.chotard, linux, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel, u.kleine-koenig
  Cc: M'boumba Cedric Madianga
In-Reply-To: <1484832316-5594-1-git-send-email-cedric.madianga@gmail.com>

This patch adds documentation of device tree bindings for the STM32 I2C
controller.

Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
Acked-by: Rob Herring <robh@kernel.org>
---
 .../devicetree/bindings/i2c/i2c-stm32.txt          | 33 ++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-stm32.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-stm32.txt b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt
new file mode 100644
index 0000000..78eaf7b
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-stm32.txt
@@ -0,0 +1,33 @@
+* I2C controller embedded in STMicroelectronics STM32 I2C platform
+
+Required properties :
+- compatible : Must be "st,stm32f4-i2c"
+- reg : Offset and length of the register set for the device
+- interrupts : Must contain the interrupt id for I2C event and then the
+  interrupt id for I2C error.
+- resets: Must contain the phandle to the reset controller.
+- clocks: Must contain the input clock of the I2C instance.
+- A pinctrl state named "default" must be defined to set pins in mode of
+  operation for I2C transfer
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties :
+- clock-frequency : Desired I2C bus clock frequency in Hz. If not specified,
+  the default 100 kHz frequency will be used. As only Normal and Fast modes
+  are supported, possible values are 100000 and 400000.
+
+Example :
+
+	i2c@40005400 {
+		compatible = "st,stm32f4-i2c";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x40005400 0x400>;
+		interrupts = <31>,
+			     <32>;
+		resets = <&rcc 277>;
+		clocks = <&rcc 0 149>;
+		pinctrl-0 = <&i2c1_sda_pin>, <&i2c1_scl_pin>;
+		pinctrl-names = "default";
+	};
-- 
1.9.1

^ permalink raw reply related

* [PATCH v10 2/5] i2c: Add STM32F4 I2C driver
From: M'boumba Cedric Madianga @ 2017-01-19 13:25 UTC (permalink / raw)
  To: wsa, robh+dt, mcoquelin.stm32, alexandre.torgue, linus.walleij,
	patrice.chotard, linux, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel, u.kleine-koenig
  Cc: M'boumba Cedric Madianga
In-Reply-To: <1484832316-5594-1-git-send-email-cedric.madianga@gmail.com>

This patch adds support for the STM32F4 I2C controller.

Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
---
 drivers/i2c/busses/Kconfig       |  10 +
 drivers/i2c/busses/Makefile      |   1 +
 drivers/i2c/busses/i2c-stm32f4.c | 897 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 908 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-stm32f4.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 0cdc844..2719208 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -886,6 +886,16 @@ config I2C_ST
 	  This driver can also be built as module. If so, the module
 	  will be called i2c-st.
 
+config I2C_STM32F4
+	tristate "STMicroelectronics STM32F4 I2C support"
+	depends on ARCH_STM32 || COMPILE_TEST
+	help
+	  Enable this option to add support for STM32 I2C controller embedded
+	  in STM32F4 SoCs.
+
+	  This driver can also be built as module. If so, the module
+	  will be called i2c-stm32f4.
+
 config I2C_STU300
 	tristate "ST Microelectronics DDC I2C interface"
 	depends on MACH_U300
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 1c1bac8..a2c6ff5 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_I2C_SH_MOBILE)	+= i2c-sh_mobile.o
 obj-$(CONFIG_I2C_SIMTEC)	+= i2c-simtec.o
 obj-$(CONFIG_I2C_SIRF)		+= i2c-sirf.o
 obj-$(CONFIG_I2C_ST)		+= i2c-st.o
+obj-$(CONFIG_I2C_STM32F4)	+= i2c-stm32f4.o
 obj-$(CONFIG_I2C_STU300)	+= i2c-stu300.o
 obj-$(CONFIG_I2C_SUN6I_P2WI)	+= i2c-sun6i-p2wi.o
 obj-$(CONFIG_I2C_TEGRA)		+= i2c-tegra.o
diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c
new file mode 100644
index 0000000..f9dd7e8
--- /dev/null
+++ b/drivers/i2c/busses/i2c-stm32f4.c
@@ -0,0 +1,897 @@
+/*
+ * Driver for STMicroelectronics STM32 I2C controller
+ *
+ * This I2C controller is described in the STM32F429/439 Soc reference manual.
+ * Please see below a link to the documentation:
+ * http://www.st.com/resource/en/reference_manual/DM00031020.pdf
+ *
+ * Copyright (C) M'boumba Cedric Madianga 2016
+ * Author: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
+ *
+ * This driver is based on i2c-st.c
+ *
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+/* STM32F4 I2C offset registers */
+#define STM32F4_I2C_CR1			0x00
+#define STM32F4_I2C_CR2			0x04
+#define STM32F4_I2C_DR			0x10
+#define STM32F4_I2C_SR1			0x14
+#define STM32F4_I2C_SR2			0x18
+#define STM32F4_I2C_CCR			0x1C
+#define STM32F4_I2C_TRISE		0x20
+#define STM32F4_I2C_FLTR		0x24
+
+/* STM32F4 I2C control 1*/
+#define STM32F4_I2C_CR1_POS		BIT(11)
+#define STM32F4_I2C_CR1_ACK		BIT(10)
+#define STM32F4_I2C_CR1_STOP		BIT(9)
+#define STM32F4_I2C_CR1_START		BIT(8)
+#define STM32F4_I2C_CR1_PE		BIT(0)
+
+/* STM32F4 I2C control 2 */
+#define STM32F4_I2C_CR2_FREQ_MASK	GENMASK(5, 0)
+#define STM32F4_I2C_CR2_FREQ(n)		((n) & STM32F4_I2C_CR2_FREQ_MASK)
+#define STM32F4_I2C_CR2_ITBUFEN		BIT(10)
+#define STM32F4_I2C_CR2_ITEVTEN		BIT(9)
+#define STM32F4_I2C_CR2_ITERREN		BIT(8)
+#define STM32F4_I2C_CR2_IRQ_MASK	(STM32F4_I2C_CR2_ITBUFEN | \
+					 STM32F4_I2C_CR2_ITEVTEN | \
+					 STM32F4_I2C_CR2_ITERREN)
+
+/* STM32F4 I2C Status 1 */
+#define STM32F4_I2C_SR1_AF		BIT(10)
+#define STM32F4_I2C_SR1_ARLO		BIT(9)
+#define STM32F4_I2C_SR1_BERR		BIT(8)
+#define STM32F4_I2C_SR1_TXE		BIT(7)
+#define STM32F4_I2C_SR1_RXNE		BIT(6)
+#define STM32F4_I2C_SR1_BTF		BIT(2)
+#define STM32F4_I2C_SR1_ADDR		BIT(1)
+#define STM32F4_I2C_SR1_SB		BIT(0)
+#define STM32F4_I2C_SR1_ITEVTEN_MASK	(STM32F4_I2C_SR1_BTF | \
+					 STM32F4_I2C_SR1_ADDR | \
+					 STM32F4_I2C_SR1_SB)
+#define STM32F4_I2C_SR1_ITBUFEN_MASK	(STM32F4_I2C_SR1_TXE | \
+					 STM32F4_I2C_SR1_RXNE)
+#define STM32F4_I2C_SR1_ITERREN_MASK	(STM32F4_I2C_SR1_AF | \
+					 STM32F4_I2C_SR1_ARLO | \
+					 STM32F4_I2C_SR1_BERR)
+
+/* STM32F4 I2C Status 2 */
+#define STM32F4_I2C_SR2_BUSY		BIT(1)
+
+/* STM32F4 I2C Control Clock */
+#define STM32F4_I2C_CCR_CCR_MASK	GENMASK(11, 0)
+#define STM32F4_I2C_CCR_CCR(n)		((n) & STM32F4_I2C_CCR_CCR_MASK)
+#define STM32F4_I2C_CCR_FS		BIT(15)
+#define STM32F4_I2C_CCR_DUTY		BIT(14)
+
+/* STM32F4 I2C Trise */
+#define STM32F4_I2C_TRISE_VALUE_MASK	GENMASK(5, 0)
+#define STM32F4_I2C_TRISE_VALUE(n)	((n) & STM32F4_I2C_TRISE_VALUE_MASK)
+
+#define STM32F4_I2C_MIN_STANDARD_FREQ	2U
+#define STM32F4_I2C_MIN_FAST_FREQ	6U
+#define STM32F4_I2C_MAX_FREQ		46U
+#define HZ_TO_MHZ			1000000
+
+enum stm32f4_i2c_speed {
+	STM32F4_I2C_SPEED_STANDARD, /* 100 kHz */
+	STM32F4_I2C_SPEED_FAST, /* 400 kHz */
+	STM32F4_I2C_SPEED_END,
+};
+
+/**
+ * struct stm32f4_i2c_msg - client specific data
+ * @addr: 8-bit slave addr, including r/w bit
+ * @count: number of bytes to be transferred
+ * @buf: data buffer
+ * @result: result of the transfer
+ * @stop: last I2C msg to be sent, i.e. STOP to be generated
+ */
+struct stm32f4_i2c_msg {
+	u8 addr;
+	u32 count;
+	u8 *buf;
+	int result;
+	bool stop;
+};
+
+/**
+ * struct stm32f4_i2c_dev - private data of the controller
+ * @adap: I2C adapter for this controller
+ * @dev: device for this controller
+ * @base: virtual memory area
+ * @complete: completion of I2C message
+ * @clk: hw i2c clock
+ * @speed: I2C clock frequency of the controller. Standard or Fast are supported
+ * @parent_rate: I2C clock parent rate in MHz
+ * @msg: I2C transfer information
+ */
+struct stm32f4_i2c_dev {
+	struct i2c_adapter adap;
+	struct device *dev;
+	void __iomem *base;
+	struct completion complete;
+	struct clk *clk;
+	int speed;
+	int parent_rate;
+	struct stm32f4_i2c_msg msg;
+};
+
+static inline void stm32f4_i2c_set_bits(void __iomem *reg, u32 mask)
+{
+	writel_relaxed(readl_relaxed(reg) | mask, reg);
+}
+
+static inline void stm32f4_i2c_clr_bits(void __iomem *reg, u32 mask)
+{
+	writel_relaxed(readl_relaxed(reg) & ~mask, reg);
+}
+
+static void stm32f4_i2c_disable_irq(struct stm32f4_i2c_dev *i2c_dev)
+{
+	void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+	stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_IRQ_MASK);
+}
+
+static int stm32f4_i2c_set_periph_clk_freq(struct stm32f4_i2c_dev *i2c_dev)
+{
+	u32 freq;
+	u32 cr2 = 0;
+
+	i2c_dev->parent_rate = clk_get_rate(i2c_dev->clk);
+	freq = DIV_ROUND_UP(i2c_dev->parent_rate, HZ_TO_MHZ);
+
+	if (i2c_dev->speed == STM32F4_I2C_SPEED_STANDARD) {
+		/*
+		 * To reach 100 kHz, the parent clk frequency should be between
+		 * a minimum value of 2 MHz and a maximum value of 46 MHz due
+		 * to hardware limitation
+		 */
+		if (freq < STM32F4_I2C_MIN_STANDARD_FREQ ||
+		    freq > STM32F4_I2C_MAX_FREQ) {
+			dev_err(i2c_dev->dev,
+				"bad parent clk freq for standard mode\n");
+			return -EINVAL;
+		}
+	} else {
+		/*
+		 * To be as close as possible to 400 kHz, the parent clk
+		 * frequency should be between a minimum value of 6 MHz and a
+		 * maximum value of 46 MHz due to hardware limitation
+		 */
+		if (freq < STM32F4_I2C_MIN_FAST_FREQ ||
+		    freq > STM32F4_I2C_MAX_FREQ) {
+			dev_err(i2c_dev->dev,
+				"bad parent clk freq for fast mode\n");
+			return -EINVAL;
+		}
+	}
+
+	cr2 |= STM32F4_I2C_CR2_FREQ(freq);
+	writel_relaxed(cr2, i2c_dev->base + STM32F4_I2C_CR2);
+
+	return 0;
+}
+
+static void stm32f4_i2c_set_rise_time(struct stm32f4_i2c_dev *i2c_dev)
+{
+	u32 freq = DIV_ROUND_UP(i2c_dev->parent_rate, HZ_TO_MHZ);
+	u32 trise;
+
+	/*
+	 * These bits must be programmed with the maximum SCL rise time given in
+	 * the I2C bus specification, incremented by 1.
+	 *
+	 * In standard mode, the maximum allowed SCL rise time is 1000 ns.
+	 * If, in the I2C_CR2 register, the value of FREQ[5:0] bits is equal to
+	 * 0x08 so period = 125 ns therefore the TRISE[5:0] bits must be
+	 * programmed with 0x9. (1000 ns / 125 ns + 1)
+	 * So, for I2C standard mode TRISE = FREQ[5:0] + 1
+	 *
+	 * In fast mode, the maximum allowed SCL rise time is 300 ns.
+	 * If, in the I2C_CR2 register, the value of FREQ[5:0] bits is equal to
+	 * 0x08 so period = 125 ns therefore the TRISE[5:0] bits must be
+	 * programmed with 0x3. (300 ns / 125 ns + 1)
+	 * So, for I2C fast mode TRISE = FREQ[5:0] * 300 / 1000 + 1
+	 *
+	 * Function stm32f4_i2c_set_periph_clk_freq made sure that parent rate
+	 * is not higher than 46 MHz . As a result trise is at most 4 bits wide
+	 * and so fits into the TRISE bits [5:0].
+	 */
+	if (i2c_dev->speed == STM32F4_I2C_SPEED_STANDARD)
+		trise = freq + 1;
+	else
+		trise = freq * 3 / 10 + 1;
+
+	writel_relaxed(STM32F4_I2C_TRISE_VALUE(trise),
+		       i2c_dev->base + STM32F4_I2C_TRISE);
+}
+
+static void stm32f4_i2c_set_speed_mode(struct stm32f4_i2c_dev *i2c_dev)
+{
+	u32 val;
+	u32 ccr = 0;
+
+	if (i2c_dev->speed == STM32F4_I2C_SPEED_STANDARD) {
+		/*
+		 * In standard mode:
+		 * t_scl_high = t_scl_low = CCR * I2C parent clk period
+		 * So to reach 100 kHz, we have:
+		 * CCR = I2C parent rate / 100 kHz >> 1
+		 *
+		 * For example with parent rate = 2 MHz:
+		 * CCR = 2000000 / (100000 << 1) = 10
+		 * t_scl_high = t_scl_low = 10 * (1 / 2000000) = 5000 ns
+		 * t_scl_high + t_scl_low = 10000 ns so 100 kHz is reached
+		 *
+		 * Function stm32f4_i2c_set_periph_clk_freq made sure that
+		 * parent rate is not higher than 46 MHz . As a result val
+		 * is at most 8 bits wide and so fits into the CCR bits [11:0].
+		 */
+		val = i2c_dev->parent_rate / (100000 << 1);
+	} else {
+		/*
+		 * In fast mode, we compute CCR with duty = 0 as with low
+		 * frequencies we are not able to reach 400 kHz.
+		 * In that case:
+		 * t_scl_high = CCR * I2C parent clk period
+		 * t_scl_low = 2 * CCR * I2C parent clk period
+		 * So, CCR = I2C parent rate / (400 kHz * 3)
+		 *
+		 * For example with parent rate = 6 MHz:
+		 * CCR = 6000000 / (400000 * 3) = 5
+		 * t_scl_high = 5 * (1 / 6000000) = 833 ns > 600 ns
+		 * t_scl_low = 2 * 5 * (1 / 6000000) = 1667 ns > 1300 ns
+		 * t_scl_high + t_scl_low = 2500 ns so 400 kHz is reached
+		 *
+		 * Function stm32f4_i2c_set_periph_clk_freq made sure that
+		 * parent rate is not higher than 46 MHz . As a result val
+		 * is at most 6 bits wide and so fits into the CCR bits [11:0].
+		 */
+		val = DIV_ROUND_UP(i2c_dev->parent_rate, 400000 * 3);
+
+		/* Select Fast mode */
+		ccr |= STM32F4_I2C_CCR_FS;
+	}
+
+	ccr |= STM32F4_I2C_CCR_CCR(val);
+	writel_relaxed(ccr, i2c_dev->base + STM32F4_I2C_CCR);
+}
+
+/**
+ * stm32f4_i2c_hw_config() - Prepare I2C block
+ * @i2c_dev: Controller's private data
+ */
+static int stm32f4_i2c_hw_config(struct stm32f4_i2c_dev *i2c_dev)
+{
+	int ret;
+
+	ret = stm32f4_i2c_set_periph_clk_freq(i2c_dev);
+	if (ret)
+		return ret;
+
+	stm32f4_i2c_set_rise_time(i2c_dev);
+
+	stm32f4_i2c_set_speed_mode(i2c_dev);
+
+	/* Enable I2C */
+	writel_relaxed(STM32F4_I2C_CR1_PE, i2c_dev->base + STM32F4_I2C_CR1);
+
+	return 0;
+}
+
+static int stm32f4_i2c_wait_free_bus(struct stm32f4_i2c_dev *i2c_dev)
+{
+	u32 status;
+	int ret;
+
+	ret = readl_relaxed_poll_timeout(i2c_dev->base + STM32F4_I2C_SR2,
+					 status,
+					 !(status & STM32F4_I2C_SR2_BUSY),
+					 10, 1000);
+	if (ret) {
+		dev_dbg(i2c_dev->dev, "bus not free\n");
+		ret = -EBUSY;
+	}
+
+	return ret;
+}
+
+/**
+ * stm32f4_i2c_write_ byte() - Write a byte in the data register
+ * @i2c_dev: Controller's private data
+ * @byte: Data to write in the register
+ */
+static void stm32f4_i2c_write_byte(struct stm32f4_i2c_dev *i2c_dev, u8 byte)
+{
+	writel_relaxed(byte, i2c_dev->base + STM32F4_I2C_DR);
+}
+
+/**
+ * stm32f4_i2c_write_msg() - Fill the data register in write mode
+ * @i2c_dev: Controller's private data
+ *
+ * This function fills the data register with I2C transfer buffer
+ */
+static void stm32f4_i2c_write_msg(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+
+	stm32f4_i2c_write_byte(i2c_dev, *msg->buf++);
+	msg->count--;
+}
+
+static void stm32f4_i2c_read_msg(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+	u32 rbuf;
+
+	rbuf = readl_relaxed(i2c_dev->base + STM32F4_I2C_DR);
+	*msg->buf++ = rbuf;
+	msg->count--;
+}
+
+static void stm32f4_i2c_terminate_xfer(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+	void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+	stm32f4_i2c_disable_irq(i2c_dev);
+
+	reg = i2c_dev->base + STM32F4_I2C_CR1;
+	if (msg->stop)
+		stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+	else
+		stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+
+	complete(&i2c_dev->complete);
+}
+
+/**
+ * stm32f4_i2c_handle_write() - Handle FIFO empty interrupt in case of write
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_write(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+	void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+	if (msg->count) {
+		stm32f4_i2c_write_msg(i2c_dev);
+		if (!msg->count) {
+			/*
+			 * Disable buffer interrupts for RX not empty and TX
+			 * empty events
+			 */
+			stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
+		}
+	} else {
+		stm32f4_i2c_terminate_xfer(i2c_dev);
+	}
+}
+
+/**
+ * stm32f4_i2c_handle_read() - Handle FIFO empty interrupt in case of read
+ * @i2c_dev: Controller's private data
+ *
+ * This function is called when a new data is received in data register
+ */
+static void stm32f4_i2c_handle_read(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+	void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
+
+	switch (msg->count) {
+	case 1:
+		stm32f4_i2c_disable_irq(i2c_dev);
+		stm32f4_i2c_read_msg(i2c_dev);
+		complete(&i2c_dev->complete);
+		break;
+	/*
+	 * For 2-byte reception, 3-byte reception and for Data N-2, N-1 and N
+	 * for N-byte reception with N > 3, we do not have to read the data
+	 * register when RX not empty event occurs as we have to wait for byte
+	 * transferred finished event before reading data.
+	 * So, here we just disable buffer interrupt in order to avoid another
+	 * system preemption due to RX not empty event.
+	 */
+	case 2:
+	case 3:
+		stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
+		break;
+	/*
+	 * For N byte reception with N > 3 we directly read data register
+	 * until N-2 data.
+	 */
+	default:
+		stm32f4_i2c_read_msg(i2c_dev);
+	}
+}
+
+/**
+ * stm32f4_i2c_handle_rx_done() - Handle byte transfer finished interrupt
+ * in case of read
+ * @i2c_dev: Controller's private data
+ *
+ * This function is called when a new data is received in the shift register
+ * but data register has not been read yet.
+ */
+static void stm32f4_i2c_handle_rx_done(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+	void __iomem *reg;
+	u32 mask;
+	int i;
+
+	switch (msg->count) {
+	case 2:
+		/*
+		 * In order to correctly send the Stop or Repeated Start
+		 * condition on the I2C bus, the STOP/START bit has to be set
+		 * before reading the last two bytes (data N-1 and N).
+		 * After that, we could read the last two bytes, disable
+		 * remaining interrupts and notify the end of xfer to the
+		 * client
+		 */
+		reg = i2c_dev->base + STM32F4_I2C_CR1;
+		if (msg->stop)
+			stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+		else
+			stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+
+		for (i = 2; i > 0; i--)
+			stm32f4_i2c_read_msg(i2c_dev);
+
+		reg = i2c_dev->base + STM32F4_I2C_CR2;
+		mask = STM32F4_I2C_CR2_ITEVTEN | STM32F4_I2C_CR2_ITERREN;
+		stm32f4_i2c_clr_bits(reg, mask);
+
+		complete(&i2c_dev->complete);
+		break;
+	case 3:
+		/*
+		 * In order to correctly generate the NACK pulse after the last
+		 * received data byte, we have to enable NACK before reading N-2
+		 * data
+		 */
+		reg = i2c_dev->base + STM32F4_I2C_CR1;
+		stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
+		stm32f4_i2c_read_msg(i2c_dev);
+		break;
+	default:
+		stm32f4_i2c_read_msg(i2c_dev);
+	}
+}
+
+/**
+ * stm32f4_i2c_handle_rx_addr() - Handle address matched interrupt in case of
+ * master receiver
+ * @i2c_dev: Controller's private data
+ */
+static void stm32f4_i2c_handle_rx_addr(struct stm32f4_i2c_dev *i2c_dev)
+{
+	struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+	u32 cr1;
+
+	switch (msg->count) {
+	case 0:
+		stm32f4_i2c_terminate_xfer(i2c_dev);
+
+		/* Clear ADDR flag */
+		readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+		break;
+	case 1:
+		/*
+		 * Single byte reception:
+		 * Enable NACK and reset POS (Acknowledge position).
+		 * Then, clear ADDR flag and set STOP or RepSTART.
+		 * In that way, the NACK and STOP or RepStart pulses will be
+		 * sent as soon as the byte will be received in shift register
+		 */
+		cr1 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR1);
+		cr1 &= ~(STM32F4_I2C_CR1_ACK | STM32F4_I2C_CR1_POS);
+		writel_relaxed(cr1, i2c_dev->base + STM32F4_I2C_CR1);
+
+		readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+
+		if (msg->stop)
+			cr1 |= STM32F4_I2C_CR1_STOP;
+		else
+			cr1 |= STM32F4_I2C_CR1_START;
+		writel_relaxed(cr1, i2c_dev->base + STM32F4_I2C_CR1);
+		break;
+	case 2:
+		/*
+		 * 2-byte reception:
+		 * Enable NACK, set POS (NACK position) and clear ADDR flag.
+		 * In that way, NACK will be sent for the next byte which will
+		 * be received in the shift register instead of the current
+		 * one.
+		 */
+		cr1 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR1);
+		cr1 &= ~STM32F4_I2C_CR1_ACK;
+		cr1 |= STM32F4_I2C_CR1_POS;
+		writel_relaxed(cr1, i2c_dev->base + STM32F4_I2C_CR1);
+
+		readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+		break;
+
+	default:
+		/*
+		 * N-byte reception:
+		 * Enable ACK, reset POS (ACK postion) and clear ADDR flag.
+		 * In that way, ACK will be sent as soon as the current byte
+		 * will be received in the shift register
+		 */
+		cr1 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR1);
+		cr1 |= STM32F4_I2C_CR1_ACK;
+		cr1 &= ~STM32F4_I2C_CR1_POS;
+		writel_relaxed(cr1, i2c_dev->base + STM32F4_I2C_CR1);
+
+		readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+		break;
+	}
+}
+
+/**
+ * stm32f4_i2c_isr_event() - Interrupt routine for I2C bus event
+ * @irq: interrupt number
+ * @data: Controller's private data
+ */
+static irqreturn_t stm32f4_i2c_isr_event(int irq, void *data)
+{
+	struct stm32f4_i2c_dev *i2c_dev = data;
+	struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+	u32 possible_status = STM32F4_I2C_SR1_ITEVTEN_MASK;
+	u32 status, ien, event, cr2;
+
+	cr2 = readl_relaxed(i2c_dev->base + STM32F4_I2C_CR2);
+	ien = cr2 & STM32F4_I2C_CR2_IRQ_MASK;
+
+	/* Update possible_status if buffer interrupt is enabled */
+	if (ien & STM32F4_I2C_CR2_ITBUFEN)
+		possible_status |= STM32F4_I2C_SR1_ITBUFEN_MASK;
+
+	status = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR1);
+	event = status & possible_status;
+	if (!event) {
+		dev_dbg(i2c_dev->dev,
+			"spurious evt irq (status=0x%08x, ien=0x%08x)\n",
+			status, ien);
+		return IRQ_NONE;
+	}
+
+	/* Start condition generated */
+	if (event & STM32F4_I2C_SR1_SB)
+		stm32f4_i2c_write_byte(i2c_dev, msg->addr);
+
+	/* I2C Address sent */
+	if (event & STM32F4_I2C_SR1_ADDR) {
+		if (msg->addr & I2C_M_RD)
+			stm32f4_i2c_handle_rx_addr(i2c_dev);
+		else
+			readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
+
+		/*
+		 * Enable buffer interrupts for RX not empty and TX empty
+		 * events
+		 */
+		cr2 |= STM32F4_I2C_CR2_ITBUFEN;
+		writel_relaxed(cr2, i2c_dev->base + STM32F4_I2C_CR2);
+	}
+
+	/* TX empty */
+	if ((event & STM32F4_I2C_SR1_TXE) && !(msg->addr & I2C_M_RD))
+		stm32f4_i2c_handle_write(i2c_dev);
+
+	/* RX not empty */
+	if ((event & STM32F4_I2C_SR1_RXNE) && (msg->addr & I2C_M_RD))
+		stm32f4_i2c_handle_read(i2c_dev);
+
+	/*
+	 * The BTF (Byte Transfer finished) event occurs when:
+	 * - in reception : a new byte is received in the shift register
+	 * but the previous byte has not been read yet from data register
+	 * - in transmission: a new byte should be sent but the data register
+	 * has not been written yet
+	 */
+	if (event & STM32F4_I2C_SR1_BTF) {
+		if (msg->addr & I2C_M_RD)
+			stm32f4_i2c_handle_rx_done(i2c_dev);
+		else
+			stm32f4_i2c_handle_write(i2c_dev);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * stm32f4_i2c_isr_error() - Interrupt routine for I2C bus error
+ * @irq: interrupt number
+ * @data: Controller's private data
+ */
+static irqreturn_t stm32f4_i2c_isr_error(int irq, void *data)
+{
+	struct stm32f4_i2c_dev *i2c_dev = data;
+	struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
+	void __iomem *reg;
+	u32 status;
+
+	status = readl_relaxed(i2c_dev->base + STM32F4_I2C_SR1);
+
+	/* Arbitration lost */
+	if (status & STM32F4_I2C_SR1_ARLO) {
+		status &= ~STM32F4_I2C_SR1_ARLO;
+		writel_relaxed(status, i2c_dev->base + STM32F4_I2C_SR1);
+		msg->result = -EAGAIN;
+	}
+
+	/*
+	 * Acknowledge failure:
+	 * In master transmitter mode a Stop must be generated by software
+	 */
+	if (status & STM32F4_I2C_SR1_AF) {
+		if (!(msg->addr & I2C_M_RD)) {
+			reg = i2c_dev->base + STM32F4_I2C_CR1;
+			stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
+		}
+		status &= ~STM32F4_I2C_SR1_AF;
+		writel_relaxed(status, i2c_dev->base + STM32F4_I2C_SR1);
+		msg->result = -EIO;
+	}
+
+	/* Bus error */
+	if (status & STM32F4_I2C_SR1_BERR) {
+		status &= ~STM32F4_I2C_SR1_BERR;
+		writel_relaxed(status, i2c_dev->base + STM32F4_I2C_SR1);
+		msg->result = -EIO;
+	}
+
+	stm32f4_i2c_disable_irq(i2c_dev);
+	complete(&i2c_dev->complete);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * stm32f4_i2c_xfer_msg() - Transfer a single I2C message
+ * @i2c_dev: Controller's private data
+ * @msg: I2C message to transfer
+ * @is_first: first message of the sequence
+ * @is_last: last message of the sequence
+ */
+static int stm32f4_i2c_xfer_msg(struct stm32f4_i2c_dev *i2c_dev,
+				struct i2c_msg *msg, bool is_first,
+				bool is_last)
+{
+	struct stm32f4_i2c_msg *f4_msg = &i2c_dev->msg;
+	void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR1;
+	unsigned long timeout;
+	u32 mask;
+	int ret;
+
+	f4_msg->addr = i2c_8bit_addr_from_msg(msg);
+	f4_msg->buf = msg->buf;
+	f4_msg->count = msg->len;
+	f4_msg->result = 0;
+	f4_msg->stop = is_last;
+
+	reinit_completion(&i2c_dev->complete);
+
+	/* Enable events and errors interrupts */
+	mask = STM32F4_I2C_CR2_ITEVTEN | STM32F4_I2C_CR2_ITERREN;
+	stm32f4_i2c_set_bits(i2c_dev->base + STM32F4_I2C_CR2, mask);
+
+	if (is_first) {
+		ret = stm32f4_i2c_wait_free_bus(i2c_dev);
+		if (ret)
+			return ret;
+
+		/* START generation */
+		stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
+	}
+
+	timeout = wait_for_completion_timeout(&i2c_dev->complete,
+					      i2c_dev->adap.timeout);
+	ret = f4_msg->result;
+
+	if (!timeout)
+		ret = -ETIMEDOUT;
+
+	return ret;
+}
+
+/**
+ * stm32f4_i2c_xfer() - Transfer combined I2C message
+ * @i2c_adap: Adapter pointer to the controller
+ * @msgs: Pointer to data to be written.
+ * @num: Number of messages to be executed
+ */
+static int stm32f4_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
+			    int num)
+{
+	struct stm32f4_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
+	int ret, i;
+
+	ret = clk_enable(i2c_dev->clk);
+	if (ret) {
+		dev_err(i2c_dev->dev, "Failed to enable clock\n");
+		return ret;
+	}
+
+	for (i = 0; i < num && !ret; i++)
+		ret = stm32f4_i2c_xfer_msg(i2c_dev, &msgs[i], i == 0,
+					   i == num - 1);
+
+	clk_disable(i2c_dev->clk);
+
+	return (ret < 0) ? ret : num;
+}
+
+static u32 stm32f4_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm stm32f4_i2c_algo = {
+	.master_xfer = stm32f4_i2c_xfer,
+	.functionality = stm32f4_i2c_func,
+};
+
+static int stm32f4_i2c_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct stm32f4_i2c_dev *i2c_dev;
+	struct resource *res;
+	u32 irq_event, irq_error, clk_rate;
+	struct i2c_adapter *adap;
+	struct reset_control *rst;
+	int ret;
+
+	i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
+	if (!i2c_dev)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(i2c_dev->base))
+		return PTR_ERR(i2c_dev->base);
+
+	irq_event = irq_of_parse_and_map(np, 0);
+	if (!irq_event) {
+		dev_err(&pdev->dev, "IRQ event missing or invalid\n");
+		return -EINVAL;
+	}
+
+	irq_error = irq_of_parse_and_map(np, 1);
+	if (!irq_error) {
+		dev_err(&pdev->dev, "IRQ error missing or invalid\n");
+		return -EINVAL;
+	}
+
+	i2c_dev->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(i2c_dev->clk)) {
+		dev_err(&pdev->dev, "Error: Missing controller clock\n");
+		return PTR_ERR(i2c_dev->clk);
+	}
+	ret = clk_prepare_enable(i2c_dev->clk);
+	if (ret) {
+		dev_err(i2c_dev->dev, "Failed to prepare_enable clock\n");
+		return ret;
+	}
+
+	rst = devm_reset_control_get(&pdev->dev, NULL);
+	if (IS_ERR(rst)) {
+		dev_err(&pdev->dev, "Error: Missing controller reset\n");
+		ret = PTR_ERR(rst);
+		goto clk_free;
+	}
+	reset_control_assert(rst);
+	udelay(2);
+	reset_control_deassert(rst);
+
+	i2c_dev->speed = STM32F4_I2C_SPEED_STANDARD;
+	ret = of_property_read_u32(np, "clock-frequency", &clk_rate);
+	if (!ret && clk_rate >= 400000)
+		i2c_dev->speed = STM32F4_I2C_SPEED_FAST;
+
+	i2c_dev->dev = &pdev->dev;
+
+	ret = devm_request_irq(&pdev->dev, irq_event, stm32f4_i2c_isr_event, 0,
+			       pdev->name, i2c_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request irq event %i\n",
+			irq_event);
+		goto clk_free;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq_error, stm32f4_i2c_isr_error, 0,
+			       pdev->name, i2c_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request irq error %i\n",
+			irq_error);
+		goto clk_free;
+	}
+
+	ret = stm32f4_i2c_hw_config(i2c_dev);
+	if (ret)
+		goto clk_free;
+
+	adap = &i2c_dev->adap;
+	i2c_set_adapdata(adap, i2c_dev);
+	snprintf(adap->name, sizeof(adap->name), "STM32 I2C(%pa)", &res->start);
+	adap->owner = THIS_MODULE;
+	adap->timeout = 2 * HZ;
+	adap->retries = 0;
+	adap->algo = &stm32f4_i2c_algo;
+	adap->dev.parent = &pdev->dev;
+	adap->dev.of_node = pdev->dev.of_node;
+
+	init_completion(&i2c_dev->complete);
+
+	ret = i2c_add_adapter(adap);
+	if (ret)
+		goto clk_free;
+
+	platform_set_drvdata(pdev, i2c_dev);
+
+	clk_disable(i2c_dev->clk);
+
+	dev_info(i2c_dev->dev, "STM32F4 I2C driver registered\n");
+
+	return 0;
+
+clk_free:
+	clk_disable_unprepare(i2c_dev->clk);
+	return ret;
+}
+
+static int stm32f4_i2c_remove(struct platform_device *pdev)
+{
+	struct stm32f4_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+
+	i2c_del_adapter(&i2c_dev->adap);
+
+	clk_unprepare(i2c_dev->clk);
+
+	return 0;
+}
+
+static const struct of_device_id stm32f4_i2c_match[] = {
+	{ .compatible = "st,stm32f4-i2c", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, stm32f4_i2c_match);
+
+static struct platform_driver stm32f4_i2c_driver = {
+	.driver = {
+		.name = "stm32f4-i2c",
+		.of_match_table = stm32f4_i2c_match,
+	},
+	.probe = stm32f4_i2c_probe,
+	.remove = stm32f4_i2c_remove,
+};
+
+module_platform_driver(stm32f4_i2c_driver);
+
+MODULE_AUTHOR("M'boumba Cedric Madianga <cedric.madianga@gmail.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32F4 I2C driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

^ permalink raw reply related

* [PATCH v10 3/5] ARM: dts: stm32: Add I2C1 support for STM32F429 SoC
From: M'boumba Cedric Madianga @ 2017-01-19 13:25 UTC (permalink / raw)
  To: wsa, robh+dt, mcoquelin.stm32, alexandre.torgue, linus.walleij,
	patrice.chotard, linux, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel, u.kleine-koenig
  Cc: M'boumba Cedric Madianga
In-Reply-To: <1484832316-5594-1-git-send-email-cedric.madianga@gmail.com>

This patch adds I2C1 support for STM32F429 SoC

Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
---
 arch/arm/boot/dts/stm32f429.dtsi | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index e4dae0e..5b063e9 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -48,6 +48,7 @@
 #include "skeleton.dtsi"
 #include "armv7-m.dtsi"
 #include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
+#include <dt-bindings/mfd/stm32f4-rcc.h>
 
 / {
 	clocks {
@@ -153,6 +154,18 @@
 			status = "disabled";
 		};
 
+		i2c1: i2c@40005400 {
+			compatible = "st,stm32f4-i2c";
+			reg = <0x40005400 0x400>;
+			interrupts = <31>,
+				     <32>;
+			resets = <&rcc STM32F4_APB1_RESET(I2C1)>;
+			clocks = <&rcc 0 STM32F4_APB1_CLOCK(I2C1)>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		usart7: serial@40007800 {
 			compatible = "st,stm32-usart", "st,stm32-uart";
 			reg = <0x40007800 0x400>;
@@ -355,6 +368,16 @@
 					slew-rate = <2>;
 				};
 			};
+
+			i2c1_pins_b: i2c1@0 {
+				pins {
+					pinmux = <STM32F429_PB9_FUNC_I2C1_SDA>,
+						 <STM32F429_PB6_FUNC_I2C1_SCL>;
+					bias-disable;
+					drive-open-drain;
+					slew-rate = <3>;
+				};
+			};
 		};
 
 		rcc: rcc@40023810 {
-- 
1.9.1

^ permalink raw reply related

* [PATCH v10 4/5] ARM: dts: stm32: Add I2C1 support for STM32429 eval board
From: M'boumba Cedric Madianga @ 2017-01-19 13:25 UTC (permalink / raw)
  To: wsa, robh+dt, mcoquelin.stm32, alexandre.torgue, linus.walleij,
	patrice.chotard, linux, linux-i2c, devicetree, linux-arm-kernel,
	linux-kernel, u.kleine-koenig
  Cc: M'boumba Cedric Madianga
In-Reply-To: <1484832316-5594-1-git-send-email-cedric.madianga@gmail.com>

This patch adds I2C1 instance support for STM32x9I-Eval board.

Signed-off-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
---
 arch/arm/boot/dts/stm32429i-eval.dts | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/stm32429i-eval.dts b/arch/arm/boot/dts/stm32429i-eval.dts
index 76f7206..c943539 100644
--- a/arch/arm/boot/dts/stm32429i-eval.dts
+++ b/arch/arm/boot/dts/stm32429i-eval.dts
@@ -146,3 +146,9 @@
 	pinctrl-names = "default";
 	status = "okay";
 };
+
+&i2c1 {
+	pinctrl-0 = <&i2c1_pins_b>;
+	pinctrl-names = "default";
+	status = "okay";
+};
-- 
1.9.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox