* Re: [RFT PATCH] ARM: dts: exynos: Enable Mixer node for Exynos5800 Peach Pi machine
From: Javier Martinez Canillas @ 2017-12-12 7:41 UTC (permalink / raw)
To: Marek Szyprowski, linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Guillaume Tucker, Daniel Vetter, Shuah Khan,
devicetree-u79uwXL29TY76Z2rM5mHXA, Kukjin Kim, Russell King,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
Mark Rutland, Krzysztof Kozlowski,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <3e6e4b15-9f8a-bea1-3c8e-2d85fc4c512d-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Hello Marek,
On 12/12/2017 08:01 AM, Marek Szyprowski wrote:
> Hi
>
> On 2017-12-11 23:48, Javier Martinez Canillas wrote:
>> Commit 1cb686c08d12 ("ARM: dts: exynos: Add status property to Exynos 542x
>> Mixer nodes") disabled the Mixer node by default in the DTSI and enabled
>> for each Exynos 542x DTS. But unfortunately it missed to enable it for the
>> Exynos5800 Peach Pi machine, since the 5800 is also an 542x SoC variant.
>>
>> Signed-off-by: Javier Martinez Canillas <javierm-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>
> Acked-by: Marek Szyprowski <m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
>
Thanks.
>> ---
>>
>> I believe this may cause the boot issues reported on Exynos5800 Peach Pi
>> from v4.15-rc3, the mentioned commit made to v4.15-rc1 but it seems that
>> didn't cause any harm until commit ("510353a63796 drm/bridge: analogix
>> dp: Fix runtime PM state in get_modes() callback") fixed the runtime PM
>> management in the DP driver.
>
> Thanks for analyzing this. Lack of this change was probably responsible for
> Exynos DRM initialization failure ("exynos-drm exynos-drm: failed to bind
> 14530000.hdmi (ops hdmi_component_ops): -1" message and probably further
> error "unbalanced disables for lcd_vdd", which shows that failure path of
> analogix dp and simple panel causes unbalanced regulator disable.
>
Yes, I came to the same conclusion than you in the thread started by
Guillaume. I just couldn't test it.
> This patch should go to v4.15-rcX (fixes) if possible.
>
Indeed. I wondered if it also needed a Fixes tag. I didn't include it because
I thought that both the culprit and the fix would be in the same kernel release.
But I'll include it anyways.
>> I can't test right now, but I'm posting anyways as a RFT in case others
>> that have access to a Peach Pi can test it.
>>
>> Best regards,
>> Javier
>>
>> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 ++++
>> 1 file changed, 4 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>> index b2b95ff205e8..0029ec27819c 100644
>> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
>> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
>> @@ -664,6 +664,10 @@
>> status = "okay";
>> };
>>
>> +&mixer {
>> + status = "okay";
>> +};
>> +
>> /* eMMC flash */
>> &mmc_0 {
>> status = "okay";
>
> Best regards
>
Best regards,
--
Javier Martinez Canillas
Software Engineer - Desktop Hardware Enablement
Red Hat
--
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 v2 4/7] cpufreq: mvebu: Use dev_pm_opp_remove()
From: Viresh Kumar @ 2017-12-12 7:33 UTC (permalink / raw)
To: Thomas Petazzoni
Cc: Gregory CLEMENT, Rafael J. Wysocki,
linux-pm-u79uwXL29TY76Z2rM5mHXA, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Antoine Tenart,
Miquèl Raynal, Nadav Haklai, Victor Gu, Marcin Wojtas,
Wilson Ding, Hua Jing, Neta Zur Hershkovits, Evan Wang,
Andre Heider
In-Reply-To: <20171212082846.4e201953-dFHcqWZE4newlwMtHBQNBj9sBOhXbXn6VpNB7YpNyf8@public.gmane.org>
On 12-12-17, 08:28, Thomas Petazzoni wrote:
> Hello,
>
> On Thu, 7 Dec 2017 14:56:13 +0100, Gregory CLEMENT wrote:
>
> > - /*
> > - * In case of a failure of dev_pm_opp_add(), we don't
> > - * bother with cleaning up the registered OPP (there's
> > - * no function to do so), and simply cancel the
> > - * registration of the cpufreq device.
> > - */
> > ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk), 0);
> > if (ret) {
> > clk_put(clk);
> > @@ -90,6 +84,11 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
> >
> > ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk) / 2, 0);
> > if (ret) {
> > + /*
> > + * The second opp failed to be added, remove
> > + * the first one before exiting.
> > + */
> > + dev_pm_opp_remove(cpu_dev, clk_get_rate(clk));
> > clk_put(clk);
> > return ret;
> > }
>
> This still doesn't fix the failure situation. Indeed, you are only
> removing the OPP at full rate for the current CPU, but you are not
> removing the OPPs for the N-1 previous CPUs that have been handled in
> previous iterations of the loop.
Sorry for missing that, I quickly looked at source and missed seeing the
for_each_cpu loop :(
--
viresh
--
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 v2 4/7] cpufreq: mvebu: Use dev_pm_opp_remove()
From: Thomas Petazzoni @ 2017-12-12 7:28 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Rafael J. Wysocki, Viresh Kumar, linux-pm-u79uwXL29TY76Z2rM5mHXA,
Jason Cooper, Andrew Lunn, Sebastian Hesselbarth, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Antoine Tenart,
Miquèl Raynal, Nadav Haklai, Victor Gu, Marcin Wojtas,
Wilson Ding, Hua Jing, Neta Zur Hershkovits, Evan Wang,
Andre Heider
In-Reply-To: <20171207135616.23670-5-gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Hello,
On Thu, 7 Dec 2017 14:56:13 +0100, Gregory CLEMENT wrote:
> - /*
> - * In case of a failure of dev_pm_opp_add(), we don't
> - * bother with cleaning up the registered OPP (there's
> - * no function to do so), and simply cancel the
> - * registration of the cpufreq device.
> - */
> ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk), 0);
> if (ret) {
> clk_put(clk);
> @@ -90,6 +84,11 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
>
> ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk) / 2, 0);
> if (ret) {
> + /*
> + * The second opp failed to be added, remove
> + * the first one before exiting.
> + */
> + dev_pm_opp_remove(cpu_dev, clk_get_rate(clk));
> clk_put(clk);
> return ret;
> }
This still doesn't fix the failure situation. Indeed, you are only
removing the OPP at full rate for the current CPU, but you are not
removing the OPPs for the N-1 previous CPUs that have been handled in
previous iterations of the loop.
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
--
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 v1 4/4] arm64: dts: mediatek: add mt2712 cpufreq related device nodes
From: Viresh Kumar @ 2017-12-12 7:26 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Andrew-sh Cheng, matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w,
mark.rutland-5wv7dgnIgG8, linux-pm-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1758225.tOgn8eUOoH-yvgW3jdyMHm1GS7QM15AGw@public.gmane.org>
On 12-12-17, 02:17, Rafael J. Wysocki wrote:
> On Monday, December 11, 2017 8:57:19 AM CET Viresh Kumar wrote:
> > On 08-12-17, 14:07, Andrew-sh Cheng wrote:
> > > Add opp v2 information,
> > > and also add clocks, regulators and opp information into cpu nodes
> > >
> > > Signed-off-by: Andrew-sh Cheng <andrew-sh.cheng-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> > > ---
> > > arch/arm64/boot/dts/mediatek/mt2712-evb.dts | 27 ++++++++++++++
> > > arch/arm64/boot/dts/mediatek/mt2712e.dtsi | 57 +++++++++++++++++++++++++++++
> > > 2 files changed, 84 insertions(+)
> >
> > Acked-by: Viresh Kumar <viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> Of course, DT bindings require ACKs from DT maintainers to be applied.
I didn't knew that we need Acks from DT maintainers for dts files as well? Yeah,
its very much required while defining new bindings for sure.
--
viresh
--
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 v2 6/7] cpufreq: Add DVFS support for Armada 37xx
From: Viresh Kumar @ 2017-12-12 7:24 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Rafael J. Wysocki, linux-pm-u79uwXL29TY76Z2rM5mHXA, Jason Cooper,
Andrew Lunn, Sebastian Hesselbarth, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA, Thomas Petazzoni,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Antoine Tenart,
Miquèl Raynal, Nadav Haklai, Victor Gu, Marcin Wojtas,
Wilson Ding, Hua Jing, Neta Zur Hershkovits, Evan Wang,
Andre Heider
In-Reply-To: <20171207135616.23670-7-gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
On 07-12-17, 14:56, Gregory CLEMENT wrote:
> +/* Power management in North Bridge register set */
> +#define ARMADA_37XX_NB_L0L1 0x18
> +#define ARMADA_37XX_NB_L2L3 0x1C
> +#define ARMADA_37XX_NB_TBG_DIV_OFF 13
> +#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7
> +#define ARMADA_37XX_NB_CLK_SEL_OFF 11
> +#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1
> +#define ARMADA_37XX_NB_CLK_SEL_TBG 0x1
> +#define ARMADA_37XX_NB_TBG_SEL_OFF 9
> +#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3
> +#define ARMADA_37XX_NB_VDD_SEL_OFF 6
> +#define ARMADA_37XX_NB_VDD_SEL_MASK 0x3
> +#define ARMADA_37XX_NB_CONFIG_SHIFT 16
> +#define ARMADA_37XX_NB_DYN_MOD 0x24
> +#define ARMADA_37XX_NB_CLK_SEL_EN BIT(26)
> +#define ARMADA_37XX_NB_TBG_EN BIT(28)
> +#define ARMADA_37XX_NB_DIV_EN BIT(29)
> +#define ARMADA_37XX_NB_VDD_EN BIT(30)
> +#define ARMADA_37XX_NB_DFS_EN BIT(31)
> +#define ARMADA_37XX_NB_CPU_LOAD 0x30
> +#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3
> +#define ARMADA_37XX_DVFS_LOAD_0 0
> +#define ARMADA_37XX_DVFS_LOAD_1 1
> +#define ARMADA_37XX_DVFS_LOAD_2 2
> +#define ARMADA_37XX_DVFS_LOAD_3 3
I thought you agreed to using space instead of tab after #define ?
Looks fine otherwise. You can add below after fixing above tab/space thing:
Acked-by: Viresh Kumar <viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
--
viresh
--
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 v2 5/7] MAINTAINERS: add new entries for Armada 37xx cpufreq driver
From: Viresh Kumar @ 2017-12-12 7:22 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Rafael J. Wysocki, linux-pm, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Rob Herring, devicetree, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits, Evan Wang, Andre Heider
In-Reply-To: <20171207135616.23670-6-gregory.clement@free-electrons.com>
On 07-12-17, 14:56, Gregory CLEMENT wrote:
> This new driver belongs to the mvebu family, update the MAINTAINER file
> to document it.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> MAINTAINERS | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index aa71ab52fd76..98dcee849481 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1582,6 +1582,7 @@ F: arch/arm/boot/dts/kirkwood*
> F: arch/arm/configs/mvebu_*_defconfig
> F: arch/arm/mach-mvebu/
> F: arch/arm64/boot/dts/marvell/armada*
> +F: drivers/cpufreq/armada-37xx-cpufreq.c
> F: drivers/cpufreq/mvebu-cpufreq.c
> F: drivers/irqchip/irq-armada-370-xp.c
> F: drivers/irqchip/irq-mvebu-*
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* Re: [PATCH v2 4/7] cpufreq: mvebu: Use dev_pm_opp_remove()
From: Viresh Kumar @ 2017-12-12 7:21 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Rafael J. Wysocki, linux-pm-u79uwXL29TY76Z2rM5mHXA, Jason Cooper,
Andrew Lunn, Sebastian Hesselbarth, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA, Thomas Petazzoni,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Antoine Tenart,
Miquèl Raynal, Nadav Haklai, Victor Gu, Marcin Wojtas,
Wilson Ding, Hua Jing, Neta Zur Hershkovits, Evan Wang,
Andre Heider
In-Reply-To: <20171207135616.23670-5-gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
On 07-12-17, 14:56, Gregory CLEMENT wrote:
> Since the introduction of this driver, the dev_pm_opp_remove() was
> added. So stop claiming we can't remove opp and use it in case of
> failure.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
> drivers/cpufreq/mvebu-cpufreq.c | 11 +++++------
> 1 file changed, 5 insertions(+), 6 deletions(-)
There is no reason for this patch to be part of your series. You should have
sent it separately. Please do it now.
And while you do it, you can add
Acked-by: Viresh Kumar <viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
--
viresh
--
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: [RFT PATCH] ARM: dts: exynos: Enable Mixer node for Exynos5800 Peach Pi machine
From: Marek Szyprowski @ 2017-12-12 7:01 UTC (permalink / raw)
To: Javier Martinez Canillas, linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Guillaume Tucker, Daniel Vetter, Shuah Khan,
devicetree-u79uwXL29TY76Z2rM5mHXA, Kukjin Kim, Russell King,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
Mark Rutland, Krzysztof Kozlowski,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20171211224856.29264-1-javierm-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Hi
On 2017-12-11 23:48, Javier Martinez Canillas wrote:
> Commit 1cb686c08d12 ("ARM: dts: exynos: Add status property to Exynos 542x
> Mixer nodes") disabled the Mixer node by default in the DTSI and enabled
> for each Exynos 542x DTS. But unfortunately it missed to enable it for the
> Exynos5800 Peach Pi machine, since the 5800 is also an 542x SoC variant.
>
> Signed-off-by: Javier Martinez Canillas <javierm-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Acked-by: Marek Szyprowski <m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> ---
>
> I believe this may cause the boot issues reported on Exynos5800 Peach Pi
> from v4.15-rc3, the mentioned commit made to v4.15-rc1 but it seems that
> didn't cause any harm until commit ("510353a63796 drm/bridge: analogix
> dp: Fix runtime PM state in get_modes() callback") fixed the runtime PM
> management in the DP driver.
Thanks for analyzing this. Lack of this change was probably responsible for
Exynos DRM initialization failure ("exynos-drm exynos-drm: failed to bind
14530000.hdmi (ops hdmi_component_ops): -1" message and probably further
error "unbalanced disables for lcd_vdd", which shows that failure path of
analogix dp and simple panel causes unbalanced regulator disable.
This patch should go to v4.15-rcX (fixes) if possible.
> I can't test right now, but I'm posting anyways as a RFT in case others
> that have access to a Peach Pi can test it.
>
> Best regards,
> Javier
>
> arch/arm/boot/dts/exynos5800-peach-pi.dts | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
> index b2b95ff205e8..0029ec27819c 100644
> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
> @@ -664,6 +664,10 @@
> status = "okay";
> };
>
> +&mixer {
> + status = "okay";
> +};
> +
> /* eMMC flash */
> &mmc_0 {
> status = "okay";
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
--
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 v2 3/7] cpufreq: sort the drivers in ARM part
From: Viresh Kumar @ 2017-12-12 6:57 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Rafael J. Wysocki, linux-pm-u79uwXL29TY76Z2rM5mHXA, Jason Cooper,
Andrew Lunn, Sebastian Hesselbarth, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA, Thomas Petazzoni,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Antoine Tenart,
Miquèl Raynal, Nadav Haklai, Victor Gu, Marcin Wojtas,
Wilson Ding, Hua Jing, Neta Zur Hershkovits, Evan Wang,
Andre Heider
In-Reply-To: <20171207135616.23670-4-gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
On 07-12-17, 14:56, Gregory CLEMENT wrote:
> Keep the driver files alphabetically sorted.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
> drivers/cpufreq/Makefile | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
Acked-by: Viresh Kumar <viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
--
viresh
--
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 v2 2/7] cpufreq: ARM: sort the Kconfig menu
From: Viresh Kumar @ 2017-12-12 6:56 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Rafael J. Wysocki, linux-pm, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Rob Herring, devicetree, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits, Evan Wang, Andre Heider
In-Reply-To: <20171207135616.23670-3-gregory.clement@free-electrons.com>
On 07-12-17, 14:56, Gregory CLEMENT wrote:
> Group all the related big LITTLE configuration together and sort the
> other entries in alphabetic order.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> drivers/cpufreq/Kconfig.arm | 82 ++++++++++++++++++++++-----------------------
> 1 file changed, 41 insertions(+), 41 deletions(-)
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* [PATCH 2/2] dt-bindings: Document the Rockchip RK1608 bindings
From: Leo Wen @ 2017-12-12 6:28 UTC (permalink / raw)
To: mchehab, robh+dt, mark.rutland, davem, gregkh, rdunlap
Cc: linux-media, devicetree, linux-kernel, linux-rockchip, eddie.cai,
Leo Wen
In-Reply-To: <1513060095-29588-1-git-send-email-leo.wen@rock-chips.com>
Add DT bindings documentation for Rockchip RK1608.
Signed-off-by: Leo Wen <leo.wen@rock-chips.com>
---
Documentation/devicetree/bindings/media/rk1608.txt | 143 +++++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 144 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/rk1608.txt
diff --git a/Documentation/devicetree/bindings/media/rk1608.txt b/Documentation/devicetree/bindings/media/rk1608.txt
new file mode 100644
index 0000000..bda5cdb
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/rk1608.txt
@@ -0,0 +1,143 @@
+Rockchip RK1608 as a PreISP to link on Soc
+------------------------------------------
+
+Required properties:
+
+- compatible : "rockchip,rk1608";
+- reg : SPI slave address of the rk1608;
+- clocks : Must contain an entry for each entry in clock-names;
+- clock-names : Must contain "mclk" for the device's master clock;
+- reset-gpio : GPIO connected to reset pin;
+- irq-gpio : GPIO connected to irq pin;
+- sleepst-gpio : GPIO connected to sleepst pin;
+- wakeup-gpio : GPIO connected to wakeup pin;
+- powerdown-gpio : GPIO connected to powerdown pin;
+- pinctrl-names : Should contain only one value - "default";
+- pinctrl-0 : Pin control group to be used for this controller;
+
+Optional properties:
+
+- spi-max-frequency : Maximum SPI clocking speed of the device;
+ (for RK1608)
+- spi-min-frequency : Minimum SPI clocking speed of the device;
+ (for RK1608)
+
+The device node should contain one 'port' child node with one child 'endpoint'
+node, according to the bindings defined in Documentation/devicetree/bindings/
+media/video-interfaces.txt. The following are properties specific to those
+nodes.
+
+endpoint node
+-------------
+
+- data-lanes : (optional) specifies MIPI CSI-2 data lanes as covered in
+ video-interfaces.txt. If present it should be <1> - the device
+ supports only one data lane without re-mapping.
+
+Note1: Since no data is generated in RK1608,so this is meaningful that you need
+a extra sensor (such as a camera) mounted on RK1608. You need to use endpoint@x
+to match these sensors.
+
+Note2:You must set the current value of the spi pins to be 8mA, if they are not.
+
+Example:
+
+&spi0 {
+ status = "okay";
+
+ spi_rk1608@00 {
+ compatible = "rockchip,rk1608";
+ reg = <0>;
+ status = "okay";
+ spi-max-frequency = <24000000>;
+ spi-min-frequency = <12000000>;
+ clocks = <&cru SCLK_SPI0>;
+ clock-names = "mclk";
+
+ reset-gpio = <&gpio6 0 GPIO_ACTIVE_HIGH>;
+ irq-gpio = <&gpio6 2 GPIO_ACTIVE_HIGH>;
+ sleepst-gpio = <&gpio6 1 GPIO_ACTIVE_HIGH>;
+ wakeup-gpio = <&gpio6 4 GPIO_ACTIVE_HIGH>;
+ powerdown-gpio = <&gpio8 0 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&rk1608_irq_gpios &rk1608_wake_gpios
+ &rk1608_sleep_gpios>;
+
+ port {
+ isp_mipi_out: endpoint {
+ remote-endpoint = <&isp_mipi_in>;
+ data-lanes = <1>;
+ };
+ /*Example: we have two cameras*/
+ sensor_in0: endpoint@0 {
+ remote-endpoint = <&xxx0>;
+ };
+
+ sensor_in1: endpoint@1 {
+ remote-endpoint = <&xxx1>;
+ };
+ };
+ };
+};
+
+&mipi_phy_rx0 {
+ bus-width = <2>;
+ status = "okay";
+
+ port {
+ isp_mipi_in: endpoint {
+ remote-endpoint = <&isp_mipi_out>;
+ data-lanes = <1>;
+ link-frequencies =
+ /bits/ 64 <1000000000>;
+ };
+ };
+};
+
+&pinctrl {
+ rk1608_irq_gpios {
+ rk1608_irq_gpios: rk1608_irq_gpios {
+ rockchip,pins = <6 2 RK_FUNC_GPIO &pcfg_pull_none>;
+ rockchip,pull = <1>;
+ };
+ };
+
+ rk1608_wake_gpios {
+ rk1608_wake_gpios: rk1608_wake_gpios {
+ rockchip,pins = <6 4 RK_FUNC_GPIO &pcfg_pull_none>;
+ rockchip,pull = <1>;
+ };
+ };
+
+ rk1608_sleep_gpios {
+ rk1608_sleep_gpios: rk1608_sleep_gpios {
+ rockchip,pins = <6 1 RK_FUNC_GPIO &pcfg_pull_none>;
+ rockchip,pull = <1>;
+ rockchip,drive = <0>;
+ };
+ };
+
+ pcfg_pull_none_8ma: pcfg-pull-none-8ma {
+ bias-disable;
+ drive-strength = <8>;
+ };
+
+ spi0 {
+ spi0_clk: spi0-clk {
+ rockchip,pins = <5 12 RK_FUNC_1 &pcfg_pull_none_8ma>;
+ };
+ spi0_cs0: spi0-cs0 {
+ rockchip,pins = <5 13 RK_FUNC_1 &pcfg_pull_none_8ma>;
+ };
+ spi0_tx: spi0-tx {
+ rockchip,pins = <5 14 RK_FUNC_1 &pcfg_pull_none_8ma>;
+ };
+ spi0_rx: spi0-rx {
+ rockchip,pins = <5 15 RK_FUNC_1 &pcfg_pull_none_8ma>;
+ };
+ spi0_cs1: spi0-cs1 {
+ rockchip,pins = <5 16 RK_FUNC_1 &pcfg_pull_none_8ma>;
+ };
+ };
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 48235d8..196a9ff 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -133,6 +133,7 @@ M: Leo Wen <leo.wen@rock-chips.com>
S: Maintained
F: drivers/media/platform/spi/rk1608.c
F: drivers/media/platform/spi/rk1608.h
+F: Documentation/devicetree/bindings/media/rk1608.txt
3C59X NETWORK DRIVER
M: Steffen Klassert <klassert@mathematik.tu-chemnitz.de>
--
2.7.4
^ permalink raw reply related
* [PATCH 1/2] [media] Add Rockchip RK1608 driver
From: Leo Wen @ 2017-12-12 6:28 UTC (permalink / raw)
To: mchehab-DgEjT+Ai2ygdnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
rdunlap-wEGCiKHe2LqWVfeAwA7xHQ
Cc: linux-media-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
eddie.cai-TNX95d0MmH7DzftRWevZcw, Leo Wen
In-Reply-To: <1513060095-29588-1-git-send-email-leo.wen-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Rk1608 is used as a PreISP to link on Soc, which mainly has two functions.
One is to download the firmware of RK1608, and the other is to match the
extra sensor such as camera and enable sensor by calling sensor's s_power.
use below v4l2-ctl command to capture frames.
v4l2-ctl --verbose -d /dev/video1 --stream-mmap=2
--stream-to=/tmp/stream.out --stream-count=60 --stream-poll
use below command to playback the video on your PC.
mplayer ./stream.out -loop 0 -demuxer rawvideo -rawvideo
w=640:h=480:size=$((640*480*3/2)):format=NV12
Signed-off-by: Leo Wen <leo.wen-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
MAINTAINERS | 6 +
drivers/media/spi/Makefile | 1 +
drivers/media/spi/rk1608.c | 1165 ++++++++++++++++++++++++++++++++++++++++++++
drivers/media/spi/rk1608.h | 366 ++++++++++++++
4 files changed, 1538 insertions(+)
create mode 100644 drivers/media/spi/rk1608.c
create mode 100644 drivers/media/spi/rk1608.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 82ad0ea..48235d8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -128,6 +128,12 @@ Maintainers List (try to look for most precise areas first)
-----------------------------------
+ROCKCHIP RK1608 DRIVER
+M: Leo Wen <leo.wen-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
+S: Maintained
+F: drivers/media/platform/spi/rk1608.c
+F: drivers/media/platform/spi/rk1608.h
+
3C59X NETWORK DRIVER
M: Steffen Klassert <klassert-H0bhvm5RIPI+B2oLq8eQJv4efur1V5z/s0AfqQuZ5sE@public.gmane.org>
L: netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
diff --git a/drivers/media/spi/Makefile b/drivers/media/spi/Makefile
index ea64013..9d9d9ec 100644
--- a/drivers/media/spi/Makefile
+++ b/drivers/media/spi/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_VIDEO_GS1662) += gs1662.o
+obj-$(CONFIG_ROCKCHIP_RK1608) += rk1608.o
diff --git a/drivers/media/spi/rk1608.c b/drivers/media/spi/rk1608.c
new file mode 100644
index 0000000..e646204
--- /dev/null
+++ b/drivers/media/spi/rk1608.c
@@ -0,0 +1,1165 @@
+/**
+ * Rockchip rk1608 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-image-sizes.h>
+#include <media/v4l2-mediabus.h>
+#include <media/v4l2-of.h>
+#include "rk1608.h"
+
+/**
+ * Rk1608 is used as the Pre-ISP to link on Soc, which mainly has two
+ * functions. One is to download the firmware of RK1608, and the other
+ * is to match the extra sensor such as camera and enable sensor by
+ * calling sensor's s_power.
+ * |-----------------------|
+ * | Sensor Camera |
+ * |-----------------------|
+ * |-----------||----------|
+ * |-----------||----------|
+ * |-----------\/----------|
+ * | Pre-ISP RK1608 |
+ * |-----------------------|
+ * |-----------||----------|
+ * |-----------||----------|
+ * |-----------\/----------|
+ * | Rockchip Soc |
+ * |-----------------------|
+ * Data Transfer As shown above. In RK1608, the data received from the
+ * extra sensor,and it is passed to the Soc through ISP.
+ */
+struct rk1608_state {
+ struct v4l2_subdev sd;
+ struct v4l2_subdev *sensor_sd;
+ struct device *dev;
+ struct spi_device *spi;
+ struct media_pad pad;
+ struct clk *mclk;
+ struct mutex lock; /* protect resource */
+ struct mutex sensor_lock; /* protect sensor */
+ struct mutex send_msg_lock; /* protect msg */
+ int power_count;
+ int reset_gpio;
+ int reset_active;
+ int irq_gpio;
+ int irq;
+ int sleepst_gpio;
+ int sleepst_irq;
+ int wakeup_gpio;
+ int wakeup_active;
+ int powerdown_gpio;
+ int powerdown_active;
+ int msg_num;
+ u32 sensor_cnt;
+ u32 sensor_nums;
+ u32 max_speed_hz;
+ u32 min_speed_hz;
+ atomic_t msg_done[8];
+ wait_queue_head_t msg_wait;
+ struct v4l2_ctrl *link_freq;
+ struct v4l2_ctrl_handler ctrl_handler;
+};
+
+static const s64 link_freq_menu_items[] = {
+ 1000000000
+};
+
+static inline struct rk1608_state *to_state(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct rk1608_state, sd);
+}
+
+/**
+ * rk1608_operation_query - RK1608 last operation state query
+ *
+ * @spi: device from which data will be read
+ * @state: last operation state [out]
+ * Context: can sleep
+ *
+ * It returns zero on success, else a negative error code.
+ */
+int rk1608_operation_query(struct spi_device *spi, s32 *state)
+{
+ s32 query_cmd = RK1608_CMD_QUERY;
+ struct spi_transfer query_cmd_packet = {
+ .tx_buf = &query_cmd,
+ .len = sizeof(query_cmd),
+ };
+ struct spi_transfer state_packet = {
+ .rx_buf = state,
+ .len = sizeof(*state),
+ };
+ struct spi_message m;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&query_cmd_packet, &m);
+ spi_message_add_tail(&state_packet, &m);
+ spi_sync(spi, &m);
+
+ return ((*state & RK1608_STATE_ID_MASK) == RK1608_STATE_ID) ? 0 : -1;
+}
+
+int rk1608_write(struct spi_device *spi,
+ s32 addr, const s32 *data, size_t data_len)
+{
+ s32 write_cmd = RK1608_CMD_WRITE;
+ struct spi_transfer write_cmd_packet = {
+ .tx_buf = &write_cmd,
+ .len = sizeof(write_cmd),
+ };
+ struct spi_transfer addr_packet = {
+ .tx_buf = &addr,
+ .len = sizeof(addr),
+ };
+ struct spi_transfer data_packet = {
+ .tx_buf = data,
+ .len = data_len,
+ };
+ struct spi_message m;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&write_cmd_packet, &m);
+ spi_message_add_tail(&addr_packet, &m);
+ spi_message_add_tail(&data_packet, &m);
+ return spi_sync(spi, &m);
+}
+
+/**
+ * rk1608_safe_write - RK1608 synchronous write with state check
+ *
+ * @spi: spi device
+ * @addr: resource address
+ * @data: data buffer
+ * @data_len: data buffer size, in bytes
+ * Context: can sleep
+ *
+ * It returns zero on success, else operation state code.
+ */
+int rk1608_safe_write(struct spi_device *spi,
+ s32 addr, const s32 *data, size_t data_len)
+{
+ int ret = 0;
+ s32 state, retry = 0;
+
+ while (data_len > 0) {
+ size_t slen = MIN(data_len, RK1608_MAX_OP_BYTES);
+
+ do {
+ rk1608_write(spi, addr, data, data_len);
+ if (rk1608_operation_query(spi, &state) != 0)
+ return -1;
+ if ((state & RK1608_STATE_MASK) == 0)
+ break;
+
+ udelay(RK1608_OP_TRY_DELAY);
+ } while (retry++ != RK1608_OP_TRY_MAX);
+
+ data_len = data_len - slen;
+ data = (s32 *)((s8 *)data + slen);
+ addr += slen;
+ }
+ return ret;
+}
+
+void rk1608_hw_init(struct spi_device *spi)
+{
+ s32 write_data = SPI0_PLL_SEL_APLL;
+
+ /* modify rk1608 spi slave clk to 300M */
+ rk1608_safe_write(spi, CRUPMU_CLKSEL14_CON, &write_data, 4);
+
+ /* modify rk1608 spi io driver strength to 8mA */
+ write_data = BIT7_6_SEL_8MA;
+ rk1608_safe_write(spi, PMUGRF_GPIO1A_E, &write_data, 4);
+ write_data = BIT1_0_SEL_8MA;
+ rk1608_safe_write(spi, PMUGRF_GPIO1B_E, &write_data, 4);
+}
+
+/**
+ * rk1608_read - RK1608 synchronous read
+ *
+ * @spi: spi device
+ * @addr: resource address
+ * @data: data buffer [out]
+ * @data_len: data buffer size, in bytes
+ * Context: can sleep
+ *
+ * It returns zero on success, else a negative error code.
+ */
+int rk1608_read(struct spi_device *spi,
+ s32 addr, s32 *data, size_t data_len)
+{
+ s32 real_len = MIN(data_len, RK1608_MAX_OP_BYTES);
+ s32 read_cmd = RK1608_CMD_READ | (real_len << 14 &
+ RK1608_STATE_ID_MASK);
+ s32 read_begin_cmd = RK1608_CMD_READ_BEGIN;
+ s32 dummy = 0;
+ struct spi_transfer read_cmd_packet = {
+ .tx_buf = &read_cmd,
+ .len = sizeof(read_cmd),
+ };
+ struct spi_transfer addr_packet = {
+ .tx_buf = &addr,
+ .len = sizeof(addr),
+ };
+ struct spi_transfer read_dummy_packet = {
+ .tx_buf = &dummy,
+ .len = sizeof(dummy),
+ };
+ struct spi_transfer read_begin_cmd_packet = {
+ .tx_buf = &read_begin_cmd,
+ .len = sizeof(read_begin_cmd),
+ };
+ struct spi_transfer data_packet = {
+ .rx_buf = data,
+ .len = data_len,
+ };
+ struct spi_message m;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&read_cmd_packet, &m);
+ spi_message_add_tail(&addr_packet, &m);
+ spi_message_add_tail(&read_dummy_packet, &m);
+ spi_message_add_tail(&read_begin_cmd_packet, &m);
+ spi_message_add_tail(&data_packet, &m);
+ return spi_sync(spi, &m);
+}
+
+/**
+ * rk1608_safe_read - RK1608 synchronous read with state check
+ *
+ * @spi: spi device
+ * @addr: resource address
+ * @data: data buffer [out]
+ * @data_len: data buffer size, in bytes
+ * Context: can sleep
+ *
+ * It returns zero on success, else operation state code.
+ */
+int rk1608_safe_read(struct spi_device *spi,
+ s32 addr, s32 *data, size_t data_len)
+{
+ s32 state = 0;
+ s32 retry = 0;
+
+ do {
+ rk1608_read(spi, addr, data, data_len);
+ if (rk1608_operation_query(spi, &state) != 0)
+ return -1;
+ if ((state & RK1608_STATE_MASK) == 0)
+ break;
+ udelay(RK1608_OP_TRY_DELAY);
+ } while (retry++ != RK1608_OP_TRY_MAX);
+
+ return (state & RK1608_STATE_MASK);
+}
+
+static int rk1608_read_wait(struct spi_device *spi,
+ const struct rk1608_section *sec)
+{
+ s32 value = 0;
+ int retry = 0;
+ int ret = 0;
+
+ do {
+ ret = rk1608_safe_read(spi, sec->wait_addr, &value, 4);
+ if (!ret && value == sec->wait_value)
+ break;
+
+ if (retry++ == sec->timeout) {
+ ret = -1;
+ dev_err(&spi->dev, "read 0x%x is %x != %x timeout\n",
+ sec->wait_addr, value, sec->wait_value);
+ break;
+ }
+ mdelay(sec->wait_time);
+ } while (1);
+
+ return ret;
+}
+
+static int rk1608_boot_request(struct spi_device *spi,
+ const struct rk1608_section *sec)
+{
+ struct rk1608_boot_req boot_req;
+ int retry = 0;
+ int ret = 0;
+
+ /*send boot request to rk1608 for ddr init*/
+ boot_req.flag = sec->flag;
+ boot_req.load_addr = sec->load_addr;
+ boot_req.boot_len = sec->size;
+ boot_req.status = 1;
+ boot_req.cmd = 2;
+
+ ret = rk1608_safe_write(spi, BOOT_REQUEST_ADDR,
+ (s32 *)&boot_req, sizeof(boot_req));
+ if (ret)
+ return ret;
+
+ if (sec->flag & BOOT_FLAG_READ_WAIT) {
+ /*waitting for rk1608 init ddr done*/
+ do {
+ ret = rk1608_safe_read(spi, BOOT_REQUEST_ADDR,
+ (s32 *)&boot_req,
+ sizeof(boot_req));
+
+ if (!ret && boot_req.status == 0)
+ break;
+
+ if (retry++ == sec->timeout) {
+ ret = -1;
+ dev_err(&spi->dev, "boot_request timeout\n");
+ break;
+ }
+ mdelay(sec->wait_time);
+ } while (1);
+ }
+
+ return ret;
+}
+
+static int rk1608_download_section(struct spi_device *spi, const u8 *data,
+ const struct rk1608_section *sec)
+{
+ int ret = 0;
+
+ dev_info(&spi->dev, "offset:%x,size:%x,addr:%x,wait_time:%x",
+ sec->offset, sec->size, sec->load_addr, sec->wait_time);
+ dev_info(&spi->dev, "timeout:%x,crc:%x,flag:%x,type:%x",
+ sec->timeout, sec->crc_16, sec->flag, sec->type);
+
+ if (sec->size > 0) {
+ ret = rk1608_safe_write(spi, sec->load_addr,
+ (s32 *)(data + sec->offset),
+ sec->size);
+ if (ret) {
+ dev_err(&spi->dev, "rk1608_safe_write err =%d\n", ret);
+ return ret;
+ }
+ }
+
+ if (sec->flag & BOOT_FLAG_BOOT_REQUEST)
+ ret = rk1608_boot_request(spi, sec);
+ else if (sec->flag & BOOT_FLAG_READ_WAIT)
+ ret = rk1608_read_wait(spi, sec);
+
+ return ret;
+}
+
+/**
+ * rk1608_download_fw: - rk1608 firmware download through spi
+ *
+ * @spi: spi device
+ * @fw_name: name of firmware file, NULL for default firmware name
+ * Context: can sleep
+ *
+ * It returns zero on success, else a negative error code.
+ **/
+int rk1608_download_fw(struct spi_device *spi, const char *fw_name)
+{
+ const struct rk1608_header *head;
+ const struct firmware *fw;
+ int i = 0;
+ int ret = 0;
+
+ if (!fw_name)
+ fw_name = RK1608_FW_NAME;
+
+ dev_info(&spi->dev, "before request firmware");
+ ret = request_firmware(&fw, fw_name, &spi->dev);
+ if (ret) {
+ dev_err(&spi->dev, "request firmware %s failed!", fw_name);
+ return ret;
+ }
+
+ head = (const struct rk1608_header *)fw->data;
+
+ dev_info(&spi->dev, "request firmware %s (version:%s) success!",
+ fw_name, head->version);
+
+ for (i = 0; i < head->section_count; i++) {
+ ret = rk1608_download_section(spi, fw->data,
+ &head->sections[i]);
+ if (ret)
+ break;
+ }
+
+ release_firmware(fw);
+ return ret;
+}
+
+int rk1608_lsb_w32(struct spi_device *spi, s32 addr, s32 data)
+{
+ s32 write_cmd = RK1608_CMD_WRITE;
+ struct spi_transfer write_cmd_packet = {
+ .tx_buf = &write_cmd,
+ .len = sizeof(write_cmd),
+ };
+ struct spi_transfer addr_packet = {
+ .tx_buf = &addr,
+ .len = sizeof(addr),
+ };
+ struct spi_transfer data_packet = {
+ .tx_buf = &data,
+ .len = sizeof(data),
+ };
+ struct spi_message m;
+
+ write_cmd = MSB2LSB32(write_cmd);
+ addr = MSB2LSB32(addr);
+ data = MSB2LSB32(data);
+ spi_message_init(&m);
+ spi_message_add_tail(&write_cmd_packet, &m);
+ spi_message_add_tail(&addr_packet, &m);
+ spi_message_add_tail(&data_packet, &m);
+ return spi_sync(spi, &m);
+}
+
+void rk1608_cs_set_value(struct rk1608_state *pdata, int value)
+{
+ s8 null_cmd = 0;
+ struct spi_transfer null_cmd_packet = {
+ .tx_buf = &null_cmd,
+ .len = sizeof(null_cmd),
+ .cs_change = !value,
+ };
+ struct spi_message m;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&null_cmd_packet, &m);
+ spi_sync(pdata->spi, &m);
+}
+
+void rk1608_set_spi_speed(struct rk1608_state *pdata, u32 hz)
+{
+ pdata->spi->max_speed_hz = hz;
+}
+
+static int rk1608_sensor_power(struct v4l2_subdev *sd, int on)
+{
+ int ret = 0;
+ struct rk1608_state *pdata = to_state(sd);
+ struct spi_device *spi = pdata->spi;
+
+ mutex_lock(&pdata->lock);
+ /*start Sensor power on/off*/
+ if (pdata->sensor_sd)
+ pdata->sensor_sd->ops->core->s_power(pdata->sensor_sd, on);
+ if (on && !pdata->power_count) {
+ clk_prepare_enable(pdata->mclk);
+ clk_set_rate(pdata->mclk, RK1608_MCLK_RATE);
+ /*request rk1608 enter slave mode*/
+ rk1608_cs_set_value(pdata, 0);
+ if (pdata->powerdown_gpio > 0) {
+ gpio_set_value(pdata->powerdown_gpio,
+ pdata->powerdown_active);
+ }
+ if (pdata->wakeup_gpio > 0) {
+ gpio_set_value(pdata->wakeup_gpio,
+ pdata->wakeup_active);
+ }
+ mdelay(3);
+ if (pdata->reset_gpio > 0)
+ gpio_set_value(pdata->reset_gpio, pdata->reset_active);
+ mdelay(5);
+ rk1608_cs_set_value(pdata, 1);
+ rk1608_set_spi_speed(pdata, pdata->min_speed_hz);
+ rk1608_lsb_w32(spi, SPI_ENR, 0);
+ rk1608_lsb_w32(spi, SPI_CTRL0,
+ OPM_SLAVE_MODE | RSD_SEL_2CYC | DFS_SEL_16BIT);
+ rk1608_hw_init(pdata->spi);
+ rk1608_set_spi_speed(pdata, pdata->max_speed_hz);
+ /*download system firmware*/
+ ret = rk1608_download_fw(pdata->spi, NULL);
+ if (ret)
+ dev_err(pdata->dev, "Download firmware failed!");
+ else
+ dev_info(pdata->dev, "Download firmware success!");
+ enable_irq(pdata->irq);
+ if (pdata->sleepst_irq > 0)
+ enable_irq(pdata->sleepst_irq);
+
+ } else if (!on && pdata->power_count == 1) {
+ disable_irq(pdata->irq);
+ if (pdata->sleepst_irq > 0)
+ disable_irq(pdata->sleepst_irq);
+ if (pdata->powerdown_gpio > 0)
+ gpio_set_value(pdata->powerdown_gpio,
+ !pdata->powerdown_active);
+
+ if (pdata->wakeup_gpio > 0)
+ gpio_set_value(pdata->wakeup_gpio,
+ !pdata->wakeup_active);
+
+ if (pdata->reset_gpio > 0)
+ gpio_set_value(pdata->reset_gpio, !pdata->reset_active);
+
+ rk1608_cs_set_value(pdata, 0);
+ clk_disable_unprepare(pdata->mclk);
+ }
+ /* Update the power count. */
+ pdata->power_count += on ? 1 : -1;
+ WARN_ON(pdata->power_count < 0);
+ mutex_unlock(&pdata->lock);
+
+ return ret;
+}
+
+static int rk1608_stream_on(struct rk1608_state *pdata)
+{
+ int cnt = 0;
+
+ /*Waiting for the sensor to be ready*/
+ while (pdata->sensor_cnt < pdata->sensor_nums) {
+ /* TIMEOUT 10s break*/
+ if (cnt++ > SENSOR_TIMEOUT) {
+ dev_err(pdata->dev, "Sensor%d is ready to timeout!",
+ pdata->sensor_cnt);
+ break;
+ }
+ mdelay(10);
+ }
+
+ if (pdata->sensor_nums) {
+ if (pdata->sensor_cnt == pdata->sensor_nums)
+ dev_info(pdata->dev, "Sensor(num %d) is ready!",
+ pdata->sensor_cnt);
+ } else {
+ dev_warn(pdata->dev, "No sensor is found!");
+ }
+
+ return 0;
+}
+
+static int rk1608_stream_off(struct rk1608_state *pdata)
+{
+ mutex_lock(&pdata->sensor_lock);
+ pdata->sensor_cnt = 0;
+ mutex_unlock(&pdata->sensor_lock);
+ return 0;
+}
+
+static int rk1608_s_stream(struct v4l2_subdev *sd, int enable)
+{
+ struct rk1608_state *pdata = to_state(sd);
+
+ if (enable)
+ return rk1608_stream_on(pdata);
+ else
+ return rk1608_stream_off(pdata);
+}
+
+static int rk1608_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ if (code->index > 0)
+ return -EINVAL;
+
+ code->code = MEDIA_BUS_FMT_SGRBG8_1X8;
+
+ return 0;
+}
+
+static int rk1608_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *fmt)
+{
+ struct v4l2_mbus_framefmt *mf = &fmt->format;
+
+ mf->code = MEDIA_BUS_FMT_SGRBG8_1X8;
+ mf->width = RK1608_WINDOW_WIDTH_DEF;
+ mf->height = RK1608_WINDOW_HEIGHT_DEF;
+ mf->field = V4L2_FIELD_NONE;
+ mf->colorspace = V4L2_COLORSPACE_SRGB;
+
+ return 0;
+}
+
+static const struct v4l2_subdev_internal_ops rk1608_subdev_internal_ops = {
+ .open = NULL,
+};
+
+static const struct v4l2_subdev_video_ops rk1608_subdev_video_ops = {
+ .s_stream = rk1608_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops rk1608_subdev_pad_ops = {
+ .enum_mbus_code = rk1608_enum_mbus_code,
+ .get_fmt = rk1608_get_fmt,
+};
+
+static const struct v4l2_subdev_core_ops rk1608_core_ops = {
+ .s_power = rk1608_sensor_power,
+};
+
+static const struct v4l2_subdev_ops rk1608_subdev_ops = {
+ .core = &rk1608_core_ops,
+ .video = &rk1608_subdev_video_ops,
+ .pad = &rk1608_subdev_pad_ops,
+};
+
+/**
+ * rk1608_msq_read_head - read rk1608 msg queue head
+ *
+ * @spi: spi device
+ * @addr: msg queue head addr
+ * @m: msg queue pointer
+ *
+ * It returns zero on success, else a negative error code.
+ */
+int rk1608_msq_read_head(struct spi_device *spi,
+ u32 addr, struct rk1608_msg_queue *q)
+{
+ int err = 0;
+ s32 reg;
+
+ err = rk1608_safe_read(spi, RK1608_PMU_SYS_REG0, ®, 4);
+
+ if (err || ((reg & RK1608_MSG_QUEUE_OK_MASK) !=
+ RK1608_MSG_QUEUE_OK_TAG))
+ return -1;
+
+ err = rk1608_safe_read(spi, addr, (s32 *)q, sizeof(*q));
+
+ return err;
+}
+
+/**
+ * rk1608_msq_recv_msg - receive a msg from RK1608 -> AP msg queue
+ *
+ * @q: msg queue
+ * @m: a msg pointer buf [out]
+ *
+ * need call rk1608_msq_recv_msg_free to free msg after msg use done
+ *
+ * It returns zero on success, else a negative error code.
+ */
+int rk1608_msq_recv_msg(struct spi_device *spi, struct msg **m)
+{
+ struct rk1608_msg_queue queue;
+ struct rk1608_msg_queue *q = &queue;
+ u32 size = 0, msg_size = 0;
+ u32 recv_addr = 0;
+ u32 next_recv_addr = 0;
+ int err = 0;
+
+ *m = NULL;
+ err = rk1608_msq_read_head(spi, RK1608_S_MSG_QUEUE_ADDR, q);
+ if (err)
+ return err;
+
+ if (q->cur_send == q->cur_recv)
+ return -1;
+ /*skip to head when size is 0*/
+ err = rk1608_safe_read(spi, (s32)q->cur_recv, (s32 *)&size, 4);
+ if (err)
+ return err;
+ if (size == 0) {
+ err = rk1608_safe_read(spi, (s32)q->buf_head, (s32 *)&size, 4);
+ if (err)
+ return err;
+
+ msg_size = size * sizeof(u32);
+ recv_addr = q->buf_head;
+ next_recv_addr = q->buf_head + msg_size;
+ } else {
+ msg_size = size * sizeof(u32);
+ recv_addr = q->cur_recv;
+ next_recv_addr = q->cur_recv + msg_size;
+ if (next_recv_addr == q->buf_tail)
+ next_recv_addr = q->buf_head;
+ }
+
+ if (msg_size > (q->buf_tail - q->buf_head))
+ return -2;
+
+ *m = kmalloc(msg_size, GFP_KERNEL);
+ err = rk1608_safe_read(spi, recv_addr, (s32 *)*m, msg_size);
+ if (err == 0) {
+ err = rk1608_safe_write(spi, RK1608_S_MSG_QUEUE_ADDR +
+ (u8 *)&q->cur_recv - (u8 *)q,
+ &next_recv_addr, 4);
+ }
+ if (err)
+ kfree(*m);
+
+ return err;
+}
+
+static void print_rk1608_log(struct rk1608_state *pdata,
+ struct msg_rk1608_log_t *log)
+{
+ char *str = (char *)(log);
+
+ str[log->size * sizeof(s32) - 1] = 0;
+ str += sizeof(struct msg_rk1608_log_t);
+ dev_info(pdata->dev, "RK1608%d: %s", log->core_id, str);
+}
+
+void int32_hexdump(const char *prefix, int32_t *data, int len)
+{
+ pr_err("%s\n", prefix);
+ print_hex_dump(KERN_ERR, "offset ", DUMP_PREFIX_OFFSET,
+ 16, 4, data, len, false);
+ pr_err("\n");
+}
+
+static void dispatch_received_msg(struct rk1608_state *pdata,
+ struct msg *msg)
+{
+ #if DEBUG_DUMP_ALL_SEND_RECV_MSG == 1
+ int32_hexdump("recv msg:", (s32 *)msg, msg->size * 4);
+ #endif
+
+ if (msg->type == id_msg_set_stream_out_on_ret_t) {
+ mutex_lock(&pdata->sensor_lock);
+ pdata->sensor_cnt++;
+ mutex_unlock(&pdata->sensor_lock);
+ }
+
+ if (msg->type == id_msg_rk1608_log_t)
+ print_rk1608_log(pdata, (struct msg_rk1608_log_t *)msg);
+}
+
+static irqreturn_t rk1608_threaded_isr(int irq, void *dev_id)
+{
+ struct rk1608_state *pdata = dev_id;
+ struct msg *msg;
+
+ WARN_ON(irq != pdata->irq);
+ while (!rk1608_msq_recv_msg(pdata->spi, &msg) && NULL != msg) {
+ dispatch_received_msg(pdata, msg);
+ /* for kernel msg sync */
+ if (pdata->msg_num != 0 && msg->sync) {
+ dev_info(pdata->dev, "rk1608 kernel sync\n");
+ mutex_lock(&pdata->send_msg_lock);
+ pdata->msg_num--;
+ atomic_set(&pdata->msg_done[pdata->msg_num], 1);
+ mutex_unlock(&pdata->send_msg_lock);
+ wake_up(&pdata->msg_wait);
+ }
+ kfree(msg);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t rk1608_sleep_isr(int irq, void *dev_id)
+{
+ struct rk1608_state *pdata = dev_id;
+
+ WARN_ON(irq != pdata->sleepst_irq);
+ if (pdata->powerdown_gpio > 0)
+ gpio_set_value(pdata->powerdown_gpio, !pdata->powerdown_active);
+
+ return IRQ_HANDLED;
+}
+
+static int rk1608_parse_dt_property(struct rk1608_state *pdata)
+{
+ int ret = 0;
+ int i;
+ struct device *dev = pdata->dev;
+ struct device_node *node = dev->of_node;
+ enum of_gpio_flags flags;
+
+ if (!node)
+ return 1;
+
+ ret = of_property_read_u32(node, "spi-max-frequency",
+ &pdata->max_speed_hz);
+ if (ret <= 0) {
+ dev_warn(dev, "can not get spi-max-frequency!");
+ pdata->max_speed_hz = RK1608_MCLK_RATE;
+ }
+
+ ret = of_property_read_u32(node, "spi-min-frequency",
+ &pdata->min_speed_hz);
+ if (ret <= 0) {
+ dev_warn(dev, "can not get spi-min-frequency!");
+ pdata->min_speed_hz = pdata->max_speed_hz / 2;
+ }
+
+ pdata->mclk = devm_clk_get(dev, "mclk");
+ if (IS_ERR(pdata->mclk)) {
+ dev_err(dev, "can not get mclk, error %ld\n",
+ PTR_ERR(pdata->mclk));
+ pdata->mclk = NULL;
+ return -1;
+ }
+
+ ret = of_get_named_gpio_flags(node, "reset-gpio", 0, &flags);
+ if (ret <= 0) {
+ dev_warn(dev, "can not find reset-gpio, error %d\n", ret);
+ return ret;
+ }
+ pdata->reset_gpio = ret;
+ pdata->reset_active = 1;
+ if (flags == OF_GPIO_ACTIVE_LOW)
+ pdata->reset_active = 0;
+
+ if (pdata->reset_gpio > 0) {
+ ret = devm_gpio_request(dev, pdata->reset_gpio, "rk1608-reset");
+ if (ret) {
+ dev_err(dev, "gpio %d request error %d\n",
+ pdata->reset_gpio, ret);
+ return ret;
+ }
+
+ ret = gpio_direction_output(pdata->reset_gpio,
+ !pdata->reset_active);
+ if (ret) {
+ dev_err(dev, "gpio %d direction output error %d\n",
+ pdata->reset_gpio, ret);
+ return ret;
+ }
+ }
+
+ ret = of_get_named_gpio_flags(node, "irq-gpio", 0, NULL);
+ if (ret <= 0) {
+ dev_warn(dev, "can not find irq-gpio, error %d\n", ret);
+ return ret;
+ }
+
+ pdata->irq_gpio = ret;
+
+ ret = devm_gpio_request(dev, pdata->irq_gpio, "rk1608-irq");
+ if (ret) {
+ dev_err(dev, "gpio %d request error %d\n", pdata->irq_gpio,
+ ret);
+ return ret;
+ }
+
+ ret = gpio_direction_input(pdata->irq_gpio);
+ if (ret) {
+ dev_err(dev, "gpio %d direction input error %d\n",
+ pdata->irq_gpio, ret);
+ return ret;
+ }
+
+ ret = gpio_to_irq(pdata->irq_gpio);
+ if (ret < 0) {
+ dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n",
+ pdata->irq_gpio, ret);
+ return ret;
+ }
+ pdata->irq = ret;
+ ret = request_threaded_irq(pdata->irq, NULL, rk1608_threaded_isr,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "rk1608-irq", pdata);
+ if (ret) {
+ dev_err(dev, "cannot request thread irq: %d\n", ret);
+ return ret;
+ }
+
+ disable_irq(pdata->irq);
+
+ ret = of_get_named_gpio_flags(node, "powerdown-gpio", 0, &flags);
+ if (ret <= 0)
+ dev_warn(dev, "can not find powerdown-gpio, error %d\n", ret);
+
+ pdata->powerdown_gpio = ret;
+ pdata->powerdown_active = 1;
+ if (flags == OF_GPIO_ACTIVE_LOW)
+ pdata->powerdown_active = 0;
+
+ if (pdata->powerdown_gpio > 0) {
+ ret = devm_gpio_request(dev, pdata->powerdown_gpio,
+ "rk1608-powerdown");
+ if (ret) {
+ dev_err(dev, "gpio %d request error %d\n",
+ pdata->powerdown_gpio, ret);
+ return ret;
+ }
+
+ ret = gpio_direction_output(pdata->powerdown_gpio,
+ !pdata->powerdown_active);
+ if (ret) {
+ dev_err(dev, "gpio %d direction output error %d\n",
+ pdata->powerdown_gpio, ret);
+ return ret;
+ }
+ }
+
+ pdata->sleepst_gpio = -1;
+ pdata->sleepst_irq = -1;
+ pdata->wakeup_gpio = -1;
+
+ ret = of_get_named_gpio_flags(node, "sleepst-gpio", 0, NULL);
+ if (ret <= 0) {
+ dev_warn(dev, "can not find property sleepst-gpio, error %d\n",
+ ret);
+ return ret;
+ }
+
+ pdata->sleepst_gpio = ret;
+
+ ret = devm_gpio_request(dev, pdata->sleepst_gpio, "rk1608-sleep-irq");
+ if (ret) {
+ dev_err(dev, "gpio %d request error %d\n",
+ pdata->sleepst_gpio, ret);
+ return ret;
+ }
+
+ ret = gpio_direction_input(pdata->sleepst_gpio);
+ if (ret) {
+ dev_err(dev, "gpio %d direction input error %d\n",
+ pdata->sleepst_gpio, ret);
+ return ret;
+ }
+
+ ret = gpio_to_irq(pdata->sleepst_gpio);
+ if (ret < 0) {
+ dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n",
+ pdata->sleepst_gpio, ret);
+ return ret;
+ }
+ pdata->sleepst_irq = ret;
+ ret = request_any_context_irq(pdata->sleepst_irq,
+ rk1608_sleep_isr,
+ IRQF_TRIGGER_RISING,
+ "rk1608-sleepst", pdata);
+ disable_irq(pdata->sleepst_irq);
+
+ ret = of_get_named_gpio_flags(node, "wakeup-gpio", 0, &flags);
+ if (ret <= 0)
+ dev_warn(dev, "can not find wakeup-gpio error %d\n", ret);
+
+ pdata->wakeup_gpio = ret;
+ pdata->wakeup_active = 1;
+ if (flags == OF_GPIO_ACTIVE_LOW)
+ pdata->wakeup_active = 0;
+
+ if (pdata->wakeup_gpio > 0) {
+ ret = devm_gpio_request(dev, pdata->wakeup_gpio,
+ "rk1608-wakeup");
+ if (ret) {
+ dev_err(dev, "gpio %d request error %d\n",
+ pdata->wakeup_gpio, ret);
+ return ret;
+ }
+
+ ret = gpio_direction_output(pdata->wakeup_gpio,
+ !pdata->wakeup_active);
+ if (ret) {
+ dev_err(dev, "gpio %d direction output error %d\n",
+ pdata->wakeup_gpio, ret);
+ return ret;
+ }
+ }
+ pdata->msg_num = 0;
+ init_waitqueue_head(&pdata->msg_wait);
+ for (i = 0; i < 8; i++)
+ atomic_set(&pdata->msg_done[i], 0);
+
+ return ret;
+}
+
+static int get_remote_node_dev(struct rk1608_state *pdev)
+{
+ struct platform_device *sensor_pdev = NULL;
+ struct device *dev = pdev->dev;
+ struct device_node *parent = dev->of_node;
+ struct device_node *node, *pre_node = NULL;
+ struct device_node *remote = NULL;
+ int ret, sensor_nums = 0;
+
+ node = of_graph_get_next_endpoint(parent, pre_node);
+ if (node) {
+ of_node_put(pre_node);
+ pre_node = node;
+ } else {
+ dev_err(dev, "fieled to get endpoint\n");
+ return -EINVAL;
+ }
+ while ((node = of_graph_get_next_endpoint(parent, pre_node)) != NULL) {
+ of_node_put(pre_node);
+ pre_node = node;
+ remote = of_graph_get_remote_port_parent(node);
+ if (!remote) {
+ dev_err(dev, "%s: no valid device\n", __func__);
+ of_node_put(remote);
+ ret = -EINVAL;
+ }
+
+ sensor_pdev = of_find_device_by_node(remote);
+ of_node_put(remote);
+
+ if (!sensor_pdev) {
+ dev_err(dev, "fieled to get Sensor device\n");
+ ret = -EINVAL;
+ } else {
+ pdev->sensor_sd = platform_get_drvdata(sensor_pdev);
+ if (pdev->sensor_sd)
+ sensor_nums++;
+ else
+ dev_err(dev, "fieled to get Sensor drvdata\n");
+ ret = 0;
+ }
+ }
+ pdev->sensor_nums = sensor_nums;
+ if (pdev->sensor_nums)
+ dev_info(dev, "get Sensor (nums=%d) dev is OK!\n",
+ pdev->sensor_nums);
+
+ return ret;
+}
+
+static int rk1608_probe(struct spi_device *spi)
+{
+ struct rk1608_state *rk1608;
+ struct v4l2_subdev *sd;
+ struct v4l2_ctrl_handler *handler;
+ int ret;
+
+ rk1608 = devm_kzalloc(&spi->dev, sizeof(*rk1608), GFP_KERNEL);
+ if (!rk1608)
+ return -ENOMEM;
+ rk1608->dev = &spi->dev;
+ rk1608->spi = spi;
+ spi_set_drvdata(spi, rk1608);
+ ret = rk1608_parse_dt_property(rk1608);
+ if (ret) {
+ dev_err(rk1608->dev, "rk1608 parse dt property err(%x)\n", ret);
+ goto parse_err;
+ }
+ ret = get_remote_node_dev(rk1608);
+ if (ret)
+ dev_warn(rk1608->dev, "get remote node dev err(%x)\n", ret);
+ rk1608->sensor_cnt = 0;
+ mutex_init(&rk1608->sensor_lock);
+ mutex_init(&rk1608->send_msg_lock);
+ mutex_init(&rk1608->lock);
+ sd = &rk1608->sd;
+ v4l2_spi_subdev_init(sd, spi, &rk1608_subdev_ops);
+
+ handler = &rk1608->ctrl_handler;
+ ret = v4l2_ctrl_handler_init(handler, 1);
+ if (ret)
+ goto handler_init_err;
+
+ rk1608->link_freq = v4l2_ctrl_new_int_menu(handler, NULL,
+ V4L2_CID_LINK_FREQ,
+ 0, 0, link_freq_menu_items);
+ if (rk1608->link_freq)
+ rk1608->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+ if (handler->error)
+ goto handler_err;
+
+ sd->ctrl_handler = handler;
+ sd->internal_ops = &rk1608_subdev_internal_ops;
+ sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ rk1608->pad.flags = MEDIA_PAD_FL_SOURCE;
+ sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+
+ ret = media_entity_init(&sd->entity, 1, &rk1608->pad, 0);
+ if (ret < 0)
+ goto handler_err;
+
+ ret = v4l2_async_register_subdev(sd);
+ if (ret < 0)
+ goto register_err;
+ dev_info(rk1608->dev, "DSP rk1608 Driver probe is OK!\n");
+
+ return 0;
+register_err:
+ media_entity_cleanup(&sd->entity);
+handler_err:
+ v4l2_ctrl_handler_free(handler);
+handler_init_err:
+ v4l2_device_unregister_subdev(&rk1608->sd);
+ mutex_destroy(&rk1608->lock);
+ mutex_destroy(&rk1608->send_msg_lock);
+ mutex_destroy(&rk1608->sensor_lock);
+parse_err:
+ kfree(rk1608);
+ return ret;
+}
+
+static int rk1608_remove(struct spi_device *spi)
+{
+ struct rk1608_state *rk1608 = spi_get_drvdata(spi);
+
+ v4l2_async_unregister_subdev(&rk1608->sd);
+ media_entity_cleanup(&rk1608->sd.entity);
+ v4l2_ctrl_handler_free(&rk1608->ctrl_handler);
+ v4l2_device_unregister_subdev(&rk1608->sd);
+ mutex_destroy(&rk1608->lock);
+ mutex_destroy(&rk1608->send_msg_lock);
+ mutex_destroy(&rk1608->sensor_lock);
+ kfree(rk1608);
+
+ return 0;
+}
+
+static const struct spi_device_id rk1608_id[] = {
+ { "RK1608", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, rk1608_id);
+
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id rk1608_of_match[] = {
+ { .compatible = "rockchip,rk1608" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, rk1608_of_match);
+#endif
+
+static struct spi_driver rk1608_driver = {
+ .driver = {
+ .of_match_table = of_match_ptr(rk1608_of_match),
+ .name = "RK1608",
+ },
+ .probe = rk1608_probe,
+ .remove = rk1608_remove,
+ .id_table = rk1608_id,
+};
+
+module_spi_driver(rk1608_driver);
+
+MODULE_AUTHOR("Rockchip Camera/ISP team");
+MODULE_DESCRIPTION("A DSP driver for rk1608 chip");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/media/spi/rk1608.h b/drivers/media/spi/rk1608.h
new file mode 100644
index 0000000..bf0c5ec
--- /dev/null
+++ b/drivers/media/spi/rk1608.h
@@ -0,0 +1,366 @@
+/**
+ * Rockchip rk1608 driver
+ *
+ * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __RK1608_H__
+#define __RK1608_H__
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/spi/spi.h>
+#include "linux/i2c.h"
+
+#define RK1608_OP_TRY_MAX 3
+#define RK1608_OP_TRY_DELAY 10
+#define RK1608_CMD_WRITE 0x00000011
+#define RK1608_CMD_WRITE_REG0 0X00010011
+#define RK1608_CMD_WRITE_REG1 0X00020011
+#define RK1608_CMD_READ 0x00000077
+#define RK1608_CMD_READ_BEGIN 0x000000aa
+#define RK1608_CMD_QUERY 0x000000ff
+#define RK1608_CMD_QUERY_REG2 0x000001ff
+#define RK1608_STATE_ID_MASK (0xffff0000)
+#define RK1608_STATE_ID (0X16080000)
+#define RK1608_STATE_MASK (0x0000ffff)
+
+#define BOOT_REQUEST_ADDR 0x18000010
+#define RK1608_HEAD_ADDR 0x60000000
+#define RK1608_FW_NAME "rk1608.rkl"
+#define RK1608_S_MSG_QUEUE_ADDR 0x60050010
+#define RK1608_PMU_SYS_REG0 0x120000f0
+#define RK1608_MSG_QUEUE_OK_MASK 0xffff0001
+#define RK1608_MSG_QUEUE_OK_TAG 0x16080001
+#define RK1608_MAX_OP_BYTES 60000
+
+#define RK1608_WINDOW_HEIGHT_DEF 480
+#define RK1608_WINDOW_WIDTH_DEF 640
+
+#define BOOT_FLAG_CRC (0x01 << 0)
+#define BOOT_FLAG_EXE (0x01 << 1)
+#define BOOT_FLAG_LOAD_PMEM (0x01 << 2)
+#define BOOT_FLAG_ACK (0x01 << 3)
+#define BOOT_FLAG_READ_WAIT (0x01 << 4)
+#define BOOT_FLAG_BOOT_REQUEST (0x01 << 5)
+
+#define DEBUG_DUMP_ALL_SEND_RECV_MSG 0
+#define RK1608_MCLK_RATE (24 * 1000 * 1000ul)
+#define SENSOR_TIMEOUT 1000
+#define GRF_BASE_ADDR 0xff770000
+#define GRF_GPIO2B_IOMUX 0x0014
+#define GRF_IO_VSEL 0x0380
+#define OPM_SLAVE_MODE 0X100000
+#define RSD_SEL_2CYC 0X008000
+#define DFS_SEL_16BIT 0X000002
+#define SPI_CTRL0 0x11060000
+#define SPI_ENR 0x11060008
+#define CRUPMU_CLKSEL14_CON 0x12008098
+#define PMUGRF_GPIO1A_E 0x12030040
+#define PMUGRF_GPIO1B_E 0x12030044
+#define BIT7_6_SEL_8MA 0xf000a000
+#define BIT1_0_SEL_8MA 0x000f000a
+#define SPI0_PLL_SEL_APLL 0xff004000
+#define INVALID_ID -1
+#define RK1608_MAX_SEC_NUM 10
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MSB2LSB32
+#define MSB2LSB32(x) ((((u32)x & 0x80808080) >> 7) | \
+ (((u32)x & 0x40404040) >> 5) | \
+ (((u32)x & 0x20202020) >> 3) | \
+ (((u32)x & 0x10101010) >> 1) | \
+ (((u32)x & 0x08080808) << 1) | \
+ (((u32)x & 0x04040404) << 3) | \
+ (((u32)x & 0x02020202) << 5) | \
+ (((u32)x & 0x01010101) << 7))
+#endif
+
+struct rk1608_section {
+ union {
+ u32 offset;
+ u32 wait_value;
+ };
+ u32 size;
+ union {
+ u32 load_addr;
+ u32 wait_addr;
+ };
+ u16 wait_time;
+ u16 timeout;
+ u16 crc_16;
+ u8 flag;
+ u8 type;
+};
+
+struct rk1608_header {
+ char version[32];
+ u32 header_size;
+ u32 section_count;
+ struct rk1608_section sections[RK1608_MAX_SEC_NUM];
+};
+
+struct rk1608_boot_req {
+ u32 flag;
+ u32 load_addr;
+ u32 boot_len;
+ u8 status;
+ u8 dummy[2];
+ u8 cmd;
+};
+
+struct rk1608_msg_queue {
+ u32 buf_head; /* msg buffer head */
+ u32 buf_tail; /* msg buffer tail */
+ u32 cur_send; /* current msg send postition */
+ u32 cur_recv; /* current msg receive position */
+};
+
+struct msg {
+ u32 size; /* unit 4 bytes */
+ u16 type; /* msg identification */
+ s8 camera_id;
+ s8 sync;
+};
+
+enum {
+ /** AP -> RK1608
+ * 1 msg of sensor
+ */
+ id_msg_init_sensor_t = 0x0001,
+ id_msg_set_input_size_t,
+ id_msg_set_output_size_t,
+ id_msg_set_stream_in_on_t,
+ id_msg_set_stream_in_off_t,
+ id_msg_set_stream_out_on_t,
+ id_msg_set_stream_out_off_t,
+
+ /** AP -> RK1608
+ * 2 msg of take picture
+ */
+ id_msg_take_picture_t = 0x0021,
+ id_msg_take_picture_done_t,
+
+ /** AP -> RK1608
+ * 3 msg of realtime parameter
+ */
+ id_msg_rt_args_t = 0x0031,
+
+ /** AP -> RK1608
+ * 4 msg of power manager
+ */
+ id_msg_set_sys_mode_bypass_t = 0x0200,
+ id_msg_set_sys_mode_standby_t,
+ id_msg_set_sys_mode_idle_enable_t,
+ id_msg_set_sys_mode_idle_disable_t,
+ id_msg_set_sys_mode_slave_rk1608_on_t,
+ id_msg_set_sys_mode_slave_rk1608_off_t,
+
+ /** AP -> RK1608
+ * 5 msg of debug config
+ */
+ id_msg_set_log_level_t = 0x0250,
+
+ /** RK1608 -> AP
+ * 6 response of sensor msg
+ */
+ id_msg_init_sensor_ret_t = 0x0301,
+ id_msg_set_input_size_ret_t,
+ id_msg_set_output_size_ret_t,
+ id_msg_set_stream_in_on_ret_t,
+ id_msg_set_stream_in_off_ret_t,
+ id_msg_set_stream_out_on_ret_t,
+ id_msg_set_stream_out_off_ret_t,
+
+ /** RK1608 -> AP
+ * 7 response of take picture msg
+ */
+ id_msg_take_picture_ret_t = 0x0320,
+ id_msg_take_picture_done_ret_t,
+
+ /** RK1608 -> AP
+ * 8 response of realtime parameter msg
+ */
+ id_msg_rt_args_ret_t = 0x0330,
+
+ /*rk1608 -> ap*/
+ id_msg_do_i2c_t = 0x0390,
+ /*ap -> rk1608*/
+ id_msg_do_i2c_ret_t,
+
+ /** RK1608 -> AP
+ * 9 msg of print log
+ */
+ id_msg_rk1608_log_t = 0x0400,
+
+ /* dsi2csi dump */
+ id_msg_dsi2sci_rgb_dump_t = 0x6000,
+ id_msg_dsi2sci_nv12_dump_t = 0x6001,
+
+ /** RK1608 -> AP
+ * 10 msg of xfile
+ */
+ id_msg_xfile_import_t = 0x8000 + 0x0600,
+ id_msg_xfile_export_t,
+ id_msg_xfile_mkdir_t
+};
+
+struct msg_rk1608_log_t {
+ u32 size;
+ u16 type;
+ s8 core_id;
+ s8 log_level;
+};
+
+/**
+ * rk1608_write - RK1608 synchronous write
+ *
+ * @spi: spi device
+ * @addr: resource address
+ * @data: data buffer
+ * @data_len: data buffer size, in bytes
+ * Context: can sleep
+ *
+ * It returns zero on success, else a negative error code.
+ */
+int rk1608_write(struct spi_device *spi, s32 addr,
+ const s32 *data, size_t data_len);
+
+/**
+ * rk1608_safe_write - RK1608 synchronous write with state check
+ *
+ * @spi: spi device
+ * @addr: resource address
+ * @data: data buffer
+ * @data_len: data buffer size, in bytes
+ * Context: can sleep
+ *
+ * It returns zero on success, else operation state code.
+ */
+int rk1608_safe_write(struct spi_device *spi,
+ s32 addr, const s32 *data, size_t data_len);
+
+/**
+ * rk1608_read - RK1608 synchronous read
+ *
+ * @spi: spi device
+ * @addr: resource address
+ * @data: data buffer [out]
+ * @data_len: data buffer size, in bytes
+ * Context: can sleep
+ *
+ * It returns zero on success, else a negative error code.
+ */
+int rk1608_read(struct spi_device *spi, s32 addr,
+ s32 *data, size_t data_len);
+
+/**
+ * rk1608_safe_read - RK1608 synchronous read with state check
+ *
+ * @spi: spi device
+ * @addr: resource address
+ * @data: data buffer [out]
+ * @data_len: data buffer size, in bytes
+ * Context: can sleep
+ *
+ * It returns zero on success, else operation state code.
+ */
+int rk1608_safe_read(struct spi_device *spi,
+ s32 addr, s32 *data, size_t data_len);
+
+/**
+ * rk1608_operation_query - RK1608 last operation state query
+ *
+ * @spi: spi device
+ * @state: last operation state [out]
+ * Context: can sleep
+ *
+ * It returns zero on success, else a negative error code.
+ */
+int rk1608_operation_query(struct spi_device *spi, s32 *state);
+
+/**
+ * rk1608_interrupt_request - RK1608 request a rk1608 interrupt
+ *
+ * @spi: spi device
+ * @interrupt_num: interrupt identification
+ * Context: can sleep
+ *
+ * It returns zero on success, else a negative error code.
+ */
+int rk1608_interrupt_request(struct spi_device *spi,
+ s32 interrupt_num);
+
+static int rk1608_read_wait(struct spi_device *spi,
+ const struct rk1608_section *sec);
+
+static int rk1608_boot_request(struct spi_device *spi,
+ const struct rk1608_section *sec);
+
+static int rk1608_download_section(struct spi_device *spi, const u8 *data,
+ const struct rk1608_section *sec);
+/**
+ * rk1608_download_fw: - rk1608 firmware download through spi
+ *
+ * @spi: spi device
+ * @fw_name: name of firmware file, NULL for default firmware name
+ * Context: can sleep
+ *
+ * It returns zero on success, else a negative error code.
+ **/
+int rk1608_download_fw(struct spi_device *spi, const char *fw_name);
+
+/**
+ * rk1608_msq_read_head - read rk1608 msg queue head
+ *
+ * @spi: spi device
+ * @addr: msg queue head addr
+ * @m: msg queue pointer
+ *
+ * It returns zero on success, else a negative error code.
+ */
+int rk1608_msq_read_head(struct spi_device *spi,
+ u32 addr, struct rk1608_msg_queue *q);
+
+/**
+ * rk1608_msq_recv_msg - receive a msg from RK1608 -> AP msg queue
+ *
+ * @q: msg queue
+ * @m: a msg pointer buf [out]
+ *
+ * need call rk1608_msq_free_received_msg to free msg after msg use done
+ *
+ * It returns zero on success, else a negative error code.
+ */
+int rk1608_msq_recv_msg(struct spi_device *spi, struct msg **m);
+#endif
--
2.7.4
--
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 related
* [PATCH 0/2] Rockchip: Add rk1608 driver and DT-bindings
From: Leo Wen @ 2017-12-12 6:28 UTC (permalink / raw)
To: mchehab-DgEjT+Ai2ygdnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, davem-fT/PcQaiUtIeIZ0/mPfg9Q,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
rdunlap-wEGCiKHe2LqWVfeAwA7xHQ
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Leo Wen,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
eddie.cai-TNX95d0MmH7DzftRWevZcw,
linux-media-u79uwXL29TY76Z2rM5mHXA
For RK1608 driver ,you can use the v4l2-ctl command to capture frames.
Add DT bindings documentation for Rockchip RK1608.
Add the information of the maintainer.
Leo Wen (2):
[media] Add Rockchip RK1608 driver
dt-bindings: Document the Rockchip RK1608 bindings
Documentation/devicetree/bindings/media/rk1608.txt | 143 +++
MAINTAINERS | 7 +
drivers/media/spi/Makefile | 1 +
drivers/media/spi/rk1608.c | 1165 ++++++++++++++++++++
drivers/media/spi/rk1608.h | 366 ++++++
5 files changed, 1682 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/rk1608.txt
create mode 100644 drivers/media/spi/rk1608.c
create mode 100644 drivers/media/spi/rk1608.h
--
2.7.4
^ permalink raw reply
* [PATCH v2 4/4] pinctrl: mediatek: update MAINTAINERS entry with MediaTek pinctrl driver
From: sean.wang-NuS5LvNUpcJWk0Htik3J/w @ 2017-12-12 6:24 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: linux-gpio-u79uwXL29TY76Z2rM5mHXA, Sean Wang,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <cover.1513059081.git.sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
From: Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
I work for MediaTek on maintaining the existing MediaTek SoC whose target
to home gateway such as MT7622 and MT7623 that is reusing MT2701 related
files and will keep adding support for the following such kinds of SoCs
in the future.
Signed-off-by: Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Reviewed-by: Biao Huang <biao.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
MAINTAINERS | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index aa71ab52f..c0edf30 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10773,6 +10773,16 @@ M: Heikki Krogerus <heikki.krogerus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
S: Maintained
F: drivers/pinctrl/intel/
+PIN CONTROLLER - MEDIATEK
+M: Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
+L: linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org (moderated for non-subscribers)
+S: Maintained
+F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
+F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
+F: drivers/pinctrl/mediatek/pinctrl-mtk-common.*
+F: drivers/pinctrl/mediatek/pinctrl-mt2701.c
+F: drivers/pinctrl/mediatek/pinctrl-mt7622.c
+
PIN CONTROLLER - QUALCOMM
M: Bjorn Andersson <bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
S: Maintained
--
2.7.4
^ permalink raw reply related
* [PATCH v2 3/4] pinctrl: mediatek: add pinctrl driver for MT7622 SoC
From: sean.wang @ 2017-12-12 6:24 UTC (permalink / raw)
To: robh+dt, mark.rutland, linus.walleij, matthias.bgg, devicetree,
linux-mediatek
Cc: linux-arm-kernel, linux-gpio, linux-kernel, Sean Wang
In-Reply-To: <cover.1513059081.git.sean.wang@mediatek.com>
From: Sean Wang <sean.wang@mediatek.com>
Add support for pinctrl on MT7622 SoC. The IO core found on the SoC has
the registers for pinctrl, pinconf and gpio mixed up in the same register
range. However, the IO core for the MT7622 SoC is completely distinct from
anyone of previous MediaTek SoCs which already had support, such as
the hardware internal, register address map and register detailed
definition for each pin.
Therefore, instead, the driver is being newly implemented by reusing
generic methods provided from the core layer with GENERIC_PINCONF,
GENERIC_PINCTRL_GROUPS, and GENERIC_PINMUX_FUNCTIONS for the sake of code
simplicity and rid of superfluous code. Where the function of pins
determined by groups is utilized in this driver which can help developers
less confused with what combinations of pins effective on the SoC and even
reducing the mistakes during the integration of those relevant boards.
As the gpio_chip handling is also only a few lines, the driver also
implements the gpio functionality directly through GPIOLIB.
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Reviewed-by: Biao Huang <biao.huang@mediatek.com>
---
drivers/pinctrl/Makefile | 2 +-
drivers/pinctrl/mediatek/Kconfig | 10 +
drivers/pinctrl/mediatek/Makefile | 3 +-
drivers/pinctrl/mediatek/pinctrl-mt7622.c | 1595 +++++++++++++++++++++++++++++
4 files changed, 1608 insertions(+), 2 deletions(-)
create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7622.c
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index d0d4844..c39aa482 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -64,5 +64,5 @@ obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/
obj-y += ti/
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_ARCH_VT8500) += vt8500/
-obj-$(CONFIG_PINCTRL_MTK) += mediatek/
+obj-y += mediatek/
obj-$(CONFIG_PINCTRL_ZX) += zte/
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index 03b3023..3e59874 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -32,6 +32,16 @@ config PINCTRL_MT8127
select PINCTRL_MTK
# For ARMv8 SoCs
+config PINCTRL_MT7622
+ bool "MediaTek MT7622 pin control"
+ depends on OF
+ depends on ARM64 || COMPILE_TEST
+ select GENERIC_PINCONF
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select GPIOLIB
+ select OF_GPIO
+
config PINCTRL_MT8173
bool "Mediatek MT8173 pin control"
depends on OF
diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
index 10d9014..ed7d2b2 100644
--- a/drivers/pinctrl/mediatek/Makefile
+++ b/drivers/pinctrl/mediatek/Makefile
@@ -1,10 +1,11 @@
# SPDX-License-Identifier: GPL-2.0
# Core
-obj-y += pinctrl-mtk-common.o
+obj-$(CONFIG_PINCTRL_MTK) += pinctrl-mtk-common.o
# SoC Drivers
obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o
obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o
obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o
+obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o
obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o
obj-$(CONFIG_PINCTRL_MT6397) += pinctrl-mt6397.o
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7622.c b/drivers/pinctrl/mediatek/pinctrl-mt7622.c
new file mode 100644
index 0000000..3824d82
--- /dev/null
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7622.c
@@ -0,0 +1,1595 @@
+/*
+ * MediaTek MT7622 Pinctrl Driver
+ *
+ * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/regmap.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "../pinmux.h"
+
+#define PINCTRL_PINCTRL_DEV KBUILD_MODNAME
+#define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), }
+#define PINCTRL_PIN_GROUP(name, id) \
+ { \
+ name, \
+ id##_pins, \
+ ARRAY_SIZE(id##_pins), \
+ id##_funcs, \
+ }
+
+#define MTK_GPIO_MODE 1
+#define MTK_INPUT 0
+#define MTK_OUTPUT 1
+#define MTK_DISABLE 0
+#define MTK_ENABLE 1
+
+/* Custom pinconf parameters */
+#define MTK_PIN_CONFIG_TDSEL (PIN_CONFIG_END + 1)
+#define MTK_PIN_CONFIG_RDSEL (PIN_CONFIG_END + 2)
+
+/* List these attributes which could be modified for the pin */
+enum {
+ PINCTRL_PIN_REG_MODE,
+ PINCTRL_PIN_REG_DIR,
+ PINCTRL_PIN_REG_DI,
+ PINCTRL_PIN_REG_DO,
+ PINCTRL_PIN_REG_SR,
+ PINCTRL_PIN_REG_SMT,
+ PINCTRL_PIN_REG_PD,
+ PINCTRL_PIN_REG_PU,
+ PINCTRL_PIN_REG_E4,
+ PINCTRL_PIN_REG_E8,
+ PINCTRL_PIN_REG_TDSEL,
+ PINCTRL_PIN_REG_RDSEL,
+ PINCTRL_PIN_REG_MAX,
+};
+
+/* struct mtk_pin_field - the structure that holds the information of the field
+ * used to describe the attribute for the pin
+ * @offset: the register offset relative to the base address
+ * @mask: the mask used to filter out the field from the register
+ * @bitpos: the start bit relative to the register
+ * @next: the indication that the field would be extended to the
+ next register
+ */
+struct mtk_pin_field {
+ u32 offset;
+ u32 mask;
+ u8 bitpos;
+ u8 next;
+};
+
+/* struct mtk_pin_field_calc - the structure that holds the range providing
+ * the guide used to look up the relevant field
+ * @s_pin: the start pin within the range
+ * @e_pin: the end pin within the range
+ * @s_addr: the start address for the range
+ * @x_addrs: the address distance between two consecutive registers
+ * within the range
+ * @s_bit: the start bit for the first register within the range
+ * @x_bits: the bit distance between two consecutive pins within
+ * the range
+ */
+struct mtk_pin_field_calc {
+ u16 s_pin;
+ u16 e_pin;
+ u32 s_addr;
+ u8 x_addrs;
+ u8 s_bit;
+ u8 x_bits;
+};
+
+/* struct mtk_pin_reg_calc - the structure that holds all ranges used to
+ * determine which register the pin would make use of
+ * for certain pin attribute.
+ * @range: the start address for the range
+ * @nranges: the number of items in the range
+ */
+struct mtk_pin_reg_calc {
+ const struct mtk_pin_field_calc *range;
+ unsigned int nranges;
+};
+
+/* struct mtk_pin_soc - the structure that holds SoC-specific data */
+struct mtk_pin_soc {
+ const struct mtk_pin_reg_calc *reg_cal;
+ const struct pinctrl_pin_desc *pins;
+ unsigned int npins;
+ const struct group_desc *grps;
+ unsigned int ngrps;
+ const struct function_desc *funcs;
+ unsigned int nfuncs;
+};
+
+struct mtk_pinctrl {
+ struct pinctrl_dev *pctrl;
+ void __iomem *base;
+ struct device *dev;
+ struct gpio_chip chip;
+ const struct mtk_pin_soc *soc;
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_mode_range[] = {
+ {0, 0, 0x320, 0x10, 16, 4},
+ {1, 4, 0x3a0, 0x10, 16, 4},
+ {5, 5, 0x320, 0x10, 0, 4},
+ {6, 6, 0x300, 0x10, 4, 4},
+ {7, 7, 0x300, 0x10, 4, 4},
+ {8, 9, 0x350, 0x10, 20, 4},
+ {10, 10, 0x300, 0x10, 8, 4},
+ {11, 11, 0x300, 0x10, 8, 4},
+ {12, 12, 0x300, 0x10, 8, 4},
+ {13, 13, 0x300, 0x10, 8, 4},
+ {14, 15, 0x320, 0x10, 4, 4},
+ {16, 17, 0x320, 0x10, 20, 4},
+ {18, 21, 0x310, 0x10, 16, 4},
+ {22, 22, 0x380, 0x10, 16, 4},
+ {23, 23, 0x300, 0x10, 24, 4},
+ {24, 24, 0x300, 0x10, 24, 4},
+ {25, 25, 0x300, 0x10, 12, 4},
+ {25, 25, 0x300, 0x10, 12, 4},
+ {26, 26, 0x300, 0x10, 12, 4},
+ {27, 27, 0x300, 0x10, 12, 4},
+ {28, 28, 0x300, 0x10, 12, 4},
+ {29, 29, 0x300, 0x10, 12, 4},
+ {30, 30, 0x300, 0x10, 12, 4},
+ {31, 31, 0x300, 0x10, 12, 4},
+ {32, 32, 0x300, 0x10, 12, 4},
+ {33, 33, 0x300, 0x10, 12, 4},
+ {34, 34, 0x300, 0x10, 12, 4},
+ {35, 35, 0x300, 0x10, 12, 4},
+ {36, 36, 0x300, 0x10, 12, 4},
+ {37, 37, 0x300, 0x10, 20, 4},
+ {38, 38, 0x300, 0x10, 20, 4},
+ {39, 39, 0x300, 0x10, 20, 4},
+ {40, 40, 0x300, 0x10, 20, 4},
+ {41, 41, 0x300, 0x10, 20, 4},
+ {42, 42, 0x300, 0x10, 20, 4},
+ {43, 43, 0x300, 0x10, 20, 4},
+ {44, 44, 0x300, 0x10, 20, 4},
+ {45, 46, 0x300, 0x10, 20, 4},
+ {47, 47, 0x300, 0x10, 20, 4},
+ {48, 48, 0x300, 0x10, 20, 4},
+ {49, 49, 0x300, 0x10, 20, 4},
+ {50, 50, 0x300, 0x10, 20, 4},
+ {51, 70, 0x330, 0x10, 4, 4},
+ {71, 71, 0x300, 0x10, 16, 4},
+ {72, 72, 0x300, 0x10, 16, 4},
+ {73, 76, 0x310, 0x10, 0, 4},
+ {77, 77, 0x320, 0x10, 28, 4},
+ {78, 78, 0x320, 0x10, 12, 4},
+ {79, 82, 0x3a0, 0x10, 0, 4},
+ {83, 83, 0x350, 0x10, 28, 4},
+ {84, 84, 0x330, 0x10, 0, 4},
+ {85, 90, 0x360, 0x10, 4, 4},
+ {91, 94, 0x390, 0x10, 16, 4},
+ {95, 97, 0x380, 0x10, 20, 4},
+ {98, 101, 0x390, 0x10, 0, 4},
+ {102, 102, 0x360, 0x10, 0, 4},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_dir_range[] = {
+ {0, 102, 0x0, 0x10, 0, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_di_range[] = {
+ {0, 102, 0x200, 0x10, 0, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_do_range[] = {
+ {0, 102, 0x100, 0x10, 0, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_sr_range[] = {
+ {0, 31, 0x910, 0x10, 0, 1},
+ {32, 50, 0xa10, 0x10, 0, 1},
+ {51, 70, 0x810, 0x10, 0, 1},
+ {71, 72, 0xb10, 0x10, 0, 1},
+ {73, 86, 0xb10, 0x10, 4, 1},
+ {87, 90, 0xc10, 0x10, 0, 1},
+ {91, 102, 0xb10, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_smt_range[] = {
+ {0, 31, 0x920, 0x10, 0, 1},
+ {32, 50, 0xa20, 0x10, 0, 1},
+ {51, 70, 0x820, 0x10, 0, 1},
+ {71, 72, 0xb20, 0x10, 0, 1},
+ {73, 86, 0xb20, 0x10, 4, 1},
+ {87, 90, 0xc20, 0x10, 0, 1},
+ {91, 102, 0xb20, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_pu_range[] = {
+ {0, 31, 0x930, 0x10, 0, 1},
+ {32, 50, 0xa30, 0x10, 0, 1},
+ {51, 70, 0x830, 0x10, 0, 1},
+ {71, 72, 0xb30, 0x10, 0, 1},
+ {73, 86, 0xb30, 0x10, 4, 1},
+ {87, 90, 0xc30, 0x10, 0, 1},
+ {91, 102, 0xb30, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_pd_range[] = {
+ {0, 31, 0x940, 0x10, 0, 1},
+ {32, 50, 0xa40, 0x10, 0, 1},
+ {51, 70, 0x840, 0x10, 0, 1},
+ {71, 72, 0xb40, 0x10, 0, 1},
+ {73, 86, 0xb40, 0x10, 4, 1},
+ {87, 90, 0xc40, 0x10, 0, 1},
+ {91, 102, 0xb40, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_e4_range[] = {
+ {0, 31, 0x960, 0x10, 0, 1},
+ {32, 50, 0xa60, 0x10, 0, 1},
+ {51, 70, 0x860, 0x10, 0, 1},
+ {71, 72, 0xb60, 0x10, 0, 1},
+ {73, 86, 0xb60, 0x10, 4, 1},
+ {87, 90, 0xc60, 0x10, 0, 1},
+ {91, 102, 0xb60, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_e8_range[] = {
+ {0, 31, 0x970, 0x10, 0, 1},
+ {32, 50, 0xa70, 0x10, 0, 1},
+ {51, 70, 0x870, 0x10, 0, 1},
+ {71, 72, 0xb70, 0x10, 0, 1},
+ {73, 86, 0xb70, 0x10, 4, 1},
+ {87, 90, 0xc70, 0x10, 0, 1},
+ {91, 102, 0xb70, 0x10, 18, 1},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_tdsel_range[] = {
+ {0, 31, 0x980, 0x4, 0, 4},
+ {32, 50, 0xa80, 0x4, 0, 4},
+ {51, 70, 0x880, 0x4, 0, 4},
+ {71, 72, 0xb80, 0x4, 0, 4},
+ {73, 86, 0xb80, 0x4, 16, 4},
+ {87, 90, 0xc80, 0x4, 0, 4},
+ {91, 102, 0xb88, 0x4, 8, 4},
+};
+
+static const struct mtk_pin_field_calc mt7622_pin_rdsel_range[] = {
+ {0, 31, 0x990, 0x4, 0, 6},
+ {32, 50, 0xa90, 0x4, 0, 6},
+ {51, 58, 0x890, 0x4, 0, 6},
+ {59, 60, 0x894, 0x4, 28, 6},
+ {61, 62, 0x894, 0x4, 16, 6},
+ {63, 66, 0x898, 0x4, 8, 6},
+ {67, 68, 0x89c, 0x4, 12, 6},
+ {69, 70, 0x89c, 0x4, 0, 6},
+ {71, 72, 0xb90, 0x4, 0, 6},
+ {73, 86, 0xb90, 0x4, 24, 6},
+ {87, 90, 0xc90, 0x4, 0, 6},
+ {91, 102, 0xb9c, 0x4, 12, 6},
+};
+
+static const struct mtk_pin_reg_calc mt7622_reg_cals[PINCTRL_PIN_REG_MAX] = {
+ [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7622_pin_mode_range),
+ [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7622_pin_dir_range),
+ [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7622_pin_di_range),
+ [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7622_pin_do_range),
+ [PINCTRL_PIN_REG_SR] = MTK_RANGE(mt7622_pin_sr_range),
+ [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7622_pin_smt_range),
+ [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7622_pin_pu_range),
+ [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7622_pin_pd_range),
+ [PINCTRL_PIN_REG_E4] = MTK_RANGE(mt7622_pin_e4_range),
+ [PINCTRL_PIN_REG_E8] = MTK_RANGE(mt7622_pin_e8_range),
+ [PINCTRL_PIN_REG_TDSEL] = MTK_RANGE(mt7622_pin_tdsel_range),
+ [PINCTRL_PIN_REG_RDSEL] = MTK_RANGE(mt7622_pin_rdsel_range),
+};
+
+static const struct pinctrl_pin_desc mt7622_pins[] = {
+ PINCTRL_PIN(0, "GPIO_A"),
+ PINCTRL_PIN(1, "I2S1_IN"),
+ PINCTRL_PIN(2, "I2S1_OUT"),
+ PINCTRL_PIN(3, "I2S_BCLK"),
+ PINCTRL_PIN(4, "I2S_WS"),
+ PINCTRL_PIN(5, "I2S_MCLK"),
+ PINCTRL_PIN(6, "TXD0"),
+ PINCTRL_PIN(7, "RXD0"),
+ PINCTRL_PIN(8, "SPI_WP"),
+ PINCTRL_PIN(9, "SPI_HOLD"),
+ PINCTRL_PIN(10, "SPI_CLK"),
+ PINCTRL_PIN(11, "SPI_MOSI"),
+ PINCTRL_PIN(12, "SPI_MISO"),
+ PINCTRL_PIN(13, "SPI_CS"),
+ PINCTRL_PIN(14, "I2C_SDA"),
+ PINCTRL_PIN(15, "I2C_SCL"),
+ PINCTRL_PIN(16, "I2S2_IN"),
+ PINCTRL_PIN(17, "I2S3_IN"),
+ PINCTRL_PIN(18, "I2S4_IN"),
+ PINCTRL_PIN(19, "I2S2_OUT"),
+ PINCTRL_PIN(20, "I2S3_OUT"),
+ PINCTRL_PIN(21, "I2S4_OUT"),
+ PINCTRL_PIN(22, "GPIO_B"),
+ PINCTRL_PIN(23, "MDC"),
+ PINCTRL_PIN(24, "MDIO"),
+ PINCTRL_PIN(25, "G2_TXD0"),
+ PINCTRL_PIN(26, "G2_TXD1"),
+ PINCTRL_PIN(27, "G2_TXD2"),
+ PINCTRL_PIN(28, "G2_TXD3"),
+ PINCTRL_PIN(29, "G2_TXEN"),
+ PINCTRL_PIN(30, "G2_TXC"),
+ PINCTRL_PIN(31, "G2_RXD0"),
+ PINCTRL_PIN(32, "G2_RXD1"),
+ PINCTRL_PIN(33, "G2_RXD2"),
+ PINCTRL_PIN(34, "G2_RXD3"),
+ PINCTRL_PIN(35, "G2_RXDV"),
+ PINCTRL_PIN(36, "G2_RXC"),
+ PINCTRL_PIN(37, "NCEB"),
+ PINCTRL_PIN(38, "NWEB"),
+ PINCTRL_PIN(39, "NREB"),
+ PINCTRL_PIN(40, "NDL4"),
+ PINCTRL_PIN(41, "NDL5"),
+ PINCTRL_PIN(42, "NDL6"),
+ PINCTRL_PIN(43, "NDL7"),
+ PINCTRL_PIN(44, "NRB"),
+ PINCTRL_PIN(45, "NCLE"),
+ PINCTRL_PIN(46, "NALE"),
+ PINCTRL_PIN(47, "NDL0"),
+ PINCTRL_PIN(48, "NDL1"),
+ PINCTRL_PIN(49, "NDL2"),
+ PINCTRL_PIN(50, "NDL3"),
+ PINCTRL_PIN(51, "MDI_TP_P0"),
+ PINCTRL_PIN(52, "MDI_TN_P0"),
+ PINCTRL_PIN(53, "MDI_RP_P0"),
+ PINCTRL_PIN(54, "MDI_RN_P0"),
+ PINCTRL_PIN(55, "MDI_TP_P1"),
+ PINCTRL_PIN(56, "MDI_TN_P1"),
+ PINCTRL_PIN(57, "MDI_RP_P1"),
+ PINCTRL_PIN(58, "MDI_RN_P1"),
+ PINCTRL_PIN(59, "MDI_RP_P2"),
+ PINCTRL_PIN(60, "MDI_RN_P2"),
+ PINCTRL_PIN(61, "MDI_TP_P2"),
+ PINCTRL_PIN(62, "MDI_TN_P2"),
+ PINCTRL_PIN(63, "MDI_TP_P3"),
+ PINCTRL_PIN(64, "MDI_TN_P3"),
+ PINCTRL_PIN(65, "MDI_RP_P3"),
+ PINCTRL_PIN(66, "MDI_RN_P3"),
+ PINCTRL_PIN(67, "MDI_RP_P4"),
+ PINCTRL_PIN(68, "MDI_RN_P4"),
+ PINCTRL_PIN(69, "MDI_TP_P4"),
+ PINCTRL_PIN(70, "MDI_TN_P4"),
+ PINCTRL_PIN(71, "PMIC_SCL"),
+ PINCTRL_PIN(72, "PMIC_SDA"),
+ PINCTRL_PIN(73, "SPIC1_CLK"),
+ PINCTRL_PIN(74, "SPIC1_MOSI"),
+ PINCTRL_PIN(75, "SPIC1_MISO"),
+ PINCTRL_PIN(76, "SPIC1_CS"),
+ PINCTRL_PIN(77, "GPIO_D"),
+ PINCTRL_PIN(78, "WATCHDOG"),
+ PINCTRL_PIN(79, "RTS3_N"),
+ PINCTRL_PIN(80, "CTS3_N"),
+ PINCTRL_PIN(81, "TXD3"),
+ PINCTRL_PIN(82, "RXD3"),
+ PINCTRL_PIN(83, "PERST0_N"),
+ PINCTRL_PIN(84, "PERST1_N"),
+ PINCTRL_PIN(85, "WLED_N"),
+ PINCTRL_PIN(86, "EPHY_LED0_N"),
+ PINCTRL_PIN(87, "AUXIN0"),
+ PINCTRL_PIN(88, "AUXIN1"),
+ PINCTRL_PIN(89, "AUXIN2"),
+ PINCTRL_PIN(90, "AUXIN3"),
+ PINCTRL_PIN(91, "TXD4"),
+ PINCTRL_PIN(92, "RXD4"),
+ PINCTRL_PIN(93, "RTS4_N"),
+ PINCTRL_PIN(94, "CTS4_N"),
+ PINCTRL_PIN(95, "PWM1"),
+ PINCTRL_PIN(96, "PWM2"),
+ PINCTRL_PIN(97, "PWM3"),
+ PINCTRL_PIN(98, "PWM4"),
+ PINCTRL_PIN(99, "PWM5"),
+ PINCTRL_PIN(100, "PWM6"),
+ PINCTRL_PIN(101, "PWM7"),
+ PINCTRL_PIN(102, "GPIO_E"),
+};
+
+/* List all groups consisting of these pins dedicated to the enablement of
+ * certain hardware block and the corresponding mode for all of the pins. The
+ * hardware probably has multiple combinations of these pinouts.
+ */
+
+/* EMMC */
+static int mt7622_emmc_pins[] = { 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, };
+static int mt7622_emmc_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, };
+
+static int mt7622_emmc_rst_pins[] = { 37, };
+static int mt7622_emmc_rst_funcs[] = { 1, };
+
+/* LED for EPHY */
+static int mt7622_ephy_leds_pins[] = { 86, 91, 92, 93, 94, };
+static int mt7622_ephy_leds_funcs[] = { 0, 0, 0, 0, 0, };
+static int mt7622_ephy0_led_pins[] = { 86, };
+static int mt7622_ephy0_led_funcs[] = { 0, };
+static int mt7622_ephy1_led_pins[] = { 91, };
+static int mt7622_ephy1_led_funcs[] = { 2, };
+static int mt7622_ephy2_led_pins[] = { 92, };
+static int mt7622_ephy2_led_funcs[] = { 2, };
+static int mt7622_ephy3_led_pins[] = { 93, };
+static int mt7622_ephy3_led_funcs[] = { 2, };
+static int mt7622_ephy4_led_pins[] = { 94, };
+static int mt7622_ephy4_led_funcs[] = { 2, };
+
+/* Embedded Switch */
+static int mt7622_esw_pins[] = { 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, };
+static int mt7622_esw_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, };
+static int mt7622_esw_p0_p1_pins[] = { 51, 52, 53, 54, 55, 56, 57, 58, };
+static int mt7622_esw_p0_p1_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, };
+static int mt7622_esw_p2_p3_p4_pins[] = { 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, };
+static int mt7622_esw_p2_p3_p4_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, };
+/* RGMII via ESW */
+static int mt7622_rgmii_via_esw_pins[] = { 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, };
+static int mt7622_rgmii_via_esw_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, };
+
+/* RGMII via GMAC1 */
+static int mt7622_rgmii_via_gmac1_pins[] = { 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, };
+static int mt7622_rgmii_via_gmac1_funcs[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, };
+
+/* RGMII via GMAC2 */
+static int mt7622_rgmii_via_gmac2_pins[] = { 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, };
+static int mt7622_rgmii_via_gmac2_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, };
+
+/* I2C */
+static int mt7622_i2c0_pins[] = { 14, 15, };
+static int mt7622_i2c0_funcs[] = { 0, 0, };
+static int mt7622_i2c1_0_pins[] = { 55, 56, };
+static int mt7622_i2c1_0_funcs[] = { 0, 0, };
+static int mt7622_i2c1_1_pins[] = { 73, 74, };
+static int mt7622_i2c1_1_funcs[] = { 3, 3, };
+static int mt7622_i2c1_2_pins[] = { 87, 88, };
+static int mt7622_i2c1_2_funcs[] = { 0, 0, };
+static int mt7622_i2c2_0_pins[] = { 57, 58, };
+static int mt7622_i2c2_0_funcs[] = { 0, 0, };
+static int mt7622_i2c2_1_pins[] = { 75, 76, };
+static int mt7622_i2c2_1_funcs[] = { 3, 3, };
+static int mt7622_i2c2_2_pins[] = { 89, 90, };
+static int mt7622_i2c2_2_funcs[] = { 0, 0, };
+
+/* I2S */
+static int mt7622_i2s_in_mclk_bclk_ws_pins[] = { 3, 4, 5, };
+static int mt7622_i2s_in_mclk_bclk_ws_funcs[] = { 3, 3, 0, };
+static int mt7622_i2s1_in_data_pins[] = { 1, };
+static int mt7622_i2s1_in_data_funcs[] = { 0, };
+static int mt7622_i2s2_in_data_pins[] = { 16, };
+static int mt7622_i2s2_in_data_funcs[] = { 0, };
+static int mt7622_i2s3_in_data_pins[] = { 17, };
+static int mt7622_i2s3_in_data_funcs[] = { 0, };
+static int mt7622_i2s4_in_data_pins[] = { 18, };
+static int mt7622_i2s4_in_data_funcs[] = { 0, };
+static int mt7622_i2s_out_mclk_bclk_ws_pins[] = { 3, 4, 5, };
+static int mt7622_i2s_out_mclk_bclk_ws_funcs[] = { 0, 0, 0, };
+static int mt7622_i2s1_out_data_pins[] = { 2, };
+static int mt7622_i2s1_out_data_funcs[] = { 0, };
+static int mt7622_i2s2_out_data_pins[] = { 19, };
+static int mt7622_i2s2_out_data_funcs[] = { 0, };
+static int mt7622_i2s3_out_data_pins[] = { 20, };
+static int mt7622_i2s3_out_data_funcs[] = { 0, };
+static int mt7622_i2s4_out_data_pins[] = { 21, };
+static int mt7622_i2s4_out_data_funcs[] = { 0, };
+
+/* IR */
+static int mt7622_ir_0_tx_pins[] = { 16, };
+static int mt7622_ir_0_tx_funcs[] = { 4, };
+static int mt7622_ir_1_tx_pins[] = { 59, };
+static int mt7622_ir_1_tx_funcs[] = { 5, };
+static int mt7622_ir_2_tx_pins[] = { 99, };
+static int mt7622_ir_2_tx_funcs[] = { 3, };
+static int mt7622_ir_0_rx_pins[] = { 17, };
+static int mt7622_ir_0_rx_funcs[] = { 4, };
+static int mt7622_ir_1_rx_pins[] = { 60, };
+static int mt7622_ir_1_rx_funcs[] = { 5, };
+static int mt7622_ir_2_rx_pins[] = { 100, };
+static int mt7622_ir_2_rx_funcs[] = { 3, };
+
+/* MDIO */
+static int mt7622_mdc_mdio_pins[] = { 23, 24, };
+static int mt7622_mdc_mdio_funcs[] = { 0, 0, };
+
+/* PCIE */
+static int mt7622_pcie0_0_waken_pins[] = { 14, };
+static int mt7622_pcie0_0_waken_funcs[] = { 2, };
+static int mt7622_pcie0_0_clkreq_pins[] = { 15, };
+static int mt7622_pcie0_0_clkreq_funcs[] = { 2, };
+static int mt7622_pcie0_1_waken_pins[] = { 79, };
+static int mt7622_pcie0_1_waken_funcs[] = { 4, };
+static int mt7622_pcie0_1_clkreq_pins[] = { 80, };
+static int mt7622_pcie0_1_clkreq_funcs[] = { 4, };
+static int mt7622_pcie1_0_waken_pins[] = { 14, };
+static int mt7622_pcie1_0_waken_funcs[] = { 3, };
+static int mt7622_pcie1_0_clkreq_pins[] = { 15, };
+static int mt7622_pcie1_0_clkreq_funcs[] = { 3, };
+
+static int mt7622_pcie0_pad_perst_pins[] = { 83, };
+static int mt7622_pcie0_pad_perst_funcs[] = { 0, };
+static int mt7622_pcie1_pad_perst_pins[] = { 84, };
+static int mt7622_pcie1_pad_perst_funcs[] = { 0, };
+
+/* PMIC bus */
+static int mt7622_pmic_bus_pins[] = { 71, 72, };
+static int mt7622_pmic_bus_funcs[] = { 0, 0, };
+
+/* Parallel NAND */
+static int mt7622_pnand_pins[] = { 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, };
+static int mt7622_pnand_funcs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, };
+
+/* PWM */
+static int mt7622_pwm_ch1_0_pins[] = { 51, };
+static int mt7622_pwm_ch1_0_funcs[] = { 3, };
+static int mt7622_pwm_ch1_1_pins[] = { 73, };
+static int mt7622_pwm_ch1_1_funcs[] = { 4, };
+static int mt7622_pwm_ch1_2_pins[] = { 95, };
+static int mt7622_pwm_ch1_2_funcs[] = { 0, };
+static int mt7622_pwm_ch2_0_pins[] = { 52, };
+static int mt7622_pwm_ch2_0_funcs[] = { 3, };
+static int mt7622_pwm_ch2_1_pins[] = { 74, };
+static int mt7622_pwm_ch2_1_funcs[] = { 4, };
+static int mt7622_pwm_ch2_2_pins[] = { 96, };
+static int mt7622_pwm_ch2_2_funcs[] = { 0, };
+static int mt7622_pwm_ch3_0_pins[] = { 53, };
+static int mt7622_pwm_ch3_0_funcs[] = { 3, };
+static int mt7622_pwm_ch3_1_pins[] = { 75, };
+static int mt7622_pwm_ch3_1_funcs[] = { 4, };
+static int mt7622_pwm_ch3_2_pins[] = { 97, };
+static int mt7622_pwm_ch3_2_funcs[] = { 0, };
+static int mt7622_pwm_ch4_0_pins[] = { 54, };
+static int mt7622_pwm_ch4_0_funcs[] = { 3, };
+static int mt7622_pwm_ch4_1_pins[] = { 67, };
+static int mt7622_pwm_ch4_1_funcs[] = { 3, };
+static int mt7622_pwm_ch4_2_pins[] = { 76, };
+static int mt7622_pwm_ch4_2_funcs[] = { 4, };
+static int mt7622_pwm_ch4_3_pins[] = { 98, };
+static int mt7622_pwm_ch4_3_funcs[] = { 0, };
+static int mt7622_pwm_ch5_0_pins[] = { 68, };
+static int mt7622_pwm_ch5_0_funcs[] = { 3, };
+static int mt7622_pwm_ch5_1_pins[] = { 77, };
+static int mt7622_pwm_ch5_1_funcs[] = { 4, };
+static int mt7622_pwm_ch5_2_pins[] = { 99, };
+static int mt7622_pwm_ch5_2_funcs[] = { 0, };
+static int mt7622_pwm_ch6_0_pins[] = { 69, };
+static int mt7622_pwm_ch6_0_funcs[] = { 3, };
+static int mt7622_pwm_ch6_1_pins[] = { 78, };
+static int mt7622_pwm_ch6_1_funcs[] = { 4, };
+static int mt7622_pwm_ch6_2_pins[] = { 81, };
+static int mt7622_pwm_ch6_2_funcs[] = { 4, };
+static int mt7622_pwm_ch6_3_pins[] = { 100, };
+static int mt7622_pwm_ch6_3_funcs[] = { 0, };
+static int mt7622_pwm_ch7_0_pins[] = { 70, };
+static int mt7622_pwm_ch7_0_funcs[] = { 3, };
+static int mt7622_pwm_ch7_1_pins[] = { 82, };
+static int mt7622_pwm_ch7_1_funcs[] = { 4, };
+static int mt7622_pwm_ch7_2_pins[] = { 101, };
+static int mt7622_pwm_ch7_2_funcs[] = { 0, };
+
+/* SD */
+static int mt7622_sd_0_pins[] = { 16, 17, 18, 19, 20, 21, };
+static int mt7622_sd_0_funcs[] = { 2, 2, 2, 2, 2, 2, };
+static int mt7622_sd_1_pins[] = { 25, 26, 27, 28, 29, 30, };
+static int mt7622_sd_1_funcs[] = { 2, 2, 2, 2, 2, 2, };
+
+/* Serial NAND */
+static int mt7622_snfi_pins[] = { 8, 9, 10, 11, 12, 13, };
+static int mt7622_snfi_funcs[] = { 2, 2, 2, 2, 2, 2, };
+
+/* SPI NOR */
+static int mt7622_spi_pins[] = { 8, 9, 10, 11, 12, 13 };
+static int mt7622_spi_funcs[] = { 0, 0, 0, 0, 0, 0, };
+
+/* SPIC */
+static int mt7622_spic0_0_pins[] = { 63, 64, 65, 66, };
+static int mt7622_spic0_0_funcs[] = { 4, 4, 4, 4, };
+static int mt7622_spic0_1_pins[] = { 79, 80, 81, 82, };
+static int mt7622_spic0_1_funcs[] = { 3, 3, 3, 3, };
+static int mt7622_spic1_0_pins[] = { 67, 68, 69, 70, };
+static int mt7622_spic1_0_funcs[] = { 4, 4, 4, 4, };
+static int mt7622_spic1_1_pins[] = { 73, 74, 75, 76, };
+static int mt7622_spic1_1_funcs[] = { 0, 0, 0, 0, };
+static int mt7622_spic2_0_pins[] = { 10, 11, 12, 13, };
+static int mt7622_spic2_0_funcs[] = { 0, 0, 0, 0, };
+static int mt7622_spic2_0_wp_hold_pins[] = { 8, 9, };
+static int mt7622_spic2_0_wp_hold_funcs[] = { 0, 0, };
+
+/* TDM */
+static int mt7622_tdm_0_out_mclk_bclk_ws_pins[] = { 8, 9, 10, };
+static int mt7622_tdm_0_out_mclk_bclk_ws_funcs[] = { 3, 3, 3, };
+static int mt7622_tdm_0_in_mclk_bclk_ws_pins[] = { 11, 12, 13, };
+static int mt7622_tdm_0_in_mclk_bclk_ws_funcs[] = { 3, 3, 3, };
+static int mt7622_tdm_0_out_data_pins[] = { 20, };
+static int mt7622_tdm_0_out_data_funcs[] = { 3, };
+static int mt7622_tdm_0_in_data_pins[] = { 21, };
+static int mt7622_tdm_0_in_data_funcs[] = { 3, };
+static int mt7622_tdm_1_out_mclk_bclk_ws_pins[] = { 57, 58, 59, };
+static int mt7622_tdm_1_out_mclk_bclk_ws_funcs[] = { 3, 3, 3, };
+static int mt7622_tdm_1_in_mclk_bclk_ws_pins[] = { 60, 61, 62, };
+static int mt7622_tdm_1_in_mclk_bclk_ws_funcs[] = { 3, 3, 3, };
+static int mt7622_tdm_1_out_data_pins[] = { 55, };
+static int mt7622_tdm_1_out_data_funcs[] = { 3, };
+static int mt7622_tdm_1_in_data_pins[] = { 56, };
+static int mt7622_tdm_1_in_data_funcs[] = { 3, };
+
+/* UART */
+static int mt7622_uart0_0_tx_rx_pins[] = { 6, 7, };
+static int mt7622_uart0_0_tx_rx_funcs[] = { 0, 0, };
+static int mt7622_uart1_0_tx_rx_pins[] = { 55, 56, };
+static int mt7622_uart1_0_tx_rx_funcs[] = { 2, 2, };
+static int mt7622_uart1_0_rts_cts_pins[] = { 57, 58, };
+static int mt7622_uart1_0_rts_cts_funcs[] = { 2, 2, };
+static int mt7622_uart1_1_tx_rx_pins[] = { 73, 74, };
+static int mt7622_uart1_1_tx_rx_funcs[] = { 2, 2, };
+static int mt7622_uart1_1_rts_cts_pins[] = { 75, 76, };
+static int mt7622_uart1_1_rts_cts_funcs[] = { 2, 2, };
+static int mt7622_uart2_0_tx_rx_pins[] = { 3, 4, };
+static int mt7622_uart2_0_tx_rx_funcs[] = { 2, 2, };
+static int mt7622_uart2_0_rts_cts_pins[] = { 1, 2, };
+static int mt7622_uart2_0_rts_cts_funcs[] = { 2, 2, };
+static int mt7622_uart2_1_tx_rx_pins[] = { 51, 52, };
+static int mt7622_uart2_1_tx_rx_funcs[] = { 0, 0, };
+static int mt7622_uart2_1_rts_cts_pins[] = { 53, 54, };
+static int mt7622_uart2_1_rts_cts_funcs[] = { 0, 0, };
+static int mt7622_uart2_2_tx_rx_pins[] = { 59, 60, };
+static int mt7622_uart2_2_tx_rx_funcs[] = { 4, 4, };
+static int mt7622_uart2_2_rts_cts_pins[] = { 61, 62, };
+static int mt7622_uart2_2_rts_cts_funcs[] = { 4, 4, };
+static int mt7622_uart2_3_tx_rx_pins[] = { 95, 96, };
+static int mt7622_uart2_3_tx_rx_funcs[] = { 3, 3, };
+static int mt7622_uart3_0_tx_rx_pins[] = { 57, 58, };
+static int mt7622_uart3_0_tx_rx_funcs[] = { 5, 5, };
+static int mt7622_uart3_1_tx_rx_pins[] = { 81, 82, };
+static int mt7622_uart3_1_tx_rx_funcs[] = { 0, 0, };
+static int mt7622_uart3_1_rts_cts_pins[] = { 79, 80, };
+static int mt7622_uart3_1_rts_cts_funcs[] = { 0, 0, };
+static int mt7622_uart4_0_tx_rx_pins[] = { 61, 62, };
+static int mt7622_uart4_0_tx_rx_funcs[] = { 5, 5, };
+static int mt7622_uart4_1_tx_rx_pins[] = { 91, 92, };
+static int mt7622_uart4_1_tx_rx_funcs[] = { 0, 0, };
+static int mt7622_uart4_1_rts_cts_pins[] = { 93, 94 };
+static int mt7622_uart4_1_rts_cts_funcs[] = { 0, 0, };
+static int mt7622_uart4_2_tx_rx_pins[] = { 97, 98, };
+static int mt7622_uart4_2_tx_rx_funcs[] = { 2, 2, };
+static int mt7622_uart4_2_rts_cts_pins[] = { 95, 96 };
+static int mt7622_uart4_2_rts_cts_funcs[] = { 2, 2, };
+
+/* Watchdog */
+static int mt7622_watchdog_pins[] = { 78, };
+static int mt7622_watchdog_funcs[] = { 0, };
+
+/* WLAN LED */
+static int mt7622_wled_pins[] = { 85, };
+static int mt7622_wled_funcs[] = { 0, };
+
+static const struct group_desc mt7622_groups[] = {
+ PINCTRL_PIN_GROUP("emmc", mt7622_emmc),
+ PINCTRL_PIN_GROUP("emmc_rst", mt7622_emmc_rst),
+ PINCTRL_PIN_GROUP("ephy_leds", mt7622_ephy_leds),
+ PINCTRL_PIN_GROUP("ephy0_led", mt7622_ephy0_led),
+ PINCTRL_PIN_GROUP("ephy1_led", mt7622_ephy1_led),
+ PINCTRL_PIN_GROUP("ephy2_led", mt7622_ephy2_led),
+ PINCTRL_PIN_GROUP("ephy3_led", mt7622_ephy3_led),
+ PINCTRL_PIN_GROUP("ephy4_led", mt7622_ephy4_led),
+ PINCTRL_PIN_GROUP("esw", mt7622_esw),
+ PINCTRL_PIN_GROUP("esw_p0_p1", mt7622_esw_p0_p1),
+ PINCTRL_PIN_GROUP("esw_p2_p3_p4", mt7622_esw_p2_p3_p4),
+ PINCTRL_PIN_GROUP("rgmii_via_esw", mt7622_rgmii_via_esw),
+ PINCTRL_PIN_GROUP("rgmii_via_gmac1", mt7622_rgmii_via_gmac1),
+ PINCTRL_PIN_GROUP("rgmii_via_gmac2", mt7622_rgmii_via_gmac2),
+ PINCTRL_PIN_GROUP("i2c0", mt7622_i2c0),
+ PINCTRL_PIN_GROUP("i2c1_0", mt7622_i2c1_0),
+ PINCTRL_PIN_GROUP("i2c1_1", mt7622_i2c1_1),
+ PINCTRL_PIN_GROUP("i2c1_2", mt7622_i2c1_2),
+ PINCTRL_PIN_GROUP("i2c2_0", mt7622_i2c2_0),
+ PINCTRL_PIN_GROUP("i2c2_1", mt7622_i2c2_1),
+ PINCTRL_PIN_GROUP("i2c2_2", mt7622_i2c2_2),
+ PINCTRL_PIN_GROUP("i2s_out_mclk_bclk_ws", mt7622_i2s_out_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("i2s_in_mclk_bclk_ws", mt7622_i2s_in_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("i2s1_in_data", mt7622_i2s1_in_data),
+ PINCTRL_PIN_GROUP("i2s2_in_data", mt7622_i2s2_in_data),
+ PINCTRL_PIN_GROUP("i2s3_in_data", mt7622_i2s3_in_data),
+ PINCTRL_PIN_GROUP("i2s4_in_data", mt7622_i2s4_in_data),
+ PINCTRL_PIN_GROUP("i2s1_out_data", mt7622_i2s1_out_data),
+ PINCTRL_PIN_GROUP("i2s2_out_data", mt7622_i2s2_out_data),
+ PINCTRL_PIN_GROUP("i2s3_out_data", mt7622_i2s3_out_data),
+ PINCTRL_PIN_GROUP("i2s4_out_data", mt7622_i2s4_out_data),
+ PINCTRL_PIN_GROUP("ir_0_tx", mt7622_ir_0_tx),
+ PINCTRL_PIN_GROUP("ir_1_tx", mt7622_ir_1_tx),
+ PINCTRL_PIN_GROUP("ir_2_tx", mt7622_ir_2_tx),
+ PINCTRL_PIN_GROUP("ir_0_rx", mt7622_ir_0_rx),
+ PINCTRL_PIN_GROUP("ir_1_rx", mt7622_ir_1_rx),
+ PINCTRL_PIN_GROUP("ir_2_rx", mt7622_ir_2_rx),
+ PINCTRL_PIN_GROUP("mdc_mdio", mt7622_mdc_mdio),
+ PINCTRL_PIN_GROUP("pcie0_0_waken", mt7622_pcie0_0_waken),
+ PINCTRL_PIN_GROUP("pcie0_0_clkreq", mt7622_pcie0_0_clkreq),
+ PINCTRL_PIN_GROUP("pcie0_1_waken", mt7622_pcie0_1_waken),
+ PINCTRL_PIN_GROUP("pcie0_1_clkreq", mt7622_pcie0_1_clkreq),
+ PINCTRL_PIN_GROUP("pcie1_0_waken", mt7622_pcie1_0_waken),
+ PINCTRL_PIN_GROUP("pcie1_0_clkreq", mt7622_pcie1_0_clkreq),
+ PINCTRL_PIN_GROUP("pcie0_pad_perst", mt7622_pcie0_pad_perst),
+ PINCTRL_PIN_GROUP("pcie1_pad_perst", mt7622_pcie1_pad_perst),
+ PINCTRL_PIN_GROUP("par_nand", mt7622_pnand),
+ PINCTRL_PIN_GROUP("pmic_bus", mt7622_pmic_bus),
+ PINCTRL_PIN_GROUP("pwm_ch1_0", mt7622_pwm_ch1_0),
+ PINCTRL_PIN_GROUP("pwm_ch1_1", mt7622_pwm_ch1_1),
+ PINCTRL_PIN_GROUP("pwm_ch1_2", mt7622_pwm_ch1_2),
+ PINCTRL_PIN_GROUP("pwm_ch2_0", mt7622_pwm_ch2_0),
+ PINCTRL_PIN_GROUP("pwm_ch2_1", mt7622_pwm_ch2_1),
+ PINCTRL_PIN_GROUP("pwm_ch2_2", mt7622_pwm_ch2_2),
+ PINCTRL_PIN_GROUP("pwm_ch3_0", mt7622_pwm_ch3_0),
+ PINCTRL_PIN_GROUP("pwm_ch3_1", mt7622_pwm_ch3_1),
+ PINCTRL_PIN_GROUP("pwm_ch3_2", mt7622_pwm_ch3_2),
+ PINCTRL_PIN_GROUP("pwm_ch4_0", mt7622_pwm_ch4_0),
+ PINCTRL_PIN_GROUP("pwm_ch4_1", mt7622_pwm_ch4_1),
+ PINCTRL_PIN_GROUP("pwm_ch4_2", mt7622_pwm_ch4_2),
+ PINCTRL_PIN_GROUP("pwm_ch4_3", mt7622_pwm_ch4_3),
+ PINCTRL_PIN_GROUP("pwm_ch5_0", mt7622_pwm_ch5_0),
+ PINCTRL_PIN_GROUP("pwm_ch5_1", mt7622_pwm_ch5_1),
+ PINCTRL_PIN_GROUP("pwm_ch5_2", mt7622_pwm_ch5_2),
+ PINCTRL_PIN_GROUP("pwm_ch6_0", mt7622_pwm_ch6_0),
+ PINCTRL_PIN_GROUP("pwm_ch6_1", mt7622_pwm_ch6_1),
+ PINCTRL_PIN_GROUP("pwm_ch6_2", mt7622_pwm_ch6_2),
+ PINCTRL_PIN_GROUP("pwm_ch6_3", mt7622_pwm_ch6_3),
+ PINCTRL_PIN_GROUP("pwm_ch7_0", mt7622_pwm_ch7_0),
+ PINCTRL_PIN_GROUP("pwm_ch7_1", mt7622_pwm_ch7_1),
+ PINCTRL_PIN_GROUP("pwm_ch7_2", mt7622_pwm_ch7_2),
+ PINCTRL_PIN_GROUP("sd_0", mt7622_sd_0),
+ PINCTRL_PIN_GROUP("sd_1", mt7622_sd_1),
+ PINCTRL_PIN_GROUP("snfi", mt7622_snfi),
+ PINCTRL_PIN_GROUP("spi_nor", mt7622_spi),
+ PINCTRL_PIN_GROUP("spic0_0", mt7622_spic0_0),
+ PINCTRL_PIN_GROUP("spic0_1", mt7622_spic0_1),
+ PINCTRL_PIN_GROUP("spic1_0", mt7622_spic1_0),
+ PINCTRL_PIN_GROUP("spic1_1", mt7622_spic1_1),
+ PINCTRL_PIN_GROUP("spic2_0", mt7622_spic2_0),
+ PINCTRL_PIN_GROUP("spic2_0_wp_hold", mt7622_spic2_0_wp_hold),
+ PINCTRL_PIN_GROUP("tdm_0_out_mclk_bclk_ws",
+ mt7622_tdm_0_out_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("tdm_0_in_mclk_bclk_ws",
+ mt7622_tdm_0_in_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("tdm_0_out_data", mt7622_tdm_0_out_data),
+ PINCTRL_PIN_GROUP("tdm_0_in_data", mt7622_tdm_0_in_data),
+ PINCTRL_PIN_GROUP("tdm_1_out_mclk_bclk_ws",
+ mt7622_tdm_1_out_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("tdm_1_in_mclk_bclk_ws",
+ mt7622_tdm_1_in_mclk_bclk_ws),
+ PINCTRL_PIN_GROUP("tdm_1_out_data", mt7622_tdm_1_out_data),
+ PINCTRL_PIN_GROUP("tdm_1_in_data", mt7622_tdm_1_in_data),
+ PINCTRL_PIN_GROUP("uart0_0_tx_rx", mt7622_uart0_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart1_0_tx_rx", mt7622_uart1_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart1_0_rts_cts", mt7622_uart1_0_rts_cts),
+ PINCTRL_PIN_GROUP("uart1_1_tx_rx", mt7622_uart1_1_tx_rx),
+ PINCTRL_PIN_GROUP("uart1_1_rts_cts", mt7622_uart1_1_rts_cts),
+ PINCTRL_PIN_GROUP("uart2_0_tx_rx", mt7622_uart2_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart2_0_rts_cts", mt7622_uart2_0_rts_cts),
+ PINCTRL_PIN_GROUP("uart2_1_tx_rx", mt7622_uart2_1_tx_rx),
+ PINCTRL_PIN_GROUP("uart2_1_rts_cts", mt7622_uart2_1_rts_cts),
+ PINCTRL_PIN_GROUP("uart2_2_tx_rx", mt7622_uart2_2_tx_rx),
+ PINCTRL_PIN_GROUP("uart2_2_rts_cts", mt7622_uart2_2_rts_cts),
+ PINCTRL_PIN_GROUP("uart2_3_tx_rx", mt7622_uart2_3_tx_rx),
+ PINCTRL_PIN_GROUP("uart3_0_tx_rx", mt7622_uart3_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart3_1_tx_rx", mt7622_uart3_1_tx_rx),
+ PINCTRL_PIN_GROUP("uart3_1_rts_cts", mt7622_uart3_1_rts_cts),
+ PINCTRL_PIN_GROUP("uart4_0_tx_rx", mt7622_uart4_0_tx_rx),
+ PINCTRL_PIN_GROUP("uart4_1_tx_rx", mt7622_uart4_1_tx_rx),
+ PINCTRL_PIN_GROUP("uart4_1_rts_cts", mt7622_uart4_1_rts_cts),
+ PINCTRL_PIN_GROUP("uart4_2_tx_rx", mt7622_uart4_2_tx_rx),
+ PINCTRL_PIN_GROUP("uart4_2_rts_cts", mt7622_uart4_2_rts_cts),
+ PINCTRL_PIN_GROUP("watchdog", mt7622_watchdog),
+ PINCTRL_PIN_GROUP("wled", mt7622_wled),
+};
+
+/* Joint those groups owning the same capability in user point of view which
+ * allows that people tend to use through the device tree.
+ */
+static const char *mt7622_emmc_groups[] = { "emmc", "emmc_rst", };
+static const char *mt7622_ethernet_groups[] = { "esw", "esw_p0_p1",
+ "esw_p2_p3_p4", "mdc_mdio",
+ "rgmii_via_gmac1",
+ "rgmii_via_gmac2",
+ "rgmii_via_esw", };
+static const char *mt7622_i2c_groups[] = { "i2c0", "i2c1_0", "i2c1_1",
+ "i2c1_2", "i2c2_0", "i2c2_1",
+ "i2c2_2", };
+static const char *mt7622_i2s_groups[] = { "i2s_out_mclk_bclk_ws",
+ "i2s_in_mclk_bclk_ws",
+ "i2s1_in_data", "i2s2_in_data",
+ "i2s3_in_data", "i2s4_in_data",
+ "i2s1_out_data", "i2s2_out_data",
+ "i2s3_out_data", "i2s4_out_data", };
+static const char *mt7622_ir_groups[] = { "ir_0_tx", "ir_1_tx", "ir_2_tx",
+ "ir_0_rx", "ir_1_rx", "ir_2_rx"};
+static const char *mt7622_led_groups[] = { "ephy_leds", "ephy0_led",
+ "ephy1_led", "ephy2_led",
+ "ephy3_led", "ephy4_led",
+ "wled", };
+static const char *mt7622_flash_groups[] = { "par_nand", "snfi", "spi_nor"};
+static const char *mt7622_pcie_groups[] = { "pcie0_0_waken", "pcie0_0_clkreq",
+ "pcie0_1_waken", "pcie0_1_clkreq",
+ "pcie1_0_waken", "pcie1_0_clkreq",
+ "pcie0_pad_perst",
+ "pcie1_pad_perst", };
+static const char *mt7622_pmic_bus_groups[] = { "pmic_bus", };
+static const char *mt7622_pwm_groups[] = { "pwm_ch1_0", "pwm_ch1_1",
+ "pwm_ch1_2", "pwm_ch2_0",
+ "pwm_ch2_1", "pwm_ch2_2",
+ "pwm_ch3_0", "pwm_ch3_1",
+ "pwm_ch3_2", "pwm_ch4_0",
+ "pwm_ch4_1", "pwm_ch4_2",
+ "pwm_ch4_3", "pwm_ch5_0",
+ "pwm_ch5_1", "pwm_ch5_2",
+ "pwm_ch6_0", "pwm_ch6_1",
+ "pwm_ch6_2", "pwm_ch6_3",
+ "pwm_ch7_0", "pwm_ch7_1",
+ "pwm_ch7_2", };
+static const char *mt7622_sd_groups[] = { "sd_0", "sd_1", };
+static const char *mt7622_spic_groups[] = { "spic0_0", "spic0_1", "spic1_0",
+ "spic1_1", "spic2_0",
+ "spic2_0_wp_hold", };
+static const char *mt7622_tdm_groups[] = { "tdm_0_out_mclk_bclk_ws",
+ "tdm_0_in_mclk_bclk_ws",
+ "tdm_0_out_data",
+ "tdm_0_in_data",
+ "tdm_1_out_mclk_bclk_ws",
+ "tdm_1_in_mclk_bclk_ws",
+ "tdm_1_out_data",
+ "tdm_1_in_data", };
+
+static const char *mt7622_uart_groups[] = { "uart0_0_tx_rx",
+ "uart1_0_tx_rx", "uart1_0_rts_cts",
+ "uart1_1_tx_rx", "uart1_1_rts_cts",
+ "uart2_0_tx_rx", "uart2_0_rts_cts",
+ "uart2_1_tx_rx", "uart2_1_rts_cts",
+ "uart2_2_tx_rx", "uart2_2_rts_cts",
+ "uart2_3_tx_rx",
+ "uart3_0_tx_rx",
+ "uart3_1_tx_rx", "uart3_1_rts_cts",
+ "uart4_0_tx_rx",
+ "uart4_1_tx_rx", "uart4_1_rts_cts",
+ "uart4_2_tx_rx",
+ "uart4_2_rts_cts",};
+static const char *mt7622_wdt_groups[] = { "watchdog", };
+
+static const struct function_desc mt7622_functions[] = {
+ {"emmc", mt7622_emmc_groups, ARRAY_SIZE(mt7622_emmc_groups)},
+ {"eth", mt7622_ethernet_groups, ARRAY_SIZE(mt7622_ethernet_groups)},
+ {"i2c", mt7622_i2c_groups, ARRAY_SIZE(mt7622_i2c_groups)},
+ {"i2s", mt7622_i2s_groups, ARRAY_SIZE(mt7622_i2s_groups)},
+ {"ir", mt7622_ir_groups, ARRAY_SIZE(mt7622_ir_groups)},
+ {"led", mt7622_led_groups, ARRAY_SIZE(mt7622_led_groups)},
+ {"flash", mt7622_flash_groups, ARRAY_SIZE(mt7622_flash_groups)},
+ {"pcie", mt7622_pcie_groups, ARRAY_SIZE(mt7622_pcie_groups)},
+ {"pmic", mt7622_pmic_bus_groups, ARRAY_SIZE(mt7622_pmic_bus_groups)},
+ {"pwm", mt7622_pwm_groups, ARRAY_SIZE(mt7622_pwm_groups)},
+ {"sd", mt7622_sd_groups, ARRAY_SIZE(mt7622_sd_groups)},
+ {"spi", mt7622_spic_groups, ARRAY_SIZE(mt7622_spic_groups)},
+ {"tdm", mt7622_tdm_groups, ARRAY_SIZE(mt7622_tdm_groups)},
+ {"uart", mt7622_uart_groups, ARRAY_SIZE(mt7622_uart_groups)},
+ {"watchdog", mt7622_wdt_groups, ARRAY_SIZE(mt7622_wdt_groups)},
+};
+
+static const struct pinconf_generic_params mtk_custom_bindings[] = {
+ {"mediatek,tdsel", MTK_PIN_CONFIG_TDSEL, 0},
+ {"mediatek,rdsel", MTK_PIN_CONFIG_RDSEL, 0},
+};
+
+#ifdef CONFIG_DEBUG_FS
+static const struct pin_config_item mtk_conf_items[] = {
+ PCONFDUMP(MTK_PIN_CONFIG_TDSEL, "tdsel", NULL, true),
+ PCONFDUMP(MTK_PIN_CONFIG_RDSEL, "rdsel", NULL, true),
+};
+#endif
+
+static const struct mtk_pin_soc mt7622_data = {
+ .reg_cal = mt7622_reg_cals,
+ .pins = mt7622_pins,
+ .npins = ARRAY_SIZE(mt7622_pins),
+ .grps = mt7622_groups,
+ .ngrps = ARRAY_SIZE(mt7622_groups),
+ .funcs = mt7622_functions,
+ .nfuncs = ARRAY_SIZE(mt7622_functions),
+};
+
+static void mtk_w32(struct mtk_pinctrl *pctl, u32 reg, u32 val)
+{
+ writel_relaxed(val, pctl->base + reg);
+}
+
+static u32 mtk_r32(struct mtk_pinctrl *pctl, u32 reg)
+{
+ return readl_relaxed(pctl->base + reg);
+}
+
+static void mtk_rmw(struct mtk_pinctrl *pctl, u32 reg, u32 mask, u32 set)
+{
+ u32 val;
+
+ val = mtk_r32(pctl, reg);
+ val &= ~mask;
+ val |= set;
+ mtk_w32(pctl, reg, val);
+}
+
+static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw, int pin,
+ const struct mtk_pin_reg_calc *rc,
+ struct mtk_pin_field *pfd)
+{
+ const struct mtk_pin_field_calc *c, *e;
+ u32 bits;
+
+ c = rc->range;
+ e = c + rc->nranges;
+
+ while (c < e) {
+ if (pin >= c->s_pin && pin <= c->e_pin)
+ break;
+ c++;
+ }
+
+ if (c >= e) {
+ dev_err(hw->dev, "Out of range for pin = %d\n", pin);
+ return -EINVAL;
+ }
+
+ /* Caculated bits as the overall offset the pin is located at */
+ bits = c->s_bit + (pin - c->s_pin) * (c->x_bits);
+
+ /* Fill pfd from bits and 32-bit register applied is assumed */
+ pfd->offset = c->s_addr + c->x_addrs * (bits / 32);
+ pfd->bitpos = bits % 32;
+ pfd->mask = (1 << c->x_bits) - 1;
+
+ /* pfd->next is used for indicating that bit wrapping-around happens
+ * which requires the manipulation for bit 0 starting in the next
+ * register to form the complete field read/write.
+ */
+ pfd->next = pfd->bitpos + c->x_bits - 1 > 31 ? c->x_addrs : 0;
+
+ return 0;
+}
+
+static int mtk_hw_pin_field_get(struct mtk_pinctrl *hw, int pin,
+ int field, struct mtk_pin_field *pfd)
+{
+ const struct mtk_pin_reg_calc *rc;
+
+ if (field < 0 || field >= PINCTRL_PIN_REG_MAX) {
+ dev_err(hw->dev, "Invalid Field %d\n", field);
+ return -EINVAL;
+ }
+
+ if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) {
+ rc = &hw->soc->reg_cal[field];
+ } else {
+ dev_err(hw->dev, "Undefined range for field %d\n", field);
+ return -EINVAL;
+ }
+
+ return mtk_hw_pin_field_lookup(hw, pin, rc, pfd);
+}
+
+static void mtk_hw_bits_part(struct mtk_pin_field *pf, int *h, int *l)
+{
+ *l = 32 - pf->bitpos;
+ *h = get_count_order(pf->mask) - *l;
+}
+
+static void mtk_hw_write_cross_field(struct mtk_pinctrl *hw,
+ struct mtk_pin_field *pf, int value)
+{
+ int nbits_l, nbits_h;
+
+ mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
+
+ mtk_rmw(hw, pf->offset, pf->mask << pf->bitpos,
+ (value & pf->mask) << pf->bitpos);
+
+ mtk_rmw(hw, pf->offset + pf->next, BIT(nbits_h) - 1,
+ (value & pf->mask) >> nbits_l);
+}
+
+static void mtk_hw_read_cross_field(struct mtk_pinctrl *hw,
+ struct mtk_pin_field *pf, int *value)
+{
+ int nbits_l, nbits_h, h, l;
+
+ mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
+
+ l = (mtk_r32(hw, pf->offset) >> pf->bitpos) & (BIT(nbits_l) - 1);
+ h = (mtk_r32(hw, pf->offset + pf->next)) & (BIT(nbits_h) - 1);
+
+ *value = (h << nbits_l) | l;
+}
+
+static int mtk_hw_set_value(struct mtk_pinctrl *hw, int pin, int field,
+ int value)
+{
+ struct mtk_pin_field pf;
+ int err;
+
+ err = mtk_hw_pin_field_get(hw, pin, field, &pf);
+ if (err)
+ return err;
+
+ if (!pf.next)
+ mtk_rmw(hw, pf.offset, pf.mask << pf.bitpos,
+ (value & pf.mask) << pf.bitpos);
+ else
+ mtk_hw_write_cross_field(hw, &pf, value);
+
+ return 0;
+}
+
+static int mtk_hw_get_value(struct mtk_pinctrl *hw, int pin, int field,
+ int *value)
+{
+ struct mtk_pin_field pf;
+ int err;
+
+ err = mtk_hw_pin_field_get(hw, pin, field, &pf);
+ if (err)
+ return err;
+
+ if (!pf.next)
+ *value = (mtk_r32(hw, pf.offset) >> pf.bitpos) & pf.mask;
+ else
+ mtk_hw_read_cross_field(hw, &pf, value);
+
+ return 0;
+}
+
+static int mtk_pinmux_set_mux(struct pinctrl_dev *pctldev,
+ unsigned int selector, unsigned int group)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+ struct function_desc *func;
+ struct group_desc *grp;
+ int i;
+
+ func = pinmux_generic_get_function(pctldev, selector);
+ if (!func)
+ return -EINVAL;
+
+ grp = pinctrl_generic_get_group(pctldev, group);
+ if (!grp)
+ return -EINVAL;
+
+ dev_dbg(pctldev->dev, "enable function %s group %s\n",
+ func->name, grp->name);
+
+ for (i = 0; i < grp->num_pins; i++) {
+ int *pin_modes = grp->data;
+
+ mtk_hw_set_value(hw, grp->pins[i], PINCTRL_PIN_REG_MODE,
+ pin_modes[i]);
+ }
+
+ return 0;
+}
+
+static int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int pin)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+
+ return mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_MODE, MTK_GPIO_MODE);
+}
+
+static int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int pin, bool input)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+
+ /* hardware would take 0 as input direction */
+ return mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DIR, !input);
+}
+
+static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *config)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+ u32 param = pinconf_to_config_param(*config);
+ int val, val2, err, reg, ret = 1;
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_PU, &val);
+ if (err)
+ return err;
+
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_PD, &val2);
+ if (err)
+ return err;
+
+ if (val || val2)
+ return -EINVAL;
+
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_SLEW_RATE:
+ reg = (param == PIN_CONFIG_BIAS_PULL_UP) ?
+ PINCTRL_PIN_REG_PU :
+ (param == PIN_CONFIG_BIAS_PULL_DOWN) ?
+ PINCTRL_PIN_REG_PD : PINCTRL_PIN_REG_SR;
+
+ err = mtk_hw_get_value(hw, pin, reg, &val);
+ if (err)
+ return err;
+
+ if (!val)
+ return -EINVAL;
+
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_DIR, &val);
+ if (err)
+ return -EINVAL;
+
+ /* HW takes input mode as zero; output mode as non-zero */
+ if ((val && param == PIN_CONFIG_INPUT_ENABLE) ||
+ (!val && param == PIN_CONFIG_OUTPUT_ENABLE))
+ return -EINVAL;
+
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_DIR, &val);
+ if (err)
+ return err;
+
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_SMT, &val2);
+ if (err)
+ return err;
+
+ if (val || !val2)
+ return -EINVAL;
+
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_E4, &val);
+ if (err)
+ return -EINVAL;
+
+ err = mtk_hw_get_value(hw, pin, PINCTRL_PIN_REG_E8, &val2);
+ if (err)
+ return -EINVAL;
+
+ /* 4mA when (e8, e4) = (0, 0); 8mA when (e8, e4) = (0, 1)
+ * 12mA when (e8, e4) = (1, 0); 16mA when (e8, e4) = (1, 1)
+ */
+ ret = ((val2 << 1) + val + 1) * 4;
+
+ break;
+ case MTK_PIN_CONFIG_TDSEL:
+ case MTK_PIN_CONFIG_RDSEL:
+ reg = (param == MTK_PIN_CONFIG_TDSEL) ?
+ PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
+
+ err = mtk_hw_get_value(hw, pin, reg, &val);
+ if (err)
+ return -EINVAL;
+
+ ret = val;
+
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, ret);
+
+ return 0;
+}
+
+static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *configs, unsigned int num_configs)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+ u32 reg, param, arg;
+ int cfg, err = 0;
+
+ for (cfg = 0; cfg < num_configs; cfg++) {
+ param = pinconf_to_config_param(configs[cfg]);
+ arg = pinconf_to_config_argument(configs[cfg]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ arg = (param == PIN_CONFIG_BIAS_DISABLE) ? 0 :
+ (param == PIN_CONFIG_BIAS_PULL_UP) ? 1 : 2;
+
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_PU,
+ arg & 1);
+ if (err)
+ goto err;
+
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_PD,
+ !!(arg & 2));
+ if (err)
+ goto err;
+ break;
+ case PIN_CONFIG_OUTPUT_ENABLE:
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_SMT,
+ MTK_DISABLE);
+ if (err)
+ goto err;
+ case PIN_CONFIG_INPUT_ENABLE:
+ case PIN_CONFIG_SLEW_RATE:
+ reg = (param == PIN_CONFIG_SLEW_RATE) ?
+ PINCTRL_PIN_REG_SR : PINCTRL_PIN_REG_DIR;
+
+ arg = (param == PIN_CONFIG_INPUT_ENABLE) ? 0 :
+ (param == PIN_CONFIG_OUTPUT_ENABLE) ? 1 : arg;
+ err = mtk_hw_set_value(hw, pin, reg, arg);
+ if (err)
+ goto err;
+
+ break;
+ case PIN_CONFIG_OUTPUT:
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DIR,
+ MTK_OUTPUT);
+ if (err)
+ goto err;
+
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DO,
+ arg);
+ if (err)
+ goto err;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ /* arg = 1: Input mode & SMT enable ;
+ * arg = 0: Output mode & SMT disable
+ */
+ arg = arg ? 2 : 1;
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_DIR,
+ arg & 1);
+ if (err)
+ goto err;
+
+ err = mtk_hw_set_value(hw, pin, PINCTRL_PIN_REG_SMT,
+ !!(arg & 2));
+ if (err)
+ goto err;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ /* 4mA when (e8, e4) = (0, 0);
+ * 8mA when (e8, e4) = (0, 1);
+ * 12mA when (e8, e4) = (1, 0);
+ * 16mA when (e8, e4) = (1, 1)
+ */
+ if (!(arg % 4) && (arg >= 4 && arg <= 16)) {
+ arg = arg / 4 - 1;
+ err = mtk_hw_set_value(hw, pin,
+ PINCTRL_PIN_REG_E4,
+ arg & 0x1);
+ if (err)
+ goto err;
+
+ err = mtk_hw_set_value(hw, pin,
+ PINCTRL_PIN_REG_E8,
+ (arg & 0x2) >> 1);
+ if (err)
+ goto err;
+ } else {
+ err = -ENOTSUPP;
+ }
+ break;
+ case MTK_PIN_CONFIG_TDSEL:
+ case MTK_PIN_CONFIG_RDSEL:
+ reg = (param == MTK_PIN_CONFIG_TDSEL) ?
+ PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
+
+ err = mtk_hw_set_value(hw, pin, reg, arg);
+ if (err)
+ goto err;
+ break;
+ default:
+ err = -ENOTSUPP;
+ }
+ }
+err:
+ return err;
+}
+
+static int mtk_pinconf_group_get(struct pinctrl_dev *pctldev,
+ unsigned int group, unsigned long *config)
+{
+ const unsigned int *pins;
+ unsigned int i, npins, old = 0;
+ int ret;
+
+ ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < npins; i++) {
+ if (mtk_pinconf_get(pctldev, pins[i], config))
+ return -ENOTSUPP;
+
+ /* configs do not match between two pins */
+ if (i && old != *config)
+ return -ENOTSUPP;
+
+ old = *config;
+ }
+
+ return 0;
+}
+
+static int mtk_pinconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned int group, unsigned long *configs,
+ unsigned int num_configs)
+{
+ const unsigned int *pins;
+ unsigned int i, npins;
+ int ret;
+
+ ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < npins; i++) {
+ ret = mtk_pinconf_set(pctldev, pins[i], configs, num_configs);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct pinctrl_ops mtk_pctlops = {
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+ .dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static const struct pinmux_ops mtk_pmxops = {
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
+ .set_mux = mtk_pinmux_set_mux,
+ .gpio_request_enable = mtk_pinmux_gpio_request_enable,
+ .gpio_set_direction = mtk_pinmux_gpio_set_direction,
+ .strict = true,
+};
+
+static const struct pinconf_ops mtk_confops = {
+ .is_generic = true,
+ .pin_config_get = mtk_pinconf_get,
+ .pin_config_set = mtk_pinconf_set,
+ .pin_config_group_get = mtk_pinconf_group_get,
+ .pin_config_group_set = mtk_pinconf_group_set,
+ .pin_config_config_dbg_show = pinconf_generic_dump_config,
+};
+
+static struct pinctrl_desc mtk_desc = {
+ .name = PINCTRL_PINCTRL_DEV,
+ .pctlops = &mtk_pctlops,
+ .pmxops = &mtk_pmxops,
+ .confops = &mtk_confops,
+ .owner = THIS_MODULE,
+};
+
+static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio)
+{
+ struct mtk_pinctrl *hw = dev_get_drvdata(chip->parent);
+ int value;
+
+ mtk_hw_get_value(hw, gpio, PINCTRL_PIN_REG_DI, &value);
+
+ return !!value;
+}
+
+static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)
+{
+ struct mtk_pinctrl *hw = dev_get_drvdata(chip->parent);
+
+ mtk_hw_set_value(hw, gpio, PINCTRL_PIN_REG_DO, !!value);
+}
+
+static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
+{
+ return pinctrl_gpio_direction_input(chip->base + gpio);
+}
+
+static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
+ int value)
+{
+ mtk_gpio_set(chip, gpio, value);
+
+ return pinctrl_gpio_direction_output(chip->base + gpio);
+}
+
+static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
+{
+ struct gpio_chip *chip = &hw->chip;
+ int ret;
+
+ chip->label = PINCTRL_PINCTRL_DEV;
+ chip->parent = hw->dev;
+ chip->request = gpiochip_generic_request;
+ chip->free = gpiochip_generic_free;
+ chip->direction_input = mtk_gpio_direction_input;
+ chip->direction_output = mtk_gpio_direction_output;
+ chip->get = mtk_gpio_get;
+ chip->set = mtk_gpio_set;
+ chip->base = -1;
+ chip->ngpio = hw->soc->npins;
+ chip->of_node = np;
+ chip->of_gpio_n_cells = 2;
+
+ ret = gpiochip_add_data(chip, hw);
+ if (ret < 0)
+ return ret;
+
+ ret = gpiochip_add_pin_range(chip, dev_name(hw->dev), 0, 0,
+ chip->ngpio);
+ if (ret < 0) {
+ gpiochip_remove(chip);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mtk_build_groups(struct mtk_pinctrl *hw)
+{
+ int err, i;
+
+ for (i = 0; i < hw->soc->ngrps; i++) {
+ const struct group_desc *group = hw->soc->grps + i;
+
+ err = pinctrl_generic_add_group(hw->pctrl, group->name,
+ group->pins, group->num_pins,
+ group->data);
+ if (err) {
+ dev_err(hw->dev, "Failed to register group %s\n",
+ group->name);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int mtk_build_functions(struct mtk_pinctrl *hw)
+{
+ int i, err;
+
+ for (i = 0; i < hw->soc->nfuncs ; i++) {
+ const struct function_desc *func = hw->soc->funcs + i;
+
+ err = pinmux_generic_add_function(hw->pctrl, func->name,
+ func->group_names,
+ func->num_group_names,
+ func->data);
+ if (err) {
+ dev_err(hw->dev, "Failed to register function %s\n",
+ func->name);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static const struct of_device_id mtk_pinctrl_of_match[] = {
+ { .compatible = "mediatek,mt7622-pinctrl", .data = &mt7622_data},
+ { }
+};
+
+static int mtk_pinctrl_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct mtk_pinctrl *hw;
+ const struct of_device_id *of_id =
+ of_match_device(mtk_pinctrl_of_match, &pdev->dev);
+ int err;
+
+ hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
+ if (!hw)
+ return -ENOMEM;
+
+ hw->soc = of_id->data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "missing IO resource\n");
+ return -ENXIO;
+ }
+
+ hw->dev = &pdev->dev;
+ hw->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hw->base))
+ return PTR_ERR(hw->base);
+
+ /* Setup pins descriptions per SoC types */
+ mtk_desc.pins = hw->soc->pins;
+ mtk_desc.npins = hw->soc->npins;
+ mtk_desc.num_custom_params = ARRAY_SIZE(mtk_custom_bindings);
+ mtk_desc.custom_params = mtk_custom_bindings;
+#ifdef CONFIG_DEBUG_FS
+ mtk_desc.custom_conf_items = mtk_conf_items;
+#endif
+
+ hw->pctrl = devm_pinctrl_register(&pdev->dev, &mtk_desc, hw);
+ if (IS_ERR(hw->pctrl))
+ return PTR_ERR(hw->pctrl);
+
+ /* Setup groups descriptions per SoC types */
+ err = mtk_build_groups(hw);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to build groups\n");
+ return 0;
+ }
+
+ /* Setup functions descriptions per SoC types */
+ err = mtk_build_functions(hw);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to build functions\n");
+ return err;
+ }
+
+ err = mtk_build_gpiochip(hw, pdev->dev.of_node);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to add gpio_chip\n");
+ return err;
+ }
+
+ platform_set_drvdata(pdev, hw);
+
+ return 0;
+}
+
+static struct platform_driver mtk_pinctrl_driver = {
+ .driver = {
+ .name = "mtk-pinctrl",
+ .of_match_table = mtk_pinctrl_of_match,
+ },
+ .probe = mtk_pinctrl_probe,
+};
+
+static int __init mtk_pinctrl_init(void)
+{
+ return platform_driver_register(&mtk_pinctrl_driver);
+}
+arch_initcall(mtk_pinctrl_init);
--
2.7.4
^ permalink raw reply related
* [PATCH v2 2/4] pinctrl: mediatek: cleanup for placing all drivers under the menu
From: sean.wang-NuS5LvNUpcJWk0Htik3J/w @ 2017-12-12 6:24 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Sean Wang
In-Reply-To: <cover.1513059081.git.sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
From: Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Since lots of MediaTek drivers had been added, it seems slightly better
for that adding cleanup for placing MediaTek pinctrl drivers under the
independent menu as other kinds of drivers usually was done.
Signed-off-by: Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Reviewed-by: Biao Huang <biao.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
drivers/pinctrl/mediatek/Kconfig | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
index fac9866..03b3023 100644
--- a/drivers/pinctrl/mediatek/Kconfig
+++ b/drivers/pinctrl/mediatek/Kconfig
@@ -1,4 +1,5 @@
-if ARCH_MEDIATEK || COMPILE_TEST
+menu "MediaTek pinctrl drivers"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
config PINCTRL_MTK
bool
@@ -46,4 +47,4 @@ config PINCTRL_MT6397
default MFD_MT6397
select PINCTRL_MTK
-endif
+endmenu
--
2.7.4
--
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 related
* [PATCH v2 1/4] dt-bindings: pinctrl: add bindings for MediaTek MT7622 SoC
From: sean.wang-NuS5LvNUpcJWk0Htik3J/w @ 2017-12-12 6:24 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Sean Wang
In-Reply-To: <cover.1513059081.git.sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
From: Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Add devicetree bindings for MediaTek MT7622 pinctrl driver.
Signed-off-by: Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Reviewed-by: Biao Huang <biao.huang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
.../devicetree/bindings/pinctrl/pinctrl-mt7622.txt | 351 +++++++++++++++++++++
1 file changed, 351 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
new file mode 100644
index 0000000..f18ed99
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
@@ -0,0 +1,351 @@
+== MediaTek MT7622 pinctrl controller ==
+
+Required properties for the root node:
+ - compatible: Should be one of the following
+ "mediatek,mt7622-pinctrl" for MT7622 SoC
+ - reg: offset and length of the pinctrl space
+
+ - gpio-controller: Marks the device node as a GPIO controller.
+ - #gpio-cells: Should be two. The first cell is the pin number and the
+ second is the GPIO flags.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+MT7622 pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, slew rate, etc.
+
+We support 2 types of configuration nodes. Those nodes can be either pinmux
+nodes or pinconf nodes. Each configuration node can consist of multiple nodes
+describing the pinmux and pinconf options.
+
+The name of each subnode doesn't matter as long as it is unique; all subnodes
+should be enumerated and processed purely based on their content.
+
+== pinmux nodes content ==
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pinmux subnode:
+
+Required properties are:
+ - groups: An array of strings. Each string contains the name of a group.
+ Valid values for these names are listed below.
+ - function: A string containing the name of the function to mux to the
+ group. Valid values for function names are listed below.
+
+== pinconf nodes content ==
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pinconf subnode:
+
+Required properties are:
+ - pins: An array of strings. Each string contains the name of a pin.
+ Valid values for these names are listed below.
+ - groups: An array of strings. Each string contains the name of a group.
+ Valid values for these names are listed below.
+
+Optional properies are:
+ bias-disable, bias-pull, bias-pull-down, input-enable,
+ input-schmitt-enable, input-schmitt-disable, output-enable
+ output-low, output-high, drive-strength, slew-rate
+
+ Valid arguments for 'slew-rate' are '0' for no slew rate controlled and '1' for
+ slower slew rate respectively.
+ Valid arguments for 'drive-strength', 4, 8, 12, or 16 in mA.
+
+The following specific properties as defined are valid to specify in a pinconf
+subnode:
+
+Optional properties are:
+ - mediatek,tdsel: An integer describing the steps for output level shifter duty
+ cycle when asserted (high pulse width adjustment). Valid arguments are from 0
+ to 15.
+ - mediatek,rdsel: An integer describing the steps for input level shifter duty
+ cycle when asserted (high pulse width adjustment). Valid arguments are from 0
+ to 63.
+
+== Valid values for pins, function and groups on MT7622 ==
+
+Valid values for pins are:
+pins can be referenced via the pin names as the below table shown and the
+related physical number is also put ahead of those names which helps cross
+references to pins between groups to know whether pins assignment conflict
+happens among devices try to acquire those available pins.
+
+ Pin #: Valid values for pins
+ -----------------------------
+ PIN 0: "GPIO_A"
+ PIN 1: "I2S1_IN"
+ PIN 2: "I2S1_OUT"
+ PIN 3: "I2S_BCLK"
+ PIN 4: "I2S_WS"
+ PIN 5: "I2S_MCLK"
+ PIN 6: "TXD0"
+ PIN 7: "RXD0"
+ PIN 8: "SPI_WP"
+ PIN 9: "SPI_HOLD"
+ PIN 10: "SPI_CLK"
+ PIN 11: "SPI_MOSI"
+ PIN 12: "SPI_MISO"
+ PIN 13: "SPI_CS"
+ PIN 14: "I2C_SDA"
+ PIN 15: "I2C_SCL"
+ PIN 16: "I2S2_IN"
+ PIN 17: "I2S3_IN"
+ PIN 18: "I2S4_IN"
+ PIN 19: "I2S2_OUT"
+ PIN 20: "I2S3_OUT"
+ PIN 21: "I2S4_OUT"
+ PIN 22: "GPIO_B"
+ PIN 23: "MDC"
+ PIN 24: "MDIO"
+ PIN 25: "G2_TXD0"
+ PIN 26: "G2_TXD1"
+ PIN 27: "G2_TXD2"
+ PIN 28: "G2_TXD3"
+ PIN 29: "G2_TXEN"
+ PIN 30: "G2_TXC"
+ PIN 31: "G2_RXD0"
+ PIN 32: "G2_RXD1"
+ PIN 33: "G2_RXD2"
+ PIN 34: "G2_RXD3"
+ PIN 35: "G2_RXDV"
+ PIN 36: "G2_RXC"
+ PIN 37: "NCEB"
+ PIN 38: "NWEB"
+ PIN 39: "NREB"
+ PIN 40: "NDL4"
+ PIN 41: "NDL5"
+ PIN 42: "NDL6"
+ PIN 43: "NDL7"
+ PIN 44: "NRB"
+ PIN 45: "NCLE"
+ PIN 46: "NALE"
+ PIN 47: "NDL0"
+ PIN 48: "NDL1"
+ PIN 49: "NDL2"
+ PIN 50: "NDL3"
+ PIN 51: "MDI_TP_P0"
+ PIN 52: "MDI_TN_P0"
+ PIN 53: "MDI_RP_P0"
+ PIN 54: "MDI_RN_P0"
+ PIN 55: "MDI_TP_P1"
+ PIN 56: "MDI_TN_P1"
+ PIN 57: "MDI_RP_P1"
+ PIN 58: "MDI_RN_P1"
+ PIN 59: "MDI_RP_P2"
+ PIN 60: "MDI_RN_P2"
+ PIN 61: "MDI_TP_P2"
+ PIN 62: "MDI_TN_P2"
+ PIN 63: "MDI_TP_P3"
+ PIN 64: "MDI_TN_P3"
+ PIN 65: "MDI_RP_P3"
+ PIN 66: "MDI_RN_P3"
+ PIN 67: "MDI_RP_P4"
+ PIN 68: "MDI_RN_P4"
+ PIN 69: "MDI_TP_P4"
+ PIN 70: "MDI_TN_P4"
+ PIN 71: "PMIC_SCL"
+ PIN 72: "PMIC_SDA"
+ PIN 73: "SPIC1_CLK"
+ PIN 74: "SPIC1_MOSI"
+ PIN 75: "SPIC1_MISO"
+ PIN 76: "SPIC1_CS"
+ PIN 77: "GPIO_D"
+ PIN 78: "WATCHDOG"
+ PIN 79: "RTS3_N"
+ PIN 80: "CTS3_N"
+ PIN 81: "TXD3"
+ PIN 82: "RXD3"
+ PIN 83: "PERST0_N"
+ PIN 84: "PERST1_N"
+ PIN 85: "WLED_N"
+ PIN 86: "EPHY_LED0_N"
+ PIN 87: "AUXIN0"
+ PIN 88: "AUXIN1"
+ PIN 89: "AUXIN2"
+ PIN 90: "AUXIN3"
+ PIN 91: "TXD4"
+ PIN 92: "RXD4"
+ PIN 93: "RTS4_N"
+ PIN 94: "CST4_N"
+ PIN 95: "PWM1"
+ PIN 96: "PWM2"
+ PIN 97: "PWM3"
+ PIN 98: "PWM4"
+ PIN 99: "PWM5"
+ PIN 100: "PWM6"
+ PIN 101: "PWM7"
+ PIN 102: "GPIO_E"
+
+Valid values for function are:
+ "emmc", "eth", "i2c", "i2s", "ir", "led", "flash", "pcie",
+ "pmic", "pwm", "sd", "spi", "tdm", "uart", "watchdog"
+
+Valid values for groups are:
+additional data is put followingly with valid value allowing us to know which
+applicable function and which relevant pins (in pin#) are able applied for that
+group.
+
+ Valid value function pins (in pin#)
+ -------------------------------------------------------------------------
+ "emmc" "emmc" 40, 41, 42, 43, 44, 45,
+ 47, 48, 49, 50
+ "emmc_rst" "emmc" 37
+ "esw" "eth" 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 67, 68,
+ 69, 70
+ "esw_p0_p1" "eth" 51, 52, 53, 54, 55, 56,
+ 57, 58
+ "esw_p2_p3_p4" "eth" 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70
+ "rgmii_via_esw" "eth" 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70
+ "rgmii_via_gmac1" "eth" 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70
+ "rgmii_via_gmac2" "eth" 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36
+ "mdc_mdio" "eth" 23, 24
+ "i2c0" "i2c" 14, 15
+ "i2c1_0" "i2c" 55, 56
+ "i2c1_1" "i2c" 73, 74
+ "i2c1_2" "i2c" 87, 88
+ "i2c2_0" "i2c" 57, 58
+ "i2c2_1" "i2c" 75, 76
+ "i2c2_2" "i2c" 89, 90
+ "i2s_in_mclk_bclk_ws" "i2s" 3, 4, 5
+ "i2s1_in_data" "i2s" 1
+ "i2s2_in_data" "i2s" 16
+ "i2s3_in_data" "i2s" 17
+ "i2s4_in_data" "i2s" 18
+ "i2s_out_mclk_bclk_ws" "i2s" 3, 4, 5
+ "i2s1_out_data" "i2s" 2
+ "i2s2_out_data" "i2s" 19
+ "i2s3_out_data" "i2s" 20
+ "i2s4_out_data" "i2s" 21
+ "ir_0_tx" "ir" 16
+ "ir_1_tx" "ir" 59
+ "ir_2_tx" "ir" 99
+ "ir_0_rx" "ir" 17
+ "ir_1_rx" "ir" 60
+ "ir_2_rx" "ir" 100
+ "ephy_leds" "led" 86, 91, 92, 93, 94
+ "ephy0_led" "led" 86
+ "ephy1_led" "led" 91
+ "ephy2_led" "led" 92
+ "ephy3_led" "led" 93
+ "ephy4_led" "led" 94
+ "wled" "led" 85
+ "par_nand" "flash" 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48,
+ 49, 50
+ "snfi" "flash" 8, 9, 10, 11, 12, 13
+ "spi_nor" "flash" 8, 9, 10, 11, 12, 13
+ "pcie0_0_waken" "pcie" 14
+ "pcie0_1_waken" "pcie" 79
+ "pcie1_0_waken" "pcie" 14
+ "pcie0_0_clkreq" "pcie" 15
+ "pcie0_1_clkreq" "pcie" 80
+ "pcie1_0_clkreq" "pcie" 15
+ "pcie0_pad_perst" "pcie" 83
+ "pcie1_pad_perst" "pcie" 84
+ "pmic_bus" "pmic" 71, 72
+ "pwm_ch1_0" "pwm" 51
+ "pwm_ch1_1" "pwm" 73
+ "pwm_ch1_2" "pwm" 95
+ "pwm_ch2_0" "pwm" 52
+ "pwm_ch2_1" "pwm" 74
+ "pwm_ch2_2" "pwm" 96
+ "pwm_ch3_0" "pwm" 53
+ "pwm_ch3_1" "pwm" 75
+ "pwm_ch3_2" "pwm" 97
+ "pwm_ch4_0" "pwm" 54
+ "pwm_ch4_1" "pwm" 67
+ "pwm_ch4_2" "pwm" 76
+ "pwm_ch4_3" "pwm" 98
+ "pwm_ch5_0" "pwm" 68
+ "pwm_ch5_1" "pwm" 77
+ "pwm_ch5_2" "pwm" 99
+ "pwm_ch6_0" "pwm" 69
+ "pwm_ch6_1" "pwm" 78
+ "pwm_ch6_2" "pwm" 81
+ "pwm_ch6_3" "pwm" 100
+ "pwm_ch7_0" "pwm" 70
+ "pwm_ch7_1" "pwm" 82
+ "pwm_ch7_2" "pwm" 101
+ "sd_0" "sd" 16, 17, 18, 19, 20, 21
+ "sd_1" "sd" 25, 26, 27, 28, 29, 30
+ "spic0_0" "spi" 63, 64, 65, 66
+ "spic0_1" "spi" 79, 80, 81, 82
+ "spic1_0" "spi" 67, 68, 69, 70
+ "spic1_1" "spi" 73, 74, 75, 76
+ "spic2_0_wp_hold" "spi" 8, 9
+ "spic2_0" "spi" 10, 11, 12, 13
+ "tdm_0_out_mclk_bclk_ws" "tdm" 8, 9, 10
+ "tdm_0_in_mclk_bclk_ws" "tdm" 11, 12, 13
+ "tdm_0_out_data" "tdm" 20
+ "tdm_0_in_data" "tdm" 21
+ "tdm_1_out_mclk_bclk_ws" "tdm" 57, 58, 59
+ "tdm_1_in_mclk_bclk_ws" "tdm" 60, 61, 62
+ "tdm_1_out_data" "tdm" 55
+ "tdm_1_in_data" "tdm" 56
+ "uart0_0_tx_rx" "uart" 6, 7
+ "uart1_0_tx_rx" "uart" 55, 56
+ "uart1_0_rts_cts" "uart" 57, 58
+ "uart1_1_tx_rx" "uart" 73, 74
+ "uart1_1_rts_cts" "uart" 75, 76
+ "uart2_0_tx_rx" "uart" 3, 4
+ "uart2_0_rts_cts" "uart" 1, 2
+ "uart2_1_tx_rx" "uart" 51, 52
+ "uart2_1_rts_cts" "uart" 53, 54
+ "uart2_2_tx_rx" "uart" 59, 60
+ "uart2_2_rts_cts" "uart" 61, 62
+ "uart2_3_tx_rx" "uart" 95, 96
+ "uart3_0_tx_rx" "uart" 57, 58
+ "uart3_1_tx_rx" "uart" 81, 82
+ "uart3_1_rts_cts" "uart" 79, 80
+ "uart4_0_tx_rx" "uart" 61, 62
+ "uart4_1_tx_rx" "uart" 91, 92
+ "uart4_1_rts_cts" "uart" 93, 94
+ "uart4_2_tx_rx" "uart" 97, 98
+ "uart4_2_rts_cts" "uart" 95, 96
+ "watchdog" "watchdog" 78
+
+Example:
+
+ pio: pinctrl@10211000 {
+ compatible = "mediatek,mt7622-pinctrl";
+ reg = <0 0x10211000 0 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ pinctrl_eth_default: eth-default {
+ mux-mdio {
+ groups = "mdc_mdio";
+ function = "eth";
+ drive-strength = <12>;
+ };
+
+ mux-gmac2 {
+ groups = "gmac2";
+ function = "eth";
+ drive-strength = <12>;
+ };
+
+ mux-esw {
+ groups = "esw";
+ function = "eth";
+ drive-strength = <8>;
+ };
+
+ conf-mdio {
+ pins = "MDC";
+ bias-pull-up;
+ };
+ };
+ };
--
2.7.4
--
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 related
* [PATCH v2 0/4] add support of pinctrl to MT7622 SoC
From: sean.wang @ 2017-12-12 6:24 UTC (permalink / raw)
To: robh+dt, mark.rutland, linus.walleij, matthias.bgg, devicetree,
linux-mediatek
Cc: linux-arm-kernel, linux-gpio, linux-kernel, Sean Wang
From: Sean Wang <sean.wang@mediatek.com>
Changes since v1:
- add changes for the suggestion in v1.
- fix up the names for pin 14, 15, 71, 72, 93 and 94.
- add function "watchdog".
- change pin groups used by ethernet, i2s, led, pcie, spic, tdm
and watchdog for refining the naming and reflecting the actual
usage on the board.
The patchset adds support for pinctrl on MT7622 SoC.
patch 1: describe the hardware, also including the defintion for pins,
groups and function.
patch 2: add cleanup for keep drivers inside the independent menu.
patch 3/4: add support for mt7622 SoC.
The IO core found on the SoC has the registers for pinctrl, pinconf and
gpio mixed up in the same register range.
However, the IO core for the MT7622 SoC is completely distinct from
anyone of previous MediaTek SoCs which already had support, such as the
hardware internal, register address map and register detailed definition
for each pin.
Therefore, instead, the driver is being newly implemented by reusing
generic methods provided from the core layer with GENERIC_PINCONF,
GENERIC_PINCTRL_GROUPS, and GENERIC_PINMUX_FUNCTIONS for the sake of code
simplicity and avoiding superfluous code. Where the function of pins
determined by groups is utilized in this driver which can help developers
less confused with what combinations of pins effective on the SoC and
even reducing the mistakes during the integration of those relevant
boards.
As the gpio_chip handling is also only a few lines, the driver also
implements the gpio functionality directly through GPIOLIB.
Sean Wang (4):
dt-bindings: pinctrl: add bindings for MediaTek MT7622 SoC
pinctrl: mediatek: cleanup for placing all drivers under the menu
pinctrl: mediatek: add pinctrl driver for MT7622 SoC
pinctrl: mediatek: update MAINTAINERS entry with MediaTek pinctrl
driver
.../devicetree/bindings/pinctrl/pinctrl-mt7622.txt | 351 +++++
MAINTAINERS | 10 +
drivers/pinctrl/Makefile | 2 +-
drivers/pinctrl/mediatek/Kconfig | 15 +-
drivers/pinctrl/mediatek/Makefile | 3 +-
drivers/pinctrl/mediatek/pinctrl-mt7622.c | 1595 ++++++++++++++++++++
6 files changed, 1972 insertions(+), 4 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt7622.c
--
2.7.4
^ permalink raw reply
* Re: [PATCH v2 3/6] ARM: sun4i: Convert to CCU
From: Priit Laes @ 2017-12-12 6:12 UTC (permalink / raw)
To: Kevin Hilman
Cc: Chen-Yu Tsai, Maxime Ripard, lkml, linux-arm-kernel, devicetree,
linux-clk-u79uwXL29TY76Z2rM5mHXA,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng, Russell King,
Mark Rutland, Rob Herring, Stephen Boyd, Michael Turquette,
Philipp Zabel, Olof Johansson
In-Reply-To: <CAOi56cUjqjcZRz6VSwUWcrW=4RQyqyZHtm1vuM3HT2ypdPJ78g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Mon, Dec 11, 2017 at 02:22:30PM -0800, Kevin Hilman wrote:
> On Sun, Mar 26, 2017 at 10:20 AM, Priit Laes <plaes-q/aMd4JkU83YtjvyW6yDsg@public.gmane.org> wrote:
> > Convert sun4i-a10.dtsi to new CCU driver.
> >
> > Signed-off-by: Priit Laes <plaes-q/aMd4JkU83YtjvyW6yDsg@public.gmane.org>
>
> I finally got around to bisecting a mainline boot failure on
> sun4i-a10-cubieboard that's been happening for quite a while. Based
> on on kernelci.org, it showed up sometime during the v4.15 merge
> window[1]. It bisected down to this commit (in mainline as commit
> 41193869f2bdb585ce09bfdd16d9482aadd560ad).
>
> When it fails, there is no output on the serial console, so I don't
> know exactly how it's failing, just that it no longer boots.
Yeah, lack of output really looks like something gone wrong in clock setup,
though the commit itself has been sitting in tree for a while and the
same board has gotten actually bunch of features enabled after my clock
patches (drm modesetting + hdmi support).
I noticed that you're using GCC 5.3.1. Can you try with newer toolchain?
Priit
>
> Kevin
>
> [1] https://kernelci.org/boot/id/5a2e10cd59b51430a9afa173/
>
> > ---
> > arch/arm/boot/dts/sun4i-a10.dtsi | 636 ++++----------------------------
> > 1 file changed, 82 insertions(+), 554 deletions(-)
> >
> > diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
> > index ba20b48..0d8320a 100644
> > --- a/arch/arm/boot/dts/sun4i-a10.dtsi
> > +++ b/arch/arm/boot/dts/sun4i-a10.dtsi
> > @@ -45,7 +45,8 @@
> >
> > #include <dt-bindings/thermal/thermal.h>
> >
> > -#include <dt-bindings/clock/sun4i-a10-pll2.h>
> > +#include <dt-bindings/clock/sunxi-a10-a20-ccu.h>
> > +#include <dt-bindings/reset/sunxi-a10-a20-ccu.h>
> > #include <dt-bindings/dma/sun4i-a10.h>
> > #include <dt-bindings/pinctrl/sun4i-a10.h>
> >
> > @@ -65,9 +66,9 @@
> > compatible = "allwinner,simple-framebuffer",
> > "simple-framebuffer";
> > allwinner,pipeline = "de_be0-lcd0-hdmi";
> > - clocks = <&ahb_gates 36>, <&ahb_gates 43>,
> > - <&ahb_gates 44>, <&de_be0_clk>,
> > - <&tcon0_ch1_clk>, <&dram_gates 26>;
> > + clocks = <&ccu CLK_AHB_LCD0>, <&ccu CLK_AHB_HDMI1>,
> > + <&ccu CLK_AHB_DE_BE0>, <&ccu CLK_DE_BE0>,
> > + <&ccu CLK_TCON0_CH1>, <&ccu CLK_DRAM_DE_BE0>;
> > status = "disabled";
> > };
> >
> > @@ -75,10 +76,11 @@
> > compatible = "allwinner,simple-framebuffer",
> > "simple-framebuffer";
> > allwinner,pipeline = "de_fe0-de_be0-lcd0-hdmi";
> > - clocks = <&ahb_gates 36>, <&ahb_gates 43>,
> > - <&ahb_gates 44>, <&ahb_gates 46>,
> > - <&de_be0_clk>, <&de_fe0_clk>, <&tcon0_ch1_clk>,
> > - <&dram_gates 25>, <&dram_gates 26>;
> > + clocks = <&ccu CLK_AHB_LCD0>, <&ccu CLK_AHB_HDMI1>,
> > + <&ccu CLK_AHB_DE_BE0>, <&ccu CLK_AHB_DE_FE0>,
> > + <&ccu CLK_DE_BE0>, <&ccu CLK_DE_FE0>,
> > + <&ccu CLK_TCON0_CH1>,
> > + <&ccu CLK_DRAM_DE_FE0>, <&ccu CLK_DRAM_DE_BE0>;
> > status = "disabled";
> > };
> >
> > @@ -86,9 +88,10 @@
> > compatible = "allwinner,simple-framebuffer",
> > "simple-framebuffer";
> > allwinner,pipeline = "de_fe0-de_be0-lcd0";
> > - clocks = <&ahb_gates 36>, <&ahb_gates 44>, <&ahb_gates 46>,
> > - <&de_be0_clk>, <&de_fe0_clk>, <&tcon0_ch0_clk>,
> > - <&dram_gates 25>, <&dram_gates 26>;
> > + clocks = <&ccu CLK_AHB_LCD0>, <&ccu CLK_AHB_DE_BE0>,
> > + <&ccu CLK_AHB_DE_FE0>, <&ccu CLK_DE_BE0>,
> > + <&ccu CLK_DE_FE0>, <&ccu CLK_TCON0_CH1>,
> > + <&ccu CLK_DRAM_DE_FE0>, <&ccu CLK_DRAM_DE_BE0>;
> > status = "disabled";
> > };
> >
> > @@ -96,11 +99,11 @@
> > compatible = "allwinner,simple-framebuffer",
> > "simple-framebuffer";
> > allwinner,pipeline = "de_fe0-de_be0-lcd0-tve0";
> > - clocks = <&ahb_gates 34>, <&ahb_gates 36>,
> > - <&ahb_gates 44>, <&ahb_gates 46>,
> > - <&de_be0_clk>, <&de_fe0_clk>,
> > - <&tcon0_ch1_clk>, <&dram_gates 5>,
> > - <&dram_gates 25>, <&dram_gates 26>;
> > + clocks = <&ccu CLK_AHB_TVE0>, <&ccu CLK_AHB_LCD0>,
> > + <&ccu CLK_AHB_DE_BE0>, <&ccu CLK_AHB_DE_FE0>,
> > + <&ccu CLK_DE_BE0>, <&ccu CLK_DE_FE0>,
> > + <&ccu CLK_TCON0_CH1>, <&ccu CLK_DRAM_TVE0>,
> > + <&ccu CLK_DRAM_DE_FE0>, <&ccu CLK_DRAM_DE_BE0>;
> > status = "disabled";
> > };
> > };
> > @@ -112,7 +115,7 @@
> > device_type = "cpu";
> > compatible = "arm,cortex-a8";
> > reg = <0x0>;
> > - clocks = <&cpu>;
> > + clocks = <&ccu CLK_CPU>;
> > clock-latency = <244144>; /* 8 32k periods */
> > operating-points = <
> > /* kHz uV */
> > @@ -168,18 +171,6 @@
> > #size-cells = <1>;
> > ranges;
> >
> > - /*
> > - * This is a dummy clock, to be used as placeholder on
> > - * other mux clocks when a specific parent clock is not
> > - * yet implemented. It should be dropped when the driver
> > - * is complete.
> > - */
> > - dummy: dummy {
> > - #clock-cells = <0>;
> > - compatible = "fixed-clock";
> > - clock-frequency = <0>;
> > - };
> > -
> > osc24M: clk@01c20050 {
> > #clock-cells = <0>;
> > compatible = "allwinner,sun4i-a10-osc-clk";
> > @@ -188,487 +179,12 @@
> > clock-output-names = "osc24M";
> > };
> >
> > - osc3M: osc3M_clk {
> > - compatible = "fixed-factor-clock";
> > - #clock-cells = <0>;
> > - clock-div = <8>;
> > - clock-mult = <1>;
> > - clocks = <&osc24M>;
> > - clock-output-names = "osc3M";
> > - };
> > -
> > osc32k: clk@0 {
> > #clock-cells = <0>;
> > compatible = "fixed-clock";
> > clock-frequency = <32768>;
> > clock-output-names = "osc32k";
> > };
> > -
> > - pll1: clk@01c20000 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-pll1-clk";
> > - reg = <0x01c20000 0x4>;
> > - clocks = <&osc24M>;
> > - clock-output-names = "pll1";
> > - };
> > -
> > - pll2: clk@01c20008 {
> > - #clock-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-pll2-clk";
> > - reg = <0x01c20008 0x8>;
> > - clocks = <&osc24M>;
> > - clock-output-names = "pll2-1x", "pll2-2x",
> > - "pll2-4x", "pll2-8x";
> > - };
> > -
> > - pll3: clk@01c20010 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-pll3-clk";
> > - reg = <0x01c20010 0x4>;
> > - clocks = <&osc3M>;
> > - clock-output-names = "pll3";
> > - };
> > -
> > - pll3x2: pll3x2_clk {
> > - compatible = "fixed-factor-clock";
> > - #clock-cells = <0>;
> > - clock-div = <1>;
> > - clock-mult = <2>;
> > - clocks = <&pll3>;
> > - clock-output-names = "pll3-2x";
> > - };
> > -
> > - pll4: clk@01c20018 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-pll1-clk";
> > - reg = <0x01c20018 0x4>;
> > - clocks = <&osc24M>;
> > - clock-output-names = "pll4";
> > - };
> > -
> > - pll5: clk@01c20020 {
> > - #clock-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-pll5-clk";
> > - reg = <0x01c20020 0x4>;
> > - clocks = <&osc24M>;
> > - clock-output-names = "pll5_ddr", "pll5_other";
> > - };
> > -
> > - pll6: clk@01c20028 {
> > - #clock-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-pll6-clk";
> > - reg = <0x01c20028 0x4>;
> > - clocks = <&osc24M>;
> > - clock-output-names = "pll6_sata", "pll6_other", "pll6";
> > - };
> > -
> > - pll7: clk@01c20030 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-pll3-clk";
> > - reg = <0x01c20030 0x4>;
> > - clocks = <&osc3M>;
> > - clock-output-names = "pll7";
> > - };
> > -
> > - pll7x2: pll7x2_clk {
> > - compatible = "fixed-factor-clock";
> > - #clock-cells = <0>;
> > - clock-div = <1>;
> > - clock-mult = <2>;
> > - clocks = <&pll7>;
> > - clock-output-names = "pll7-2x";
> > - };
> > -
> > - /* dummy is 200M */
> > - cpu: cpu@01c20054 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-cpu-clk";
> > - reg = <0x01c20054 0x4>;
> > - clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>;
> > - clock-output-names = "cpu";
> > - };
> > -
> > - axi: axi@01c20054 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-axi-clk";
> > - reg = <0x01c20054 0x4>;
> > - clocks = <&cpu>;
> > - clock-output-names = "axi";
> > - };
> > -
> > - axi_gates: clk@01c2005c {
> > - #clock-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-axi-gates-clk";
> > - reg = <0x01c2005c 0x4>;
> > - clocks = <&axi>;
> > - clock-indices = <0>;
> > - clock-output-names = "axi_dram";
> > - };
> > -
> > - ahb: ahb@01c20054 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-ahb-clk";
> > - reg = <0x01c20054 0x4>;
> > - clocks = <&axi>;
> > - clock-output-names = "ahb";
> > - };
> > -
> > - ahb_gates: clk@01c20060 {
> > - #clock-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-ahb-gates-clk";
> > - reg = <0x01c20060 0x8>;
> > - clocks = <&ahb>;
> > - clock-indices = <0>, <1>,
> > - <2>, <3>,
> > - <4>, <5>, <6>,
> > - <7>, <8>, <9>,
> > - <10>, <11>, <12>,
> > - <13>, <14>, <16>,
> > - <17>, <18>, <20>,
> > - <21>, <22>, <23>,
> > - <24>, <25>, <26>,
> > - <32>, <33>, <34>,
> > - <35>, <36>, <37>,
> > - <40>, <41>, <43>,
> > - <44>, <45>,
> > - <46>, <47>,
> > - <50>, <52>;
> > - clock-output-names = "ahb_usb0", "ahb_ehci0",
> > - "ahb_ohci0", "ahb_ehci1",
> > - "ahb_ohci1", "ahb_ss", "ahb_dma",
> > - "ahb_bist", "ahb_mmc0", "ahb_mmc1",
> > - "ahb_mmc2", "ahb_mmc3", "ahb_ms",
> > - "ahb_nand", "ahb_sdram", "ahb_ace",
> > - "ahb_emac", "ahb_ts", "ahb_spi0",
> > - "ahb_spi1", "ahb_spi2", "ahb_spi3",
> > - "ahb_pata", "ahb_sata", "ahb_gps",
> > - "ahb_ve", "ahb_tvd", "ahb_tve0",
> > - "ahb_tve1", "ahb_lcd0", "ahb_lcd1",
> > - "ahb_csi0", "ahb_csi1", "ahb_hdmi",
> > - "ahb_de_be0", "ahb_de_be1",
> > - "ahb_de_fe0", "ahb_de_fe1",
> > - "ahb_mp", "ahb_mali400";
> > - };
> > -
> > - apb0: apb0@01c20054 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-apb0-clk";
> > - reg = <0x01c20054 0x4>;
> > - clocks = <&ahb>;
> > - clock-output-names = "apb0";
> > - };
> > -
> > - apb0_gates: clk@01c20068 {
> > - #clock-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-apb0-gates-clk";
> > - reg = <0x01c20068 0x4>;
> > - clocks = <&apb0>;
> > - clock-indices = <0>, <1>,
> > - <2>, <3>,
> > - <5>, <6>,
> > - <7>, <10>;
> > - clock-output-names = "apb0_codec", "apb0_spdif",
> > - "apb0_ac97", "apb0_iis",
> > - "apb0_pio", "apb0_ir0",
> > - "apb0_ir1", "apb0_keypad";
> > - };
> > -
> > - apb1: clk@01c20058 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-apb1-clk";
> > - reg = <0x01c20058 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&osc32k>;
> > - clock-output-names = "apb1";
> > - };
> > -
> > - apb1_gates: clk@01c2006c {
> > - #clock-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-apb1-gates-clk";
> > - reg = <0x01c2006c 0x4>;
> > - clocks = <&apb1>;
> > - clock-indices = <0>, <1>,
> > - <2>, <4>,
> > - <5>, <6>,
> > - <7>, <16>,
> > - <17>, <18>,
> > - <19>, <20>,
> > - <21>, <22>,
> > - <23>;
> > - clock-output-names = "apb1_i2c0", "apb1_i2c1",
> > - "apb1_i2c2", "apb1_can",
> > - "apb1_scr", "apb1_ps20",
> > - "apb1_ps21", "apb1_uart0",
> > - "apb1_uart1", "apb1_uart2",
> > - "apb1_uart3", "apb1_uart4",
> > - "apb1_uart5", "apb1_uart6",
> > - "apb1_uart7";
> > - };
> > -
> > - nand_clk: clk@01c20080 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-mod0-clk";
> > - reg = <0x01c20080 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "nand";
> > - };
> > -
> > - ms_clk: clk@01c20084 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-mod0-clk";
> > - reg = <0x01c20084 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "ms";
> > - };
> > -
> > - mmc0_clk: clk@01c20088 {
> > - #clock-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-mmc-clk";
> > - reg = <0x01c20088 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "mmc0",
> > - "mmc0_output",
> > - "mmc0_sample";
> > - };
> > -
> > - mmc1_clk: clk@01c2008c {
> > - #clock-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-mmc-clk";
> > - reg = <0x01c2008c 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "mmc1",
> > - "mmc1_output",
> > - "mmc1_sample";
> > - };
> > -
> > - mmc2_clk: clk@01c20090 {
> > - #clock-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-mmc-clk";
> > - reg = <0x01c20090 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "mmc2",
> > - "mmc2_output",
> > - "mmc2_sample";
> > - };
> > -
> > - mmc3_clk: clk@01c20094 {
> > - #clock-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-mmc-clk";
> > - reg = <0x01c20094 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "mmc3",
> > - "mmc3_output",
> > - "mmc3_sample";
> > - };
> > -
> > - ts_clk: clk@01c20098 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-mod0-clk";
> > - reg = <0x01c20098 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "ts";
> > - };
> > -
> > - ss_clk: clk@01c2009c {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-mod0-clk";
> > - reg = <0x01c2009c 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "ss";
> > - };
> > -
> > - spi0_clk: clk@01c200a0 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-mod0-clk";
> > - reg = <0x01c200a0 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "spi0";
> > - };
> > -
> > - spi1_clk: clk@01c200a4 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-mod0-clk";
> > - reg = <0x01c200a4 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "spi1";
> > - };
> > -
> > - spi2_clk: clk@01c200a8 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-mod0-clk";
> > - reg = <0x01c200a8 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "spi2";
> > - };
> > -
> > - pata_clk: clk@01c200ac {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-mod0-clk";
> > - reg = <0x01c200ac 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "pata";
> > - };
> > -
> > - ir0_clk: clk@01c200b0 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-mod0-clk";
> > - reg = <0x01c200b0 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "ir0";
> > - };
> > -
> > - ir1_clk: clk@01c200b4 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-mod0-clk";
> > - reg = <0x01c200b4 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "ir1";
> > - };
> > -
> > - spdif_clk: clk@01c200c0 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-mod1-clk";
> > - reg = <0x01c200c0 0x4>;
> > - clocks = <&pll2 SUN4I_A10_PLL2_8X>,
> > - <&pll2 SUN4I_A10_PLL2_4X>,
> > - <&pll2 SUN4I_A10_PLL2_2X>,
> > - <&pll2 SUN4I_A10_PLL2_1X>;
> > - clock-output-names = "spdif";
> > - };
> > -
> > - usb_clk: clk@01c200cc {
> > - #clock-cells = <1>;
> > - #reset-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-usb-clk";
> > - reg = <0x01c200cc 0x4>;
> > - clocks = <&pll6 1>;
> > - clock-output-names = "usb_ohci0", "usb_ohci1",
> > - "usb_phy";
> > - };
> > -
> > - spi3_clk: clk@01c200d4 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-mod0-clk";
> > - reg = <0x01c200d4 0x4>;
> > - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
> > - clock-output-names = "spi3";
> > - };
> > -
> > - dram_gates: clk@01c20100 {
> > - #clock-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-dram-gates-clk";
> > - reg = <0x01c20100 0x4>;
> > - clocks = <&pll5 0>;
> > - clock-indices = <0>,
> > - <1>, <2>,
> > - <3>,
> > - <4>,
> > - <5>, <6>,
> > - <15>,
> > - <24>, <25>,
> > - <26>, <27>,
> > - <28>, <29>;
> > - clock-output-names = "dram_ve",
> > - "dram_csi0", "dram_csi1",
> > - "dram_ts",
> > - "dram_tvd",
> > - "dram_tve0", "dram_tve1",
> > - "dram_output",
> > - "dram_de_fe1", "dram_de_fe0",
> > - "dram_de_be0", "dram_de_be1",
> > - "dram_de_mp", "dram_ace";
> > - };
> > -
> > - de_be0_clk: clk@01c20104 {
> > - #clock-cells = <0>;
> > - #reset-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-display-clk";
> > - reg = <0x01c20104 0x4>;
> > - clocks = <&pll3>, <&pll7>, <&pll5 1>;
> > - clock-output-names = "de-be0";
> > - };
> > -
> > - de_be1_clk: clk@01c20108 {
> > - #clock-cells = <0>;
> > - #reset-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-display-clk";
> > - reg = <0x01c20108 0x4>;
> > - clocks = <&pll3>, <&pll7>, <&pll5 1>;
> > - clock-output-names = "de-be1";
> > - };
> > -
> > - de_fe0_clk: clk@01c2010c {
> > - #clock-cells = <0>;
> > - #reset-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-display-clk";
> > - reg = <0x01c2010c 0x4>;
> > - clocks = <&pll3>, <&pll7>, <&pll5 1>;
> > - clock-output-names = "de-fe0";
> > - };
> > -
> > - de_fe1_clk: clk@01c20110 {
> > - #clock-cells = <0>;
> > - #reset-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-display-clk";
> > - reg = <0x01c20110 0x4>;
> > - clocks = <&pll3>, <&pll7>, <&pll5 1>;
> > - clock-output-names = "de-fe1";
> > - };
> > -
> > -
> > - tcon0_ch0_clk: clk@01c20118 {
> > - #clock-cells = <0>;
> > - #reset-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-tcon-ch0-clk";
> > - reg = <0x01c20118 0x4>;
> > - clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
> > - clock-output-names = "tcon0-ch0-sclk";
> > -
> > - };
> > -
> > - tcon1_ch0_clk: clk@01c2011c {
> > - #clock-cells = <0>;
> > - #reset-cells = <1>;
> > - compatible = "allwinner,sun4i-a10-tcon-ch1-clk";
> > - reg = <0x01c2011c 0x4>;
> > - clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
> > - clock-output-names = "tcon1-ch0-sclk";
> > -
> > - };
> > -
> > - tcon0_ch1_clk: clk@01c2012c {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-tcon-ch0-clk";
> > - reg = <0x01c2012c 0x4>;
> > - clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
> > - clock-output-names = "tcon0-ch1-sclk";
> > -
> > - };
> > -
> > - tcon1_ch1_clk: clk@01c20130 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-tcon-ch1-clk";
> > - reg = <0x01c20130 0x4>;
> > - clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
> > - clock-output-names = "tcon1-ch1-sclk";
> > -
> > - };
> > -
> > - ve_clk: clk@01c2013c {
> > - #clock-cells = <0>;
> > - #reset-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-ve-clk";
> > - reg = <0x01c2013c 0x4>;
> > - clocks = <&pll4>;
> > - clock-output-names = "ve";
> > - };
> > -
> > - codec_clk: clk@01c20140 {
> > - #clock-cells = <0>;
> > - compatible = "allwinner,sun4i-a10-codec-clk";
> > - reg = <0x01c20140 0x4>;
> > - clocks = <&pll2 SUN4I_A10_PLL2_1X>;
> > - clock-output-names = "codec";
> > - };
> > };
> >
> > soc@01c00000 {
> > @@ -717,7 +233,7 @@
> > compatible = "allwinner,sun4i-a10-dma";
> > reg = <0x01c02000 0x1000>;
> > interrupts = <27>;
> > - clocks = <&ahb_gates 6>;
> > + clocks = <&ccu CLK_AHB_DMA>;
> > #dma-cells = <2>;
> > };
> >
> > @@ -725,7 +241,7 @@
> > compatible = "allwinner,sun4i-a10-nand";
> > reg = <0x01c03000 0x1000>;
> > interrupts = <37>;
> > - clocks = <&ahb_gates 13>, <&nand_clk>;
> > + clocks = <&ccu CLK_AHB_NAND>, <&ccu CLK_NAND>;
> > clock-names = "ahb", "mod";
> > dmas = <&dma SUN4I_DMA_DEDICATED 3>;
> > dma-names = "rxtx";
> > @@ -738,7 +254,7 @@
> > compatible = "allwinner,sun4i-a10-spi";
> > reg = <0x01c05000 0x1000>;
> > interrupts = <10>;
> > - clocks = <&ahb_gates 20>, <&spi0_clk>;
> > + clocks = <&ccu CLK_AHB_SPI0>, <&ccu CLK_SPI0>;
> > clock-names = "ahb", "mod";
> > dmas = <&dma SUN4I_DMA_DEDICATED 27>,
> > <&dma SUN4I_DMA_DEDICATED 26>;
> > @@ -752,7 +268,7 @@
> > compatible = "allwinner,sun4i-a10-spi";
> > reg = <0x01c06000 0x1000>;
> > interrupts = <11>;
> > - clocks = <&ahb_gates 21>, <&spi1_clk>;
> > + clocks = <&ccu CLK_AHB_SPI1>, <&ccu CLK_SPI1>;
> > clock-names = "ahb", "mod";
> > dmas = <&dma SUN4I_DMA_DEDICATED 9>,
> > <&dma SUN4I_DMA_DEDICATED 8>;
> > @@ -766,7 +282,7 @@
> > compatible = "allwinner,sun4i-a10-emac";
> > reg = <0x01c0b000 0x1000>;
> > interrupts = <55>;
> > - clocks = <&ahb_gates 17>;
> > + clocks = <&ccu CLK_AHB_EMAC>;
> > allwinner,sram = <&emac_sram 1>;
> > status = "disabled";
> > };
> > @@ -782,10 +298,10 @@
> > mmc0: mmc@01c0f000 {
> > compatible = "allwinner,sun4i-a10-mmc";
> > reg = <0x01c0f000 0x1000>;
> > - clocks = <&ahb_gates 8>,
> > - <&mmc0_clk 0>,
> > - <&mmc0_clk 1>,
> > - <&mmc0_clk 2>;
> > + clocks = <&ccu CLK_AHB_MMC0>,
> > + <&ccu CLK_MMC0>,
> > + <&ccu CLK_MMC0_OUTPUT>,
> > + <&ccu CLK_MMC0_SAMPLE>;
> > clock-names = "ahb",
> > "mmc",
> > "output",
> > @@ -799,10 +315,10 @@
> > mmc1: mmc@01c10000 {
> > compatible = "allwinner,sun4i-a10-mmc";
> > reg = <0x01c10000 0x1000>;
> > - clocks = <&ahb_gates 9>,
> > - <&mmc1_clk 0>,
> > - <&mmc1_clk 1>,
> > - <&mmc1_clk 2>;
> > + clocks = <&ccu CLK_AHB_MMC1>,
> > + <&ccu CLK_MMC1>,
> > + <&ccu CLK_MMC1_OUTPUT>,
> > + <&ccu CLK_MMC1_SAMPLE>;
> > clock-names = "ahb",
> > "mmc",
> > "output",
> > @@ -816,10 +332,10 @@
> > mmc2: mmc@01c11000 {
> > compatible = "allwinner,sun4i-a10-mmc";
> > reg = <0x01c11000 0x1000>;
> > - clocks = <&ahb_gates 10>,
> > - <&mmc2_clk 0>,
> > - <&mmc2_clk 1>,
> > - <&mmc2_clk 2>;
> > + clocks = <&ccu CLK_AHB_MMC2>,
> > + <&ccu CLK_MMC2>,
> > + <&ccu CLK_MMC2_OUTPUT>,
> > + <&ccu CLK_MMC2_SAMPLE>;
> > clock-names = "ahb",
> > "mmc",
> > "output",
> > @@ -833,10 +349,10 @@
> > mmc3: mmc@01c12000 {
> > compatible = "allwinner,sun4i-a10-mmc";
> > reg = <0x01c12000 0x1000>;
> > - clocks = <&ahb_gates 11>,
> > - <&mmc3_clk 0>,
> > - <&mmc3_clk 1>,
> > - <&mmc3_clk 2>;
> > + clocks = <&ccu CLK_AHB_MMC3>,
> > + <&ccu CLK_MMC3>,
> > + <&ccu CLK_MMC3_OUTPUT>,
> > + <&ccu CLK_MMC3_SAMPLE>;
> > clock-names = "ahb",
> > "mmc",
> > "output",
> > @@ -850,7 +366,7 @@
> > usb_otg: usb@01c13000 {
> > compatible = "allwinner,sun4i-a10-musb";
> > reg = <0x01c13000 0x0400>;
> > - clocks = <&ahb_gates 0>;
> > + clocks = <&ccu CLK_AHB_OTG>;
> > interrupts = <38>;
> > interrupt-names = "mc";
> > phys = <&usbphy 0>;
> > @@ -865,9 +381,11 @@
> > compatible = "allwinner,sun4i-a10-usb-phy";
> > reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>;
> > reg-names = "phy_ctrl", "pmu1", "pmu2";
> > - clocks = <&usb_clk 8>;
> > + clocks = <&ccu CLK_USB_PHY>;
> > clock-names = "usb_phy";
> > - resets = <&usb_clk 0>, <&usb_clk 1>, <&usb_clk 2>;
> > + resets = <&ccu RST_USB_PHY0>,
> > + <&ccu RST_USB_PHY1>,
> > + <&ccu RST_USB_PHY2>;
> > reset-names = "usb0_reset", "usb1_reset", "usb2_reset";
> > status = "disabled";
> > };
> > @@ -876,7 +394,7 @@
> > compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
> > reg = <0x01c14000 0x100>;
> > interrupts = <39>;
> > - clocks = <&ahb_gates 1>;
> > + clocks = <&ccu CLK_AHB_EHCI0>;
> > phys = <&usbphy 1>;
> > phy-names = "usb";
> > status = "disabled";
> > @@ -886,7 +404,7 @@
> > compatible = "allwinner,sun4i-a10-ohci", "generic-ohci";
> > reg = <0x01c14400 0x100>;
> > interrupts = <64>;
> > - clocks = <&usb_clk 6>, <&ahb_gates 2>;
> > + clocks = <&ccu CLK_USB_OHCI0>, <&ccu CLK_AHB_OHCI0>;
> > phys = <&usbphy 1>;
> > phy-names = "usb";
> > status = "disabled";
> > @@ -896,7 +414,7 @@
> > compatible = "allwinner,sun4i-a10-crypto";
> > reg = <0x01c15000 0x1000>;
> > interrupts = <86>;
> > - clocks = <&ahb_gates 5>, <&ss_clk>;
> > + clocks = <&ccu CLK_AHB_SS>, <&ccu CLK_SS>;
> > clock-names = "ahb", "mod";
> > };
> >
> > @@ -904,7 +422,7 @@
> > compatible = "allwinner,sun4i-a10-spi";
> > reg = <0x01c17000 0x1000>;
> > interrupts = <12>;
> > - clocks = <&ahb_gates 22>, <&spi2_clk>;
> > + clocks = <&ccu CLK_AHB_SPI2>, <&ccu CLK_SPI2>;
> > clock-names = "ahb", "mod";
> > dmas = <&dma SUN4I_DMA_DEDICATED 29>,
> > <&dma SUN4I_DMA_DEDICATED 28>;
> > @@ -918,7 +436,8 @@
> > compatible = "allwinner,sun4i-a10-ahci";
> > reg = <0x01c18000 0x1000>;
> > interrupts = <56>;
> > - clocks = <&pll6 0>, <&ahb_gates 25>;
> > + clocks = <&ccu CLK_PLL_PERIPH_SATA>,
> > + <&ccu CLK_AHB_SATA>;
> > status = "disabled";
> > };
> >
> > @@ -926,7 +445,7 @@
> > compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
> > reg = <0x01c1c000 0x100>;
> > interrupts = <40>;
> > - clocks = <&ahb_gates 3>;
> > + clocks = <&ccu CLK_AHB_EHCI1>;
> > phys = <&usbphy 2>;
> > phy-names = "usb";
> > status = "disabled";
> > @@ -936,7 +455,7 @@
> > compatible = "allwinner,sun4i-a10-ohci", "generic-ohci";
> > reg = <0x01c1c400 0x100>;
> > interrupts = <65>;
> > - clocks = <&usb_clk 7>, <&ahb_gates 4>;
> > + clocks = <&ccu CLK_USB_OHCI1>, <&ccu CLK_AHB_OHCI1>;
> > phys = <&usbphy 2>;
> > phy-names = "usb";
> > status = "disabled";
> > @@ -946,7 +465,7 @@
> > compatible = "allwinner,sun4i-a10-spi";
> > reg = <0x01c1f000 0x1000>;
> > interrupts = <50>;
> > - clocks = <&ahb_gates 23>, <&spi3_clk>;
> > + clocks = <&ccu CLK_AHB_SPI3>, <&ccu CLK_SPI3>;
> > clock-names = "ahb", "mod";
> > dmas = <&dma SUN4I_DMA_DEDICATED 31>,
> > <&dma SUN4I_DMA_DEDICATED 30>;
> > @@ -956,6 +475,15 @@
> > #size-cells = <0>;
> > };
> >
> > + ccu: clock@01c20000 {
> > + compatible = "allwinner,sun4i-a10-ccu";
> > + reg = <0x01c20000 0x400>;
> > + clocks = <&osc24M>, <&osc32k>;
> > + clock-names = "hosc", "losc";
> > + #clock-cells = <1>;
> > + #reset-cells = <1>;
> > + };
> > +
> > intc: interrupt-controller@01c20400 {
> > compatible = "allwinner,sun4i-a10-ic";
> > reg = <0x01c20400 0x400>;
> > @@ -967,7 +495,7 @@
> > compatible = "allwinner,sun4i-a10-pinctrl";
> > reg = <0x01c20800 0x400>;
> > interrupts = <28>;
> > - clocks = <&apb0_gates 5>, <&osc24M>, <&osc32k>;
> > + clocks = <&ccu CLK_APB0_PIO>, <&osc24M>, <&osc32k>;
> > clock-names = "apb", "hosc", "losc";
> > gpio-controller;
> > interrupt-controller;
> > @@ -1145,7 +673,7 @@
> > compatible = "allwinner,sun4i-a10-spdif";
> > reg = <0x01c21000 0x400>;
> > interrupts = <13>;
> > - clocks = <&apb0_gates 1>, <&spdif_clk>;
> > + clocks = <&ccu CLK_APB0_SPDIF>, <&ccu CLK_SPDIF>;
> > clock-names = "apb", "spdif";
> > dmas = <&dma SUN4I_DMA_NORMAL 2>,
> > <&dma SUN4I_DMA_NORMAL 2>;
> > @@ -1155,7 +683,7 @@
> >
> > ir0: ir@01c21800 {
> > compatible = "allwinner,sun4i-a10-ir";
> > - clocks = <&apb0_gates 6>, <&ir0_clk>;
> > + clocks = <&ccu CLK_APB0_IR0>, <&ccu CLK_IR0>;
> > clock-names = "apb", "ir";
> > interrupts = <5>;
> > reg = <0x01c21800 0x40>;
> > @@ -1164,7 +692,7 @@
> >
> > ir1: ir@01c21c00 {
> > compatible = "allwinner,sun4i-a10-ir";
> > - clocks = <&apb0_gates 7>, <&ir1_clk>;
> > + clocks = <&ccu CLK_APB0_IR1>, <&ccu CLK_IR1>;
> > clock-names = "apb", "ir";
> > interrupts = <6>;
> > reg = <0x01c21c00 0x40>;
> > @@ -1183,7 +711,7 @@
> > compatible = "allwinner,sun4i-a10-codec";
> > reg = <0x01c22c00 0x40>;
> > interrupts = <30>;
> > - clocks = <&apb0_gates 0>, <&codec_clk>;
> > + clocks = <&ccu CLK_APB0_CODEC>, <&ccu CLK_CODEC>;
> > clock-names = "apb", "codec";
> > dmas = <&dma SUN4I_DMA_NORMAL 19>,
> > <&dma SUN4I_DMA_NORMAL 19>;
> > @@ -1209,7 +737,7 @@
> > interrupts = <1>;
> > reg-shift = <2>;
> > reg-io-width = <4>;
> > - clocks = <&apb1_gates 16>;
> > + clocks = <&ccu CLK_APB1_UART0>;
> > status = "disabled";
> > };
> >
> > @@ -1219,7 +747,7 @@
> > interrupts = <2>;
> > reg-shift = <2>;
> > reg-io-width = <4>;
> > - clocks = <&apb1_gates 17>;
> > + clocks = <&ccu CLK_APB1_UART1>;
> > status = "disabled";
> > };
> >
> > @@ -1229,7 +757,7 @@
> > interrupts = <3>;
> > reg-shift = <2>;
> > reg-io-width = <4>;
> > - clocks = <&apb1_gates 18>;
> > + clocks = <&ccu CLK_APB1_UART2>;
> > status = "disabled";
> > };
> >
> > @@ -1239,7 +767,7 @@
> > interrupts = <4>;
> > reg-shift = <2>;
> > reg-io-width = <4>;
> > - clocks = <&apb1_gates 19>;
> > + clocks = <&ccu CLK_APB1_UART3>;
> > status = "disabled";
> > };
> >
> > @@ -1249,7 +777,7 @@
> > interrupts = <17>;
> > reg-shift = <2>;
> > reg-io-width = <4>;
> > - clocks = <&apb1_gates 20>;
> > + clocks = <&ccu CLK_APB1_UART4>;
> > status = "disabled";
> > };
> >
> > @@ -1259,7 +787,7 @@
> > interrupts = <18>;
> > reg-shift = <2>;
> > reg-io-width = <4>;
> > - clocks = <&apb1_gates 21>;
> > + clocks = <&ccu CLK_APB1_UART5>;
> > status = "disabled";
> > };
> >
> > @@ -1269,7 +797,7 @@
> > interrupts = <19>;
> > reg-shift = <2>;
> > reg-io-width = <4>;
> > - clocks = <&apb1_gates 22>;
> > + clocks = <&ccu CLK_APB1_UART6>;
> > status = "disabled";
> > };
> >
> > @@ -1279,7 +807,7 @@
> > interrupts = <20>;
> > reg-shift = <2>;
> > reg-io-width = <4>;
> > - clocks = <&apb1_gates 23>;
> > + clocks = <&ccu CLK_APB1_UART7>;
> > status = "disabled";
> > };
> >
> > @@ -1287,7 +815,7 @@
> > compatible = "allwinner,sun4i-a10-i2c";
> > reg = <0x01c2ac00 0x400>;
> > interrupts = <7>;
> > - clocks = <&apb1_gates 0>;
> > + clocks = <&ccu CLK_APB1_I2C0>;
> > status = "disabled";
> > #address-cells = <1>;
> > #size-cells = <0>;
> > @@ -1297,7 +825,7 @@
> > compatible = "allwinner,sun4i-a10-i2c";
> > reg = <0x01c2b000 0x400>;
> > interrupts = <8>;
> > - clocks = <&apb1_gates 1>;
> > + clocks = <&ccu CLK_APB1_I2C1>;
> > status = "disabled";
> > #address-cells = <1>;
> > #size-cells = <0>;
> > @@ -1307,7 +835,7 @@
> > compatible = "allwinner,sun4i-a10-i2c";
> > reg = <0x01c2b400 0x400>;
> > interrupts = <9>;
> > - clocks = <&apb1_gates 2>;
> > + clocks = <&ccu CLK_APB1_I2C2>;
> > status = "disabled";
> > #address-cells = <1>;
> > #size-cells = <0>;
> > @@ -1317,7 +845,7 @@
> > compatible = "allwinner,sun4i-a10-ps2";
> > reg = <0x01c2a000 0x400>;
> > interrupts = <62>;
> > - clocks = <&apb1_gates 6>;
> > + clocks = <&ccu CLK_APB1_PS20>;
> > status = "disabled";
> > };
> >
> > @@ -1325,7 +853,7 @@
> > compatible = "allwinner,sun4i-a10-ps2";
> > reg = <0x01c2a400 0x400>;
> > interrupts = <63>;
> > - clocks = <&apb1_gates 7>;
> > + clocks = <&ccu CLK_APB1_PS21>;
> > status = "disabled";
> > };
> > };
> > --
> > git-series 0.9.1
> >
> > --
> > You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> > To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
> > For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply
* [PATCH] arm64: allwinner: a64: a64-olinuxino: add usb otg
From: Jagan Teki @ 2017-12-12 5:56 UTC (permalink / raw)
To: Maxime Ripard
Cc: Chen-Yu Tsai, Icenowy Zheng, Rob Herring, Mark Rutland,
Catalin Marinas, Will Deacon, Michael Trimarchi, linux-arm-kernel,
devicetree, linux-kernel, linux-sunxi, Jagan Teki
Add usb otg support for a64-olinuxino board,
- USB0-ID connected with PH9
- USB0-VBUSDET connected with PH6
- USB-DRVVBUS controlled by N_VBUSEN pin from PMIC
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
.../boot/dts/allwinner/sun50i-a64-olinuxino.dts | 26 ++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
index 338e7861..f9bc6c3 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
@@ -59,6 +59,10 @@
};
};
+&ehci0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
@@ -70,6 +74,10 @@
status = "okay";
};
+&ohci0 {
+ status = "okay";
+};
+
&r_rsb {
status = "okay";
@@ -78,6 +86,7 @@
reg = <0x3a3>;
interrupt-parent = <&r_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ x-powers,drive-vbus-en; /* set N_VBUSEN as output pin */
};
};
@@ -192,8 +201,25 @@
regulator-name = "vcc-rtc";
};
+®_drivevbus {
+ regulator-name = "usb0-vbus";
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
status = "okay";
};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */
+ usb0_vbus_det-gpio = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */
+ usb0_vbus-supply = <®_drivevbus>;
+ status = "okay";
+};
--
2.7.4
^ permalink raw reply related
* [PATCH v5 3/3] dt-bindings: timer: Add andestech atcpit100 timer binding doc
From: Rick Chen @ 2017-12-12 5:47 UTC (permalink / raw)
To: rickchen36, rick, linux-kernel, arnd, linus.walleij,
daniel.lezcano, linux-arch, tglx, jason, marc.zyngier, robh+dt,
netdev, deanbo422, devicetree, viro, dhowells, will.deacon,
linux-serial
Cc: Greentime Hu
In-Reply-To: <1513057621-19084-1-git-send-email-rickchen36@gmail.com>
Add a document to describe Andestech atcpit100 timer and
binding information.
Signed-off-by: Rick Chen <rickchen36@gmail.com>
Signed-off-by: Greentime Hu <green.hu@gmail.com>
Acked-by: Rob Herring <robh@kernel.org>
---
.../bindings/timer/andestech,atcpit100-timer.txt | 33 ++++++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 Documentation/devicetree/bindings/timer/andestech,atcpit100-timer.txt
diff --git a/Documentation/devicetree/bindings/timer/andestech,atcpit100-timer.txt b/Documentation/devicetree/bindings/timer/andestech,atcpit100-timer.txt
new file mode 100644
index 0000000..14812f68
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/andestech,atcpit100-timer.txt
@@ -0,0 +1,33 @@
+Andestech ATCPIT100 timer
+------------------------------------------------------------------
+ATCPIT100 is a generic IP block from Andes Technology, embedded in
+Andestech AE3XX platforms and other designs.
+
+This timer is a set of compact multi-function timers, which can be
+used as pulse width modulators (PWM) as well as simple timers.
+
+It supports up to 4 PIT channels. Each PIT channel is a
+multi-function timer and provide the following usage scenarios:
+One 32-bit timer
+Two 16-bit timers
+Four 8-bit timers
+One 16-bit PWM
+One 16-bit timer and one 8-bit PWM
+Two 8-bit timer and one 8-bit PWM
+
+Required properties:
+- compatible : Should be "andestech,atcpit100"
+- reg : Address and length of the register set
+- interrupts : Reference to the timer interrupt
+- clocks : a clock to provide the tick rate for "andestech,atcpit100"
+- clock-names : should be "PCLK" for the peripheral clock source.
+
+Examples:
+
+timer0: timer@f0400000 {
+ compatible = "andestech,atcpit100";
+ reg = <0xf0400000 0x1000>;
+ interrupts = <2 4>;
+ clocks = <&apb>;
+ clock-names = "PCLK";
+};
--
2.7.4
^ permalink raw reply related
* [PATCH v5 2/3] clocksource/drivers/atcpit100: VDSO support
From: Rick Chen @ 2017-12-12 5:47 UTC (permalink / raw)
To: rickchen36, rick, linux-kernel, arnd, linus.walleij,
daniel.lezcano, linux-arch, tglx, jason, marc.zyngier, robh+dt,
netdev, deanbo422, devicetree, viro, dhowells, will.deacon,
linux-serial
Cc: Vincent Chen, Greentime Hu
In-Reply-To: <1513057621-19084-1-git-send-email-rickchen36@gmail.com>
VDSO needs real-time cycle count to ensure the time accuracy.
Unlike others, nds32 architecture does not define clock source,
hence VDSO needs atcpit100 offering real-time cycle count
to derive the correct time.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Rick Chen <rickchen36@gmail.com>
Signed-off-by: Greentime Hu <green.hu@gmail.com>
---
drivers/clocksource/timer-atcpit100.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/clocksource/timer-atcpit100.c b/drivers/clocksource/timer-atcpit100.c
index 0077fdb..1be6c0a 100644
--- a/drivers/clocksource/timer-atcpit100.c
+++ b/drivers/clocksource/timer-atcpit100.c
@@ -29,6 +29,9 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include "timer-of.h"
+#ifdef CONFIG_NDS32
+#include <asm/vdso_timer_info.h>
+#endif
/*
* Definition of register offsets
@@ -211,6 +214,14 @@ static u64 notrace atcpit100_timer_sched_read(void)
return ~readl(timer_of_base(&to) + CH1_CNT);
}
+#ifdef CONFIG_NDS32
+static void fill_vdso_need_info(void)
+{
+ timer_info.cycle_count_down = true;
+ timer_info.cycle_count_reg_offset = CH1_CNT;
+}
+#endif
+
static int __init atcpit100_timer_init(struct device_node *node)
{
int ret;
@@ -249,6 +260,10 @@ static int __init atcpit100_timer_init(struct device_node *node)
val = readl(base + INT_EN);
writel(val | CH0INT0EN, base + INT_EN);
+#ifdef CONFIG_NDS32
+ fill_vdso_need_info();
+#endif
+
return ret;
}
--
2.7.4
^ permalink raw reply related
* [PATCH v5 1/3] clocksource/drivers/atcpit100: Add andestech atcpit100 timer
From: Rick Chen @ 2017-12-12 5:46 UTC (permalink / raw)
To: rickchen36, rick, linux-kernel, arnd, linus.walleij,
daniel.lezcano, linux-arch, tglx, jason, marc.zyngier, robh+dt,
netdev, deanbo422, devicetree, viro, dhowells, will.deacon,
linux-serial
Cc: Greentime Hu
In-Reply-To: <1513057621-19084-1-git-send-email-rickchen36@gmail.com>
ATCPIT100 is often used on the Andes architecture,
This timer provide 4 PIT channels. Each PIT channel is a
multi-function timer, can be configured as 32,16,8 bit timers
or PWM as well.
For system timer it will set channel 1 32-bit timer0 as clock
source and count downwards until underflow and restart again.
It also set channel 0 32-bit timer0 as clock event and count
downwards until condition match. It will generate an interrupt
for handling periodically.
Signed-off-by: Rick Chen <rickchen36@gmail.com>
Signed-off-by: Greentime Hu <green.hu@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
---
drivers/clocksource/Kconfig | 7 +
drivers/clocksource/Makefile | 1 +
drivers/clocksource/timer-atcpit100.c | 255 ++++++++++++++++++++++++++++++++++
3 files changed, 263 insertions(+)
create mode 100644 drivers/clocksource/timer-atcpit100.c
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index cc60620..8c57ef2 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -615,4 +615,11 @@ config CLKSRC_ST_LPC
Enable this option to use the Low Power controller timer
as clocksource.
+config CLKSRC_ATCPIT100
+ bool "Clocksource for AE3XX platform"
+ depends on NDS32 || COMPILE_TEST
+ depends on HAS_IOMEM
+ help
+ This option enables support for the Andestech AE3XX platform timers.
+
endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 72711f1..7d072f5 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -75,3 +75,4 @@ obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o
obj-$(CONFIG_H8300_TPU) += h8300_tpu.o
obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o
obj-$(CONFIG_X86_NUMACHIP) += numachip.o
+obj-$(CONFIG_CLKSRC_ATCPIT100) += timer-atcpit100.o
diff --git a/drivers/clocksource/timer-atcpit100.c b/drivers/clocksource/timer-atcpit100.c
new file mode 100644
index 0000000..0077fdb
--- /dev/null
+++ b/drivers/clocksource/timer-atcpit100.c
@@ -0,0 +1,255 @@
+/*
+ * Andestech ATCPIT100 Timer Device Driver Implementation
+ *
+ * Copyright (C) 2017 Andes Technology Corporation
+ * Rick Chen, Andes Technology Corporation <rick@andestech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/cpufreq.h>
+#include <linux/sched.h>
+#include <linux/sched_clock.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include "timer-of.h"
+
+/*
+ * Definition of register offsets
+ */
+
+/* ID and Revision Register */
+#define ID_REV 0x0
+
+/* Configuration Register */
+#define CFG 0x10
+
+/* Interrupt Enable Register */
+#define INT_EN 0x14
+#define CH_INT_EN(c, i) ((1<<i)<<(4*c))
+#define CH0INT0EN 0x01
+
+/* Interrupt Status Register */
+#define INT_STA 0x18
+#define CH0INT0 0x01
+
+/* Channel Enable Register */
+#define CH_EN 0x1C
+#define CH0TMR0EN 0x1
+#define CH1TMR0EN 0x10
+
+/* Channel 0 , 1 Control Register */
+#define CH0_CTL (0x20)
+#define CH1_CTL (0x20 + 0x10)
+
+/* Channel clock source , bit 3 , 0:External clock , 1:APB clock */
+#define APB_CLK BIT(3)
+
+/* Channel mode , bit 0~2 */
+#define TMR_32 0x1
+#define TMR_16 0x2
+#define TMR_8 0x3
+
+/* Channel 0 , 1 Reload Register */
+#define CH0_REL (0x24)
+#define CH1_REL (0x24 + 0x10)
+
+/* Channel 0 , 1 Counter Register */
+#define CH0_CNT (0x28)
+#define CH1_CNT (0x28 + 0x10)
+
+#define TIMER_SYNC_TICKS 3
+
+static void atcpit100_ch1_tmr0_en(void __iomem *base)
+{
+ writel(~0, base + CH1_REL);
+ writel(APB_CLK|TMR_32, base + CH1_CTL);
+}
+
+static void atcpit100_ch0_tmr0_en(void __iomem *base)
+{
+ writel(APB_CLK|TMR_32, base + CH0_CTL);
+}
+
+static void atcpit100_clkevt_time_setup(void __iomem *base, unsigned long delay)
+{
+ writel(delay, base + CH0_CNT);
+ writel(delay, base + CH0_REL);
+}
+
+static void atcpit100_timer_clear_interrupt(void __iomem *base)
+{
+ u32 val;
+
+ val = readl(base + INT_STA);
+ writel(val | CH0INT0, base + INT_STA);
+}
+
+static void atcpit100_clocksource_start(void __iomem *base)
+{
+ u32 val;
+
+ val = readl(base + CH_EN);
+ writel(val | CH1TMR0EN, base + CH_EN);
+}
+
+static void atcpit100_clkevt_time_start(void __iomem *base)
+{
+ u32 val;
+
+ val = readl(base + CH_EN);
+ writel(val | CH0TMR0EN, base + CH_EN);
+}
+
+static void atcpit100_clkevt_time_stop(void __iomem *base)
+{
+ u32 val;
+
+ atcpit100_timer_clear_interrupt(base);
+ val = readl(base + CH_EN);
+ writel(val & ~CH0TMR0EN, base + CH_EN);
+}
+
+static int atcpit100_clkevt_next_event(unsigned long evt,
+ struct clock_event_device *clkevt)
+{
+ struct timer_of *to = to_timer_of(clkevt);
+
+ writel(evt, timer_of_base(to) + CH0_REL);
+
+ return 0;
+}
+
+static int atcpit100_clkevt_set_periodic(struct clock_event_device *evt)
+{
+ struct timer_of *to = to_timer_of(evt);
+
+ atcpit100_clkevt_time_setup(timer_of_base(to), timer_of_period(to));
+ atcpit100_clkevt_time_start(timer_of_base(to));
+
+ return 0;
+}
+static int atcpit100_clkevt_shutdown(struct clock_event_device *evt)
+{
+ struct timer_of *to = to_timer_of(evt);
+
+ atcpit100_clkevt_time_stop(timer_of_base(to));
+
+ return 0;
+}
+static int atcpit100_clkevt_set_oneshot(struct clock_event_device *evt)
+{
+ struct timer_of *to = to_timer_of(evt);
+ u32 val;
+
+ writel(~0x0, timer_of_base(to) + CH0_REL);
+ val = readl(timer_of_base(to) + CH_EN);
+ writel(val | CH0TMR0EN, timer_of_base(to) + CH_EN);
+
+ return 0;
+}
+
+static irqreturn_t atcpit100_timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = (struct clock_event_device *)dev_id;
+ struct timer_of *to = to_timer_of(evt);
+
+ atcpit100_timer_clear_interrupt(timer_of_base(to));
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct timer_of to = {
+ .flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE,
+
+ .clkevt = {
+ .name = "atcpit100_tick",
+ .rating = 300,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_state_shutdown = atcpit100_clkevt_shutdown,
+ .set_state_periodic = atcpit100_clkevt_set_periodic,
+ .set_state_oneshot = atcpit100_clkevt_set_oneshot,
+ .tick_resume = atcpit100_clkevt_shutdown,
+ .set_next_event = atcpit100_clkevt_next_event,
+ .cpumask = cpu_all_mask,
+ },
+
+ .of_irq = {
+ .handler = atcpit100_timer_interrupt,
+ .flags = IRQF_TIMER | IRQF_IRQPOLL,
+ },
+
+ /*
+ * FIXME: we currently only support clocking using PCLK
+ * and using EXTCLK is not supported in the driver.
+ */
+ .of_clk = {
+ .name = "PCLK",
+ }
+};
+
+static u64 notrace atcpit100_timer_sched_read(void)
+{
+ return ~readl(timer_of_base(&to) + CH1_CNT);
+}
+
+static int __init atcpit100_timer_init(struct device_node *node)
+{
+ int ret;
+ u32 val;
+ void __iomem *base;
+
+ ret = timer_of_init(node, &to);
+ if (ret)
+ return ret;
+
+ base = timer_of_base(&to);
+
+ sched_clock_register(atcpit100_timer_sched_read, 32,
+ timer_of_rate(&to));
+
+ ret = clocksource_mmio_init(base + CH1_CNT,
+ node->name, timer_of_rate(&to), 300, 32,
+ clocksource_mmio_readl_down);
+
+ if (ret) {
+ pr_err("Failed to register clocksource\n");
+ return ret;
+ }
+
+ /* clear channel 0 timer0 interrupt */
+ atcpit100_timer_clear_interrupt(base);
+
+ clockevents_config_and_register(&to.clkevt, timer_of_rate(&to),
+ TIMER_SYNC_TICKS, 0xffffffff);
+ atcpit100_ch0_tmr0_en(base);
+ atcpit100_ch1_tmr0_en(base);
+ atcpit100_clocksource_start(base);
+ atcpit100_clkevt_time_start(base);
+
+ /* Enable channel 0 timer0 interrupt */
+ val = readl(base + INT_EN);
+ writel(val | CH0INT0EN, base + INT_EN);
+
+ return ret;
+}
+
+TIMER_OF_DECLARE(atcpit100, "andestech,atcpit100", atcpit100_timer_init);
--
2.7.4
^ permalink raw reply related
* [PATCH v5 0/3] Add andestech atcpit100 timer
From: Rick Chen @ 2017-12-12 5:46 UTC (permalink / raw)
To: rickchen36-Re5JQEeQqe8AvxtiuMwx3w, rick-MUIXKm3Oiri1Z/+hSey0Gg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A,
linux-arch-u79uwXL29TY76Z2rM5mHXA, tglx-hfZtesqFncYOwBW4kG4KsQ,
jason-NLaQJdtUoK4Be96aLqz0jA, marc.zyngier-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, netdev-u79uwXL29TY76Z2rM5mHXA,
deanbo422-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA,
viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
dhowells-H+wXaHxf7aLQT0dZR+AlfA, will.deacon-5wv7dgnIgG8,
linux-serial-u79uwXL29TY76Z2rM5mHXA
Changelog v5:
- Patch 1/3: Changes
- Patch 2/3: New
- Patch 3/3: Changes
[Patch 1/3] clocksource/drivers/atcpit100: Add andestech atcpit100 timer
1 No need to split out the Makefile patch from the actual driver.
Suggested by Arnd Bergmann
2 Add of_clk.name = "PCLK" to be explicit on what we use.
Suggested by Linus Walleij
3 Remove the GENERIC_CLOCKEVENTS from Kconfig.
Suggested by Daniel Lezcano
4 Add depends on NDS32 || COMPILE_TEST in Kconfig
Suggested by Greentime Hu
[Patch 2/3] clocksource/drivers/atcpit100: VDSO support
Why implemented in timer driver, please see details from
https://lkml.org/lkml/2017/12/8/362
[PATCH v3 17/33] nds32: VDSO support.
Suggested by Mark Rutland
Here Mark Rutlan suggested as below:
You should not add properties to arbitrary DT bindings to
handle a Linux implementation detail.
Please remove this DT code, and have the drivers for those
timer blocks export this information to your vdso code somehow.
[Patch 3/3] dt-bindings: timer: Add andestech atcpit100 timer binding doc
Fix incorrect description about PCLK.
Suggested by Linus Walleij
Rick Chen (3):
clocksource/drivers/atcpit100: Add andestech atcpit100 timer
clocksource/drivers/atcpit100: VDSO support
dt-bindings: timer: Add andestech atcpit100 timer binding doc
.../bindings/timer/andestech,atcpit100-timer.txt | 33 +++
drivers/clocksource/Kconfig | 7 +
drivers/clocksource/Makefile | 1 +
drivers/clocksource/timer-atcpit100.c | 270 +++++++++++++++++++++
4 files changed, 311 insertions(+)
create mode 100644 Documentation/devicetree/bindings/timer/andestech,atcpit100-timer.txt
create mode 100644 drivers/clocksource/timer-atcpit100.c
--
2.7.4
--
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 V7 0/7] dmaengine: qcom_hidma: add support for bugfixed HW
From: Vinod Koul @ 2017-12-12 5:38 UTC (permalink / raw)
To: Sinan Kaya
Cc: dmaengine, timur, devicetree, linux-acpi, sakari.ailus,
linux-arm-msm, linux-arm-kernel
In-Reply-To: <1512681031-11343-1-git-send-email-okaya@codeaurora.org>
On Thu, Dec 07, 2017 at 04:10:24PM -0500, Sinan Kaya wrote:
> Introduce new ACPI and OF device ids for thw HW along with the helper
> functions.
>
> Changes from v6:
> * add const to the device callback parameter in fwnode.
> * reorganize the callbacks in the code
> * rename get_match_data() as device_get_match_data()
> * place pointer checks into acpi_get_match_data()
This fails for me at 3rd patch. I am on -rc1 is there a dependency?
--
~Vinod
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox