* Re: [PATCH v2] ARM: dts: Add missing CPU frequencies for Exynos5422/5800
From: Markus Reichl @ 2016-12-15 13:55 UTC (permalink / raw)
To: Bartlomiej Zolnierkiewicz, Krzysztof Kozlowski
Cc: Kukjin Kim, Javier Martinez Canillas, Rob Herring, Mark Rutland,
Russell King, Doug Anderson, Andreas Faerber, Thomas Abraham,
Ben Gamari, Arjun K V, linux-samsung-soc, linux-arm-kernel,
linux-pm, devicetree, linux-kernel
In-Reply-To: <10512254.nyUcL0zgTP@amdc3058>
Hi Bartlomiej,
Am 15.12.2016 um 12:55 schrieb Bartlomiej Zolnierkiewicz:
> Add missing 2000MHz & 1900MHz OPPs (for A15 cores) and 1400MHz OPP
> (for A7 cores). Also update common Odroid-XU3 Lite/XU3/XU4 thermal
> cooling maps to account for new OPPs.
>
> Since new OPPs are not available on all Exynos5422/5800 boards modify
> dts files for Odroid-XU3 Lite (limited to 1.8 GHz / 1.3 GHz) & Peach
> Pi (limited to 2.0 GHz / 1.3 GHz) accordingly.
>
> Tested on Odroid-XU3 and XU3 Lite.
>
> Cc: Doug Anderson <dianders@chromium.org>
> Cc: Javier Martinez Canillas <javier@osg.samsung.com>
> Cc: Andreas Faerber <afaerber@suse.de>
> Cc: Thomas Abraham <thomas.ab@samsung.com>
> Cc: Ben Gamari <ben@smart-cactus.org>
> Cc: Arjun K V <arjun.kv@samsung.com>
> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> ---
> v2:
> - added comments about limitations of SoC revisions used by Odroid-XU3 Lite and
> Peach Pi boards (suggested by Javier)
> - removed redundant opp_a7_14 label
> - added Arjun to Cc:
>
> Javier, could you test it on Peach Pi board?
>
> arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi | 14 ++++++-------
> arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts | 22 +++++++++++++++++++++
> arch/arm/boot/dts/exynos5800-peach-pi.dts | 9 ++++++++
> arch/arm/boot/dts/exynos5800.dtsi | 15 ++++++++++++++
> 4 files changed, 53 insertions(+), 7 deletions(-)
>
> Index: b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
> ===================================================================
> --- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi 2016-12-15 12:43:54.365955950 +0100
> +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi 2016-12-15 12:43:54.361955949 +0100
> @@ -118,7 +118,7 @@
> /*
> * When reaching cpu_alert3, reduce CPU
> * by 2 steps. On Exynos5422/5800 that would
> - * be: 1600 MHz and 1100 MHz.
> + * (usually) be: 1800 MHz and 1200 MHz.
> */
> map3 {
> trip = <&cpu_alert3>;
> @@ -131,16 +131,16 @@
>
> /*
> * When reaching cpu_alert4, reduce CPU
> - * further, down to 600 MHz (11 steps for big,
> - * 7 steps for LITTLE).
> + * further, down to 600 MHz (13 steps for big,
> + * 8 steps for LITTLE).
> */
> - map5 {
> + cooling_map5: map5 {
> trip = <&cpu_alert4>;
> - cooling-device = <&cpu0 3 7>;
> + cooling-device = <&cpu0 3 8>;
> };
> - map6 {
> + cooling_map6: map6 {
> trip = <&cpu_alert4>;
> - cooling-device = <&cpu4 3 11>;
> + cooling-device = <&cpu4 3 13>;
> };
> };
> };
> Index: b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
> ===================================================================
> --- a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts 2016-12-15 12:43:54.365955950 +0100
> +++ b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts 2016-12-15 12:43:54.361955949 +0100
> @@ -21,6 +21,28 @@
> compatible = "hardkernel,odroid-xu3-lite", "samsung,exynos5800", "samsung,exynos5";
> };
>
> +/*
> + * Odroid XU3-Lite board uses SoC revision with lower maximum frequencies
> + * than Odroid XU3/XU4 boards: 1.8 GHz for A15 cores & 1.3 GHz for A7 cores.
> + * Therefore we need to update OPPs tables and thermal maps accordingly.
> + */
> +&cluster_a15_opp_table {
> + /delete-node/opp@2000000000;
> + /delete-node/opp@1900000000;
> +};
> +
> +&cluster_a7_opp_table {
> + /delete-node/opp@1400000000;
> +};
> +
> +&cooling_map5 {
> + cooling-device = <&cpu0 3 7>;
> +};
> +
> +&cooling_map6 {
> + cooling-device = <&cpu4 3 11>;
> +};
> +
> &pwm {
> /*
> * PWM 0 -- fan
> Index: b/arch/arm/boot/dts/exynos5800-peach-pi.dts
> ===================================================================
> --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts 2016-12-15 12:43:54.365955950 +0100
> +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts 2016-12-15 12:43:54.361955949 +0100
> @@ -146,6 +146,15 @@
> vdd-supply = <&ldo9_reg>;
> };
>
> +/*
> + * Peach Pi board uses SoC revision with lower maximum frequency for A7 cores
> + * (1.3 GHz instead of 1.4 GHz) than Odroid XU3/XU4 boards. Thus we need to
> + * update A7 OPPs table accordingly.
> + */
> +&cluster_a7_opp_table {
> + /delete-property/opp@1400000000;
> +};
> +
> &cpu0 {
> cpu-supply = <&buck2_reg>;
> };
> Index: b/arch/arm/boot/dts/exynos5800.dtsi
> ===================================================================
> --- a/arch/arm/boot/dts/exynos5800.dtsi 2016-12-15 12:43:54.365955950 +0100
> +++ b/arch/arm/boot/dts/exynos5800.dtsi 2016-12-15 12:43:54.361955949 +0100
> @@ -24,6 +24,16 @@
> };
>
> &cluster_a15_opp_table {
> + opp@2000000000 {
> + opp-hz = /bits/ 64 <2000000000>;
> + opp-microvolt = <1250000>;
> + clock-latency-ns = <140000>;
> + };
> + opp@1900000000 {
> + opp-hz = /bits/ 64 <1900000000>;
> + opp-microvolt = <1250000>;
> + clock-latency-ns = <140000>;
> + };
> opp@1700000000 {
> opp-microvolt = <1250000>;
> };
> @@ -85,6 +95,11 @@
> };
>
> &cluster_a7_opp_table {
> + opp@1400000000 {
> + opp-hz = /bits/ 64 <1400000000>;
> + opp-microvolt = <1250000>;
> + clock-latency-ns = <140000>;
> + };
> opp@1300000000 {
> opp-microvolt = <1250000>;
> };
>
On Odroid XU4, XU3 and XU3-lite:
Tested-by: Markus Reichl <m.reichl@fivetechno.de>
Thanks,
--
Markus Reichl
^ permalink raw reply
* Re: [PATCH 1/1] of: of_reserved_mem: Ensure cma reserved region not cross the low/high memory
From: Rob Herring @ 2016-12-15 13:54 UTC (permalink / raw)
To: Laura Abbott
Cc: Jason Liu, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Frank Rowand
In-Reply-To: <833f99b1-d10b-27ba-e0f9-a7c6398fb63d-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
On Wed, Dec 14, 2016 at 4:21 PM, Laura Abbott <labbott-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> On 12/14/2016 12:45 PM, Rob Herring wrote:
>> On Wed, Nov 23, 2016 at 5:37 AM, Jason Liu <jason.hui.liu-3arQi8VN3Tc@public.gmane.org> wrote:
>>> Need ensure the cma reserved region not cross the low/high memory boundary
>>> when using the dynamic allocation methond through device-tree, otherwise,
>>> kernel will fail to boot up when cma reserved region cross how/high mem.
>>
>> The kernel command line code setting CMA already deals with this. Why
>> don't we just call the CMA code (cma_declare_contiguous) to deal with
>> this?
>>
>> Rob
>>
>
> That was proposed in the first version[1] but I think this is a generic
> problem not specific to CMA. Even non-CMA reservations trying to span
> zones could cause problems so the devicetree allocation code should
> restrict reservations to a single zone.
Fair enough, but that's not what this patch does. It's only for CMA.
Rob
--
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: [RESEND PATCHv3 2/2] regulator: fixed: Handle optional overcurrent pin
From: Axel Haslam @ 2016-12-15 13:03 UTC (permalink / raw)
To: Mark Brown
Cc: Liam Girdwood, Kevin Hilman, Sekhar Nori, David Lechner,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161215121958.klssvbtbuhsz3pga-GFdadSzt00ze9xe1eoZjHA@public.gmane.org>
On Thu, Dec 15, 2016 at 1:19 PM, Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> On Thu, Dec 15, 2016 at 12:28:56PM +0100, Axel Haslam wrote:
>
>> + ret = devm_request_threaded_irq(&pdev->dev,
>> + gpiod_to_irq(drvdata->oc_gpio), NULL,
>> + reg_fixed_overcurrent_irq, irqflags,
>> + "over_current", drvdata);
>
>> drvdata->dev = devm_regulator_register(&pdev->dev, &drvdata->desc,
>> &cfg);
>
> We are registering a managed interrupt for the interrupt handler and we
> are registering it before we register the regulator. This means that
> the interrupt may fire in both probe and remove paths without the
> regulator which it will then try to use in the interrupt handler,
> potentially crashing the system. It's better to register the interrupt
> after the regulator (which will make the managed bit OK) to avoid this
> possibility.
will fix, and send v4.
Regards,
Axel.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v3] dt-bindings: power: supply: bq24735: reverse the polarity of ac-detect
From: Peter Rosin @ 2016-12-15 12:21 UTC (permalink / raw)
To: linux-kernel
Cc: Peter Rosin, Sebastian Reichel, Rob Herring, Mark Rutland,
linux-pm, devicetree, linux-tegra, Jon Hunter
The ACOK pin on the bq24735 is active-high, of course meaning that when
AC is OK the pin is high. However, all Tegra dts files have incorrectly
specified active-high even though the signal is inverted on the Tegra
boards. This has worked since the Linux driver has also inverted the
meaning of the GPIO. Fix this situation by simply specifying in the
bindings what everybody else agrees on; that the ti,ac-detect-gpios is
active on AC adapter absence.
Signed-off-by: Peter Rosin <peda@axentia.se>
---
Hi!
This patch is the result of this discussion:
http://marc.info/?t=148152531800002
I don't like how it changes the one thing that is seems correct, but
what to do?
Cheers,
Peter
Documentation/devicetree/bindings/power/supply/ti,bq24735.txt | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/power/supply/ti,bq24735.txt b/Documentation/devicetree/bindings/power/supply/ti,bq24735.txt
index 3bf55757ceec..43d56c49455b 100644
--- a/Documentation/devicetree/bindings/power/supply/ti,bq24735.txt
+++ b/Documentation/devicetree/bindings/power/supply/ti,bq24735.txt
@@ -8,8 +8,9 @@ Optional properties :
- interrupts : Specify the interrupt to be used to trigger when the AC
adapter is either plugged in or removed.
- ti,ac-detect-gpios : This GPIO is optionally used to read the AC adapter
- presence. This is a Host GPIO that is configured as an input and
- connected to the bq24735.
+ status. This is a Host GPIO that is configured as an input and
+ connected to the bq24735, typically the ACOK pin (note: the GPIO should
+ be active on AC adapter absence).
- ti,charge-current : Used to control and set the charging current. This value
must be between 128mA and 8.128A with a 64mA step resolution. The POR value
is 0x0000h. This number is in mA (e.g. 8192), see spec for more information
--
2.1.4
^ permalink raw reply related
* Re: [PATCH 0/3] clkdev: add devm_get_clk_from_child()
From: Mark Brown @ 2016-12-15 12:21 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Stephen Boyd, Russell King - ARM Linux, Rob Herring, Linux-ALSA,
Linux-DT, Michael Turquette, Linux-Kernel, linux-clk, Linux-ARM
In-Reply-To: <8737hyymo9.wl%kuninori.morimoto.gx@renesas.com>
[-- Attachment #1: Type: text/plain, Size: 291 bytes --]
On Fri, Dec 09, 2016 at 12:25:48AM +0000, Kuninori Morimoto wrote:
> Mark, I think I should re-post 2nd patch (3rd will be dropped) after
> merge window ? There will be no branch dependency
Should be fine without but obviously if it looks like it's gone AWOL
then reposting would be good.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Applied "misc: atmel-ssc: register as sound DAI if #sound-dai-cells is present" to the asoc tree
From: Mark Brown @ 2016-12-15 12:20 UTC (permalink / raw)
To: Peter Rosin
Cc: Rob Herring, Nicolas Ferre, Mark Brown, linux-kernel,
Mark Rutland, devicetree, alsa-devel, Arnd Bergmann,
Greg Kroah-Hartman, Takashi Iwai
In-Reply-To: <1480593549-6464-2-git-send-email-peda@axentia.se>
The patch
misc: atmel-ssc: register as sound DAI if #sound-dai-cells is present
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From e8314d7d53c8b050aac2828a5de5f28a997b468b Mon Sep 17 00:00:00 2001
From: Peter Rosin <peda@axentia.se>
Date: Tue, 6 Dec 2016 20:22:36 +0100
Subject: [PATCH] misc: atmel-ssc: register as sound DAI if #sound-dai-cells is
present
The SSC is currently not usable with the ASoC simple-audio-card, as
every SSC audio user has to build a platform driver that may do as
little as calling atmel_ssc_set_audio/atmel_ssc_put_audio (which
allocates the SSC and registers a DAI with the ASoC subsystem).
So, have that happen automatically, if the #sound-dai-cells property
is present in devicetree, which it has to be anyway for simple audio
card to work.
Signed-off-by: Peter Rosin <peda@axentia.se>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
.../devicetree/bindings/misc/atmel-ssc.txt | 2 +
drivers/misc/atmel-ssc.c | 50 ++++++++++++++++++++++
include/linux/atmel-ssc.h | 1 +
3 files changed, 53 insertions(+)
diff --git a/Documentation/devicetree/bindings/misc/atmel-ssc.txt b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
index efc98ea1f23d..f8629bb73945 100644
--- a/Documentation/devicetree/bindings/misc/atmel-ssc.txt
+++ b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
@@ -24,6 +24,8 @@ Optional properties:
this parameter to choose where the clock from.
- By default the clock is from TK pin, if the clock from RK pin, this
property is needed.
+ - #sound-dai-cells: Should contain <0>.
+ - This property makes the SSC into an automatically registered DAI.
Examples:
- PDC transfer:
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 0516ecda54d3..b2a0340f277e 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -20,6 +20,8 @@
#include <linux/of.h>
+#include "../../sound/soc/atmel/atmel_ssc_dai.h"
+
/* Serialize access to ssc_list and user count */
static DEFINE_SPINLOCK(user_lock);
static LIST_HEAD(ssc_list);
@@ -145,6 +147,49 @@ static inline const struct atmel_ssc_platform_data * __init
platform_get_device_id(pdev)->driver_data;
}
+#ifdef CONFIG_SND_ATMEL_SOC_SSC
+static int ssc_sound_dai_probe(struct ssc_device *ssc)
+{
+ struct device_node *np = ssc->pdev->dev.of_node;
+ int ret;
+ int id;
+
+ ssc->sound_dai = false;
+
+ if (!of_property_read_bool(np, "#sound-dai-cells"))
+ return 0;
+
+ id = of_alias_get_id(np, "ssc");
+ if (id < 0)
+ return id;
+
+ ret = atmel_ssc_set_audio(id);
+ ssc->sound_dai = !ret;
+
+ return ret;
+}
+
+static void ssc_sound_dai_remove(struct ssc_device *ssc)
+{
+ if (!ssc->sound_dai)
+ return;
+
+ atmel_ssc_put_audio(of_alias_get_id(ssc->pdev->dev.of_node, "ssc"));
+}
+#else
+static inline int ssc_sound_dai_probe(struct ssc_device *ssc)
+{
+ if (of_property_read_bool(ssc->pdev->dev.of_node, "#sound-dai-cells"))
+ return -ENOTSUPP;
+
+ return 0;
+}
+
+static inline void ssc_sound_dai_remove(struct ssc_device *ssc)
+{
+}
+#endif
+
static int ssc_probe(struct platform_device *pdev)
{
struct resource *regs;
@@ -204,6 +249,9 @@ static int ssc_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n",
ssc->regs, ssc->irq);
+ if (ssc_sound_dai_probe(ssc))
+ dev_err(&pdev->dev, "failed to auto-setup ssc for audio\n");
+
return 0;
}
@@ -211,6 +259,8 @@ static int ssc_remove(struct platform_device *pdev)
{
struct ssc_device *ssc = platform_get_drvdata(pdev);
+ ssc_sound_dai_remove(ssc);
+
spin_lock(&user_lock);
list_del(&ssc->list);
spin_unlock(&user_lock);
diff --git a/include/linux/atmel-ssc.h b/include/linux/atmel-ssc.h
index 7c0f6549898b..fdb545101ede 100644
--- a/include/linux/atmel-ssc.h
+++ b/include/linux/atmel-ssc.h
@@ -20,6 +20,7 @@ struct ssc_device {
int user;
int irq;
bool clk_from_rk_pin;
+ bool sound_dai;
};
struct ssc_device * __must_check ssc_request(unsigned int ssc_num);
--
2.11.0
^ permalink raw reply related
* Applied "ASoC: atmel: tse850: rely on the ssc to register as a cpu dai by itself" to the asoc tree
From: Mark Brown @ 2016-12-15 12:20 UTC (permalink / raw)
To: Peter Rosin
Cc: Rob Herring, Mark Brown, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA,
alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw, Arnd Bergmann,
Greg Kroah-Hartman, Takashi Iwai, Nicolas Ferre, Liam Girdwood,
Rob Herring
In-Reply-To: <1481052157-23400-3-git-send-email-peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
The patch
ASoC: atmel: tse850: rely on the ssc to register as a cpu dai by itself
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From ca8c7f233fa2c40e2a23f982dc33d947f28ad207 Mon Sep 17 00:00:00 2001
From: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
Date: Tue, 6 Dec 2016 20:22:37 +0100
Subject: [PATCH] ASoC: atmel: tse850: rely on the ssc to register as a cpu dai
by itself
This breaks devicetree compatibility, but in this case that is ok. All
affected units are either on my desk, or running an even older version
of the driver that is not compatible with the upstreamed version anyway
(and when these other units are eventually updated, they will get a
fresh dtb as well, so that is not a significant problem either).
All of that is of course assuming that noone else has managed to build
something that can use this driver, but that seems extremely improbable.
Signed-off-by: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
.../bindings/sound/axentia,tse850-pcm5142.txt | 11 ++++++++---
sound/soc/atmel/tse850-pcm5142.c | 23 +++-------------------
2 files changed, 11 insertions(+), 23 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt b/Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt
index 5b9b38f578bb..fdb25b492514 100644
--- a/Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt
+++ b/Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt
@@ -2,8 +2,7 @@ Devicetree bindings for the Axentia TSE-850 audio complex
Required properties:
- compatible: "axentia,tse850-pcm5142"
- - axentia,ssc-controller: The phandle of the atmel SSC controller used as
- cpu dai.
+ - axentia,cpu-dai: The phandle of the cpu dai.
- axentia,audio-codec: The phandle of the PCM5142 codec.
- axentia,add-gpios: gpio specifier that controls the mixer.
- axentia,loop1-gpios: gpio specifier that controls loop relays on channel 1.
@@ -43,6 +42,12 @@ the PCM5142 codec.
Example:
+ &ssc0 {
+ #sound-dai-cells = <0>;
+
+ status = "okay";
+ };
+
&i2c {
codec: pcm5142@4c {
compatible = "ti,pcm5142";
@@ -77,7 +82,7 @@ Example:
sound {
compatible = "axentia,tse850-pcm5142";
- axentia,ssc-controller = <&ssc0>;
+ axentia,cpu-dai = <&ssc0>;
axentia,audio-codec = <&codec>;
axentia,add-gpios = <&pioA 8 GPIO_ACTIVE_LOW>;
diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c
index ac6a814c8ecf..a72c7d642026 100644
--- a/sound/soc/atmel/tse850-pcm5142.c
+++ b/sound/soc/atmel/tse850-pcm5142.c
@@ -51,11 +51,7 @@
#include <sound/soc.h>
#include <sound/pcm_params.h>
-#include "atmel_ssc_dai.h"
-
struct tse850_priv {
- int ssc_id;
-
struct gpio_desc *add;
struct gpio_desc *loop1;
struct gpio_desc *loop2;
@@ -329,23 +325,20 @@ static int tse850_dt_init(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *codec_np, *cpu_np;
- struct snd_soc_card *card = &tse850_card;
struct snd_soc_dai_link *dailink = &tse850_dailink;
- struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
if (!np) {
dev_err(&pdev->dev, "only device tree supported\n");
return -EINVAL;
}
- cpu_np = of_parse_phandle(np, "axentia,ssc-controller", 0);
+ cpu_np = of_parse_phandle(np, "axentia,cpu-dai", 0);
if (!cpu_np) {
- dev_err(&pdev->dev, "failed to get dai and pcm info\n");
+ dev_err(&pdev->dev, "failed to get cpu dai\n");
return -EINVAL;
}
dailink->cpu_of_node = cpu_np;
dailink->platform_of_node = cpu_np;
- tse850->ssc_id = of_alias_get_id(cpu_np, "ssc");
of_node_put(cpu_np);
codec_np = of_parse_phandle(np, "axentia,audio-codec", 0);
@@ -415,23 +408,14 @@ static int tse850_probe(struct platform_device *pdev)
return ret;
}
- ret = atmel_ssc_set_audio(tse850->ssc_id);
- if (ret != 0) {
- dev_err(dev,
- "failed to set SSC %d for audio\n", tse850->ssc_id);
- goto err_disable_ana;
- }
-
ret = snd_soc_register_card(card);
if (ret) {
dev_err(dev, "snd_soc_register_card failed\n");
- goto err_put_audio;
+ goto err_disable_ana;
}
return 0;
-err_put_audio:
- atmel_ssc_put_audio(tse850->ssc_id);
err_disable_ana:
regulator_disable(tse850->ana);
return ret;
@@ -443,7 +427,6 @@ static int tse850_remove(struct platform_device *pdev)
struct tse850_priv *tse850 = snd_soc_card_get_drvdata(card);
snd_soc_unregister_card(card);
- atmel_ssc_put_audio(tse850->ssc_id);
regulator_disable(tse850->ana);
return 0;
--
2.11.0
--
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
* Re: [RESEND PATCHv3 2/2] regulator: fixed: Handle optional overcurrent pin
From: Mark Brown @ 2016-12-15 12:19 UTC (permalink / raw)
To: Axel Haslam
Cc: lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, khilman-rdvid1DuHRBWk0Htik3J/w,
nsekhar-l0cyMroinI0, david-nq/r/kbU++upp/zk7JDF2g,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161215112856.9541-3-ahaslam-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 758 bytes --]
On Thu, Dec 15, 2016 at 12:28:56PM +0100, Axel Haslam wrote:
> + ret = devm_request_threaded_irq(&pdev->dev,
> + gpiod_to_irq(drvdata->oc_gpio), NULL,
> + reg_fixed_overcurrent_irq, irqflags,
> + "over_current", drvdata);
> drvdata->dev = devm_regulator_register(&pdev->dev, &drvdata->desc,
> &cfg);
We are registering a managed interrupt for the interrupt handler and we
are registering it before we register the regulator. This means that
the interrupt may fire in both probe and remove paths without the
regulator which it will then try to use in the interrupt handler,
potentially crashing the system. It's better to register the interrupt
after the regulator (which will make the managed bit OK) to avoid this
possibility.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH v2] ARM: dts: sunxi: Change node name for pwrseq pin on Olinuxino-lime2-emmc
From: Maxime Ripard @ 2016-12-15 12:17 UTC (permalink / raw)
To: Emmanuel Vadot
Cc: mark.rutland-5wv7dgnIgG8, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
wens-jdAy2FN1RRM, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20161215123533.f7e2373d2a9eb113ee7b0600-xXdDKFdH5B3kFDPD4ZthVA@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 1418 bytes --]
On Thu, Dec 15, 2016 at 12:35:33PM +0100, Emmanuel Vadot wrote:
>
> Hi Maxime,
>
> On Wed, 14 Dec 2016 16:30:13 +0100
> Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
>
> > On Wed, Dec 14, 2016 at 03:57:24PM +0100, Emmanuel Vadot wrote:
> > > The node name for the power seq pin is mmc2@0 like the mmc2_pins_a one.
> > > This makes the original node (mmc2_pins_a) scrapped out of the dtb and
> > > result in a unusable eMMC if U-Boot didn't configured the pins to the
> > > correct functions.
> > >
> > > Changes since v1:
> > > * Rename the node mmc2-rst-pin
> >
> > That changelog should be after the ---. Removed it and applied.
> >
> > Thanks!
> > Maxime
>
> Sorry, still kinda new at doing patches for Linux, will be more
> carefull next time.
> Quick question, when you say applied, applied where exactly ? I had a
> quick look at your branches on git.kernel.org didn't find anything.
In general, my tree on kernel.org.
In this case, my local tree for now. We're right in the middle of the
merge window for 4.10, so in order not to pollute next and not to
confuse everyone (or rebasing a branch at some point), I just gather
the patches here. I'll publish a branch based on 4.10 as soon as
4.10-rc1 is released.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH v3 1/2] ASoC: cs43130: Add support for CS43130 codec
From: Mark Brown @ 2016-12-15 12:12 UTC (permalink / raw)
To: Li Xu
Cc: alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
devicetree-u79uwXL29TY76Z2rM5mHXA,
lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, perex-/Fr2/VpizcU, tiwai-IBi9RG/b67k,
brian.austin-jGc1dHjMKG3QT0dZR+AlfA,
Paul.Handrigan-jGc1dHjMKG3QT0dZR+AlfA
In-Reply-To: <4c1d62fd-3bcf-4996-a942-bfcf6d7dce52-k7YZYYsDncjfk+Ne4bZl5AC/G2K4zDHf@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 19756 bytes --]
On Tue, Dec 13, 2016 at 11:47:06AM -0600, Li Xu wrote:
> + dev_dbg(codec->dev, "%s: cs43130->mclk = %d, cs43130->pll_out = %d",
> + __func__, cs43130->mclk, cs43130->pll_out);
If the standard style for logging output in the kernel were to include
the function name then dev_ would already do that. It isn't so they
don't - I think I also saw this affecting some of the non-debugging
messages.
> + if (cs43130->xtal_ibias > 0) {
> + usleep_range(1000, 1050);
> + /*PDN_XTAL = 0,enable*/
To repeat what I said last time:
| Please use the standard kernel coding style, need spaces here.
Please don't ignore review comments, people are generally making them
for a reason and are likely to have the same concerns if issues remain
unaddressed. Having to repeat the same comments can get repetitive and
make people question the value of time spent reviewing. If you disagree
with the review comments that's fine but you need to reply and discuss
your concerns so that the reviewer can understand your decisions.
> + regmap_update_bits(cs43130->regmap,
> + CS43130_PWDN_CTL,
> + CS43130_PDN_XTAL_MASK,
> + 0 << CS43130_PDN_XTAL_SHIFT);
> + }
> +
> + /* PLL_START = 0, disable PLL_START */
> + regmap_update_bits(cs43130->regmap,
> + CS43130_PLL_SET_1,
> + CS43130_PLL_START_MASK,
> + 0 << CS43130_PLL_START_MASK);
The indentation style here isn't consistent even between the two
adjacent function calls :( . The first one is more the normal coding
style for the kernel, keeping each row of arguments aligned.
I'm picking up a lot of coding style stuff here - it really is
important, people read as much by pattern matching as by reading
individual letters so it does make it harder for people and poor coding
style also tends to be a very good indicator that there's other problems
in the code with poor understanding of APIs and so on.
> + bitwidth = (cs43130->dai_bit+1)*8;
Coding style, use spaces.
> + SOC_SINGLE("Swap L/R", CS43130_PCM_PATH_CTL_2, 1, 1, 0),
> + SOC_SINGLE("Copy L/R", CS43130_PCM_PATH_CTL_2, 0, 1, 0),
These should really be DAPM muxes.
> + /* ASP_3ST = 0 in master mode */
> + if (cs43130->dai_mode)
> + regmap_update_bits(cs43130->regmap, CS43130_PAD_INT_CFG,
> + 0x01, 0x00);
Again, why do we never need to undo this? If we never need to undo it
why not just do it unconditionally on probe?
> + SND_SOC_DAPM_DAC_E("HiFi DAC",
> + NULL, CS43130_PWDN_CTL, CS43130_PDN_HP_SHIFT, 1,
> + cs43130_dac_event,
> + (SND_SOC_DAPM_PRE_PMD)
> + ),
Like I said last time:
| There's no need for the ); to be on a new line here, nor for the extra
| indentation on the line before. There are lots more coding style
| issues, checkpatch will probably pick up many of them.
You also don't need the brackets around the DAPM constants.
> + regmap_read(cs43130->regmap, CS43130_PCM_PATH_CTL_1, ®);
> + mute_reg = reg & 0xfc;
> + if (mute)
> + regmap_write(cs43130->regmap, CS43130_PCM_PATH_CTL_1,
> + mute_reg | 0x03);
> + else
> + regmap_write(cs43130->regmap, CS43130_PCM_PATH_CTL_1, mute_reg);
This looks like you're open coding regmap_update_bits().
> + if (freq_in < 9600000 || freq_in > 26000000) {
> + dev_err(codec->dev,
> + "unsupported pll input reference clock:%d\n", freq_in);
> + return -EINVAL;
> + }
> +
> + switch (freq_in) {
> + case 9600000:
> + case 11289600:
> + case 12000000:
> + case 12288000:
> + case 13000000:
> + case 19200000:
> + case 22579200:
> + case 24000000:
> + case 24576000:
> + case 26000000:
> + cs43130->mclk = freq_in;
> + break;
> + default:
> + dev_err(codec->dev,
> + "unsupported pll input reference clock:%d\n", freq_in);
> + return -EINVAL;
> + }
You've got both a range check and a list of explicit supported
frequencies here - surely the range check is redundant?
> + /* Read all INT status and mask reg */
> + regmap_bulk_read(cs43130->regmap, CS43130_INT_STATUS_1,
> + stickies, CS43130_NUM_INT * sizeof(unsigned int));
> + regmap_bulk_read(cs43130->regmap, CS43130_INT_MASK_1,
> + masks, CS43130_NUM_INT * sizeof(unsigned int));
These are going to be buffer overflows, regmap bulk_read() takes a
number of registers to read not a number of bytes.
> + default:
> + dev_info(&i2c_client->dev,
> + "cirrus,xtal-ibias value or xtal unused %d",
> + val);
> + }
Missing break and this should be an error.
> + /* Enable interrupt handler */
> + ret = devm_request_threaded_irq(&client->dev,
> + client->irq,
> + NULL, cs43130_irq_thread,
> + IRQF_ONESHOT | IRQF_TRIGGER_LOW,
> + "cs43130", cs43130);
> + if (ret != 0) {
> + dev_err(&client->dev, "Failed to request IRQ: %d\n", ret);
> + return ret;
> + }
> +
> + /* Unmask INT */
> + regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1,
> + CS43130_XTAL_RDY_INT | CS43130_XTAL_ERR_INT, 0);
We don't mask the interrupts when removing the driver. This means the
interrupt could fire as the device is being unbound which might crash
since the interrupt handler will still be registered as you're using
devm_ here. It's generally better not to use devm_ for interrupts, it's
hard to get right.
> + pm_runtime_disable(&client->dev);
We never enabled runtime PM.
> + regulator_bulk_disable(CS43130_NUM_SUPPLIES,
> + cs43130->supplies);
The indentation of the second line here is weird - normally it'd be
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int cs43130_runtime_suspend(struct device *dev)
> +{
> + struct cs43130_private *cs43130 = dev_get_drvdata(dev);
> +
> + regcache_cache_only(cs43130->regmap, true);
> + regcache_mark_dirty(cs43130->regmap);
> +
> + gpiod_set_value_cansleep(cs43130->reset_gpio, 0);
> +
> + regulator_bulk_disable(CS43130_NUM_SUPPLIES,
> + cs43130->supplies);
> + return 0;
> +}
> +
> +static int cs43130_runtime_resume(struct device *dev)
> +{
> + struct cs43130_private *cs43130 = dev_get_drvdata(dev);
> + int ret;
> +
> + ret = regulator_bulk_enable(CS43130_NUM_SUPPLIES,
> + cs43130->supplies);
> + if (ret != 0) {
> + dev_err(dev, "Failed to enable supplies: %d\n",
> + ret);
> + return ret;
> + }
> +
> + regcache_cache_only(cs43130->regmap, false);
> +
> + gpiod_set_value_cansleep(cs43130->reset_gpio, 1);
> +
> + usleep_range(2000, 2050);
> +
> + ret = regcache_sync(cs43130->regmap);
> + if (ret != 0) {
> + dev_err(dev, "Failed to restore register cache\n");
> + goto err;
> + }
> + return 0;
> +err:
> + regcache_cache_only(cs43130->regmap, true);
> + regulator_bulk_disable(CS43130_NUM_SUPPLIES,
> + cs43130->supplies);
> +
> + return ret;
> +}
> +#endif
> +
> +static const struct dev_pm_ops cs43130_runtime_pm = {
> + SET_RUNTIME_PM_OPS(cs43130_runtime_suspend, cs43130_runtime_resume,
> + NULL)
> +};
> +
> +static const struct of_device_id cs43130_of_match[] = {
> + { .compatible = "cirrus,cs43130", },
> + {},
> +};
> +
> +MODULE_DEVICE_TABLE(of, cs43130_of_match);
> +
> +static const struct i2c_device_id cs43130_i2c_id[] = {
> + {"cs43130", 0},
> + {}
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, cs43130_i2c_id);
> +
> +static struct i2c_driver cs43130_i2c_driver = {
> + .driver = {
> + .name = "cs43130",
> + .of_match_table = cs43130_of_match,
> + },
> + .id_table = cs43130_i2c_id,
> + .probe = cs43130_i2c_probe,
> + .remove = cs43130_i2c_remove,
> +};
> +
> +module_i2c_driver(cs43130_i2c_driver);
> +
> +MODULE_AUTHOR("Li Xu <li.xu-jGc1dHjMKG3QT0dZR+AlfA@public.gmane.org>");
> +MODULE_DESCRIPTION("Cirrus Logic CS43130 ALSA SoC Codec Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/sound/soc/codecs/cs43130.h b/sound/soc/codecs/cs43130.h
> new file mode 100644
> index 0000000..bceae76
> --- /dev/null
> +++ b/sound/soc/codecs/cs43130.h
> @@ -0,0 +1,268 @@
> +/*
> + * ALSA SoC CS43130 codec driver
> + *
> + * Copyright 2016 Cirrus Logic, Inc.
> + *
> + * Author: Li Xu <li.xu-jGc1dHjMKG3QT0dZR+AlfA@public.gmane.org>
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef __CS43130_H__
> +#define __CS43130_H__
> +
> +/* CS43130 registers addresses */
> +/* all reg address is shifted by a byte for control byte to be LSB */
> +#define CS43130_FIRSTREG 0x010000
> +#define CS43130_LASTREG 0x0F0014
> +#define CS43130_CHIP_ID 0x00043130
> +#define CS4399_CHIP_ID 0x00043990
> +#define CS43130_DEVID_AB 0x010000 /*Device ID A & B [RO]*/
> +#define CS43130_DEVID_CD 0x010001 /*Device ID C & D [RO]*/
> +#define CS43130_DEVID_E 0x010002 /*Device ID E [RO]*/
> +#define CS43130_FAB_ID 0x010003 /*Fab ID [RO]*/
> +#define CS43130_REV_ID 0x010004 /*Revision ID [RO]*/
> +#define CS43130_SUBREV_ID 0x010005 /*Subrevision ID*/
> +#define CS43130_SYS_CLK_CTL_1 0x010006 /*System Clocking Ctl 1*/
> +#define CS43130_SP_SRATE 0x01000B /*Serial Port Sample Rate*/
> +#define CS43130_SP_BITSIZE 0x01000C /*Serial Port Bit Size*/
> +#define CS43130_PAD_INT_CFG 0x01000D /*Pad Interface Config*/
> +#define CS43130_DXD1 0x010010 /*DXD1*/
> +#define CS43130_PWDN_CTL 0x020000 /*Power Down Ctl*/
> +#define CS43130_DXD2 0x020019 /*DXD2*/
> +#define CS43130_CRYSTAL_SET 0x020052 /*Crystal Setting*/
> +#define CS43130_PLL_SET_1 0x030001 /*PLL Setting 1*/
> +#define CS43130_PLL_SET_2 0x030002 /*PLL Setting 2*/
> +#define CS43130_PLL_SET_3 0x030003 /*PLL Setting 3*/
> +#define CS43130_PLL_SET_4 0x030004 /*PLL Setting 4*/
> +#define CS43130_PLL_SET_5 0x030005 /*PLL Setting 5*/
> +#define CS43130_PLL_SET_6 0x030008 /*PLL Setting 6*/
> +#define CS43130_PLL_SET_7 0x03000A /*PLL Setting 7*/
> +#define CS43130_PLL_SET_8 0x03001B /*PLL Setting 8*/
> +#define CS43130_PLL_SET_9 0x040002 /*PLL Setting 9*/
> +#define CS43130_PLL_SET_10 0x040003 /*PLL Setting 10*/
> +#define CS43130_CLKOUT_CTL 0x040004 /*CLKOUT Ctl*/
> +#define CS43130_ASP_NUM_1 0x040010 /*ASP Numerator 1*/
> +#define CS43130_ASP_NUM_2 0x040011 /*ASP Numerator 2*/
> +#define CS43130_ASP_DENOM_1 0x040012 /*ASP Denominator 1*/
> +#define CS43130_ASP_DENOM_2 0x040013 /*ASP Denominator 2*/
> +#define CS43130_ASP_LRCK_HI_TIME_1 0x040014 /*ASP LRCK High Time 1*/
> +#define CS43130_ASP_LRCK_HI_TIME_2 0x040015 /*ASP LRCK High Time 2*/
> +#define CS43130_ASP_LRCK_PERIOD_1 0x040016 /*ASP LRCK Period 1*/
> +#define CS43130_ASP_LRCK_PERIOD_2 0x040017 /*ASP LRCK Period 2*/
> +#define CS43130_ASP_CLOCK_CONF 0x040018 /*ASP Clock Config*/
> +#define CS43130_ASP_FRAME_CONF 0x040019 /*ASP Frame Config*/
> +#define CS43130_XSP_NUM_1 0x040020 /*XSP Numerator 1*/
> +#define CS43130_XSP_NUM_2 0x040021 /*XSP Numerator 2*/
> +#define CS43130_XSP_DENOM_1 0x040022 /*XSP Denominator 1*/
> +#define CS43130_XSP_DENOM_2 0x040023 /*XSP Denominator 2*/
> +#define CS43130_XSP_LRCK_HI_TIME_1 0x040024 /*XSP LRCK High Time 1*/
> +#define CS43130_XSP_LRCK_HI_TIME_2 0x040025 /*XSP LRCK High Time 2*/
> +#define CS43130_XSP_LRCK_PERIOD_1 0x040026 /*XSP LRCK Period 1*/
> +#define CS43130_XSP_LRCK_PERIOD_2 0x040027 /*XSP LRCK Period 2*/
> +#define CS43130_XSP_CLOCK_CONF 0x040028 /*XSP Clock Config*/
> +#define CS43130_XSP_FRAME_CONF 0x040029 /*XSP Frame Config*/
> +#define CS43130_ASP_CH_1_LOC 0x050000 /*ASP Chan 1 Location*/
> +#define CS43130_ASP_CH_2_LOC 0x050001 /*ASP Chan 2 Location*/
> +#define CS43130_ASP_CH_1_SZ_EN 0x05000A /*ASP Chan 1 Size, Enable*/
> +#define CS43130_ASP_CH_2_SZ_EN 0x05000B /*ASP Chan 2 Size, Enable*/
> +#define CS43130_XSP_CH_1_LOC 0x060000 /*XSP Chan 1 Location*/
> +#define CS43130_XSP_CH_2_LOC 0x060001 /*XSP Chan 2 Location*/
> +#define CS43130_XSP_CH_1_SZ_EN 0x06000A /*XSP Chan 1 Size, Enable*/
> +#define CS43130_XSP_CH_2_SZ_EN 0x06000B /*XSP Chan 2 Size, Enable*/
> +#define CS43130_DSD_VOL_B 0x070000 /*DSD Volume B*/
> +#define CS43130_DSD_VOL_A 0x070001 /*DSD Volume A*/
> +#define CS43130_DSD_PATH_CTL_1 0x070002 /*DSD Proc Path Sig Ctl 1*/
> +#define CS43130_DSD_INT_CFG 0x070003 /*DSD Interface Config*/
> +#define CS43130_DSD_PATH_CTL_2 0x070004 /*DSD Proc Path Sig Ctl 2*/
> +#define CS43130_DSD_PCM_MIX_CTL 0x070005 /*DSD and PCM Mixing Ctl*/
> +#define CS43130_DSD_PATH_CTL_3 0x070006 /*DSD Proc Path Sig Ctl 3*/
> +#define CS43130_HP_OUT_CTL_1 0x080000 /*HP Output Ctl 1*/
> +#define CS43130_PCM_FILT_OPT 0x090000 /*PCM Filter Option*/
> +#define CS43130_PCM_VOL_B 0x090001 /*PCM Volume B*/
> +#define CS43130_PCM_VOL_A 0x090002 /*PCM Volume A*/
> +#define CS43130_PCM_PATH_CTL_1 0x090003 /*PCM Path Signal Ctl 1*/
> +#define CS43130_PCM_PATH_CTL_2 0x090004 /*PCM Path Signal Ctl 2*/
> +#define CS43130_CLASS_H_CTL 0x0B0000 /*Class H Ctl*/
> +#define CS43130_HP_DETECT 0x0D0000 /*HP Detect*/
> +#define CS43130_HP_STATUS 0x0D0001 /*HP Status [RO]*/
> +#define CS43130_HP_LOAD_1 0x0E0000 /*HP Load 1*/
> +#define CS43130_HP_MEAS_LOAD_1 0x0E0003 /*HP Load Measurement 1*/
> +#define CS43130_HP_MEAS_LOAD_2 0x0E0004 /*HP Load Measurement 2*/
> +#define CS43130_HP_DC_STAT_1 0x0E000D /*HP DC Load Status 0 [RO]*/
> +#define CS43130_HP_DC_STAT_2 0x0E000E /*HP DC Load Status 1 [RO]*/
> +#define CS43130_HP_AC_STAT_1 0x0E0010 /*HP AC Load Status 0 [RO]*/
> +#define CS43130_HP_AC_STAT_2 0x0E0011 /*HP AC Load Status 1 [RO]*/
> +#define CS43130_HP_LOAD_STAT 0x0E001A /*HP Load Status [RO]*/
> +#define CS43130_INT_STATUS_1 0x0F0000 /*Interrupt Status 1*/
> +#define CS43130_INT_STATUS_2 0x0F0001 /*Interrupt Status 2*/
> +#define CS43130_INT_STATUS_3 0x0F0002 /*Interrupt Status 3*/
> +#define CS43130_INT_STATUS_4 0x0F0003 /*Interrupt Status 4*/
> +#define CS43130_INT_STATUS_5 0x0F0004 /*Interrupt Status 5*/
> +#define CS43130_INT_MASK_1 0x0F0010 /*Interrupt Mask 1*/
> +#define CS43130_INT_MASK_2 0x0F0011 /*Interrupt Mask 2*/
> +#define CS43130_INT_MASK_3 0x0F0012 /*Interrupt Mask 3*/
> +#define CS43130_INT_MASK_4 0x0F0013 /*Interrupt Mask 4*/
> +#define CS43130_INT_MASK_5 0x0F0014 /*Interrupt Mask 5*/
> +
> +#define CS43130_MCLK_SRC_SEL_MASK 0x03
> +#define CS43130_MCLK_SRC_SEL_SHIFT 0
> +#define CS43130_MCLK_INT_MASK 0x04
> +#define CS43130_MCLK_INT_SHIFT 2
> +#define CS43130_SP_SRATE_MASK 0x0F
> +#define CS43130_SP_SRATE_SHIFT 0
> +#define CS43130_SP_BITSIZE_ASP_MASK 0x03
> +#define CS43130_SP_BITSIZE_ASP_SHIFT 0
> +#define CS43130_HP_DETECT_CTRL_SHIFT 6
> +#define CS43130_HP_DETECT_CTRL_MASK (0x03 << CS43130_HP_DETECT_CTRL_SHIFT)
> +#define CS43130_HP_DETECT_INV_SHIFT 5
> +#define CS43130_HP_DETECT_INV_MASK (1 << CS43130_HP_DETECT_INV_SHIFT)
> +
> +/* CS43130_INT_MASK_1 */
> +#define CS43130_HP_PLUG_INT_SHIFT 6
> +#define CS43130_HP_PLUG_INT (1 << CS43130_HP_PLUG_INT_SHIFT)
> +#define CS43130_HP_UNPLUG_INT_SHIFT 5
> +#define CS43130_HP_UNPLUG_INT (1 << CS43130_HP_UNPLUG_INT_SHIFT)
> +#define CS43130_XTAL_RDY_INT_SHIFT 4
> +#define CS43130_XTAL_RDY_INT (1 << CS43130_XTAL_RDY_INT_SHIFT)
> +#define CS43130_XTAL_ERR_INT_SHIFT 3
> +#define CS43130_XTAL_ERR_INT (1 << CS43130_XTAL_ERR_INT_SHIFT)
> +
> +/*Reg CS43130_SP_BITSIZE*/
> +#define CS43130_SP_BIT_SIZE_8 0x00
> +#define CS43130_SP_BIT_SIZE_16 0x01
> +#define CS43130_SP_BIT_SIZE_24 0x02
> +#define CS43130_SP_BIT_SIZE_32 0x03
> +
> +/*PLL*/
> +#define CS43130_PLL_START_MASK (0x1<<0)
> +#define CS43130_PLL_MODE_MASK 0x02
> +#define CS43130_PLL_MODE_SHIFT 1
> +
> +#define CS43130_PLL_REF_PREDIV_MASK 0x3
> +
> +#define CS43130_ASP_STP_MASK 0x10
> +#define CS43130_ASP_STP_SHIFT 4
> +#define CS43130_ASP_5050_MASK 0x08
> +#define CS43130_ASP_5050_SHIFT 3
> +#define CS43130_ASP_FSD_MASK 0x07
> +#define CS43130_ASP_FSD_SHIFT 0
> +
> +#define CS43130_ASP_MODE_MASK 0x10
> +#define CS43130_ASP_MODE_SHIFT 4
> +#define CS43130_ASP_SCPOL_OUT_MASK 0x08
> +#define CS43130_ASP_SCPOL_OUT_SHIFT 3
> +#define CS43130_ASP_SCPOL_IN_MASK 0x04
> +#define CS43130_ASP_SCPOL_IN_SHIFT 2
> +#define CS43130_ASP_LCPOL_OUT_MASK 0x02
> +#define CS43130_ASP_LCPOL_OUT_SHIFT 1
> +#define CS43130_ASP_LCPOL_IN_MASK 0x01
> +#define CS43130_ASP_LCPOL_IN_SHIFT 0
> +
> +/*Reg CS43130_PWDN_CTL*/
> +#define CS43130_PDN_XSP_MASK 0x80
> +#define CS43130_PDN_XSP_SHIFT 7
> +#define CS43130_PDN_ASP_MASK 0x40
> +#define CS43130_PDN_ASP_SHIFT 6
> +#define CS43130_PDN_DSPIF_MASK 0x20
> +#define CS43130_PDN_DSDIF_SHIFT 5
> +#define CS43130_PDN_HP_MASK 0x10
> +#define CS43130_PDN_HP_SHIFT 4
> +#define CS43130_PDN_XTAL_MASK 0x08
> +#define CS43130_PDN_XTAL_SHIFT 3
> +#define CS43130_PDN_PLL_MASK 0x04
> +#define CS43130_PDN_PLL_SHIFT 2
> +#define CS43130_PDN_CLKOUT_MASK 0x02
> +#define CS43130_PDN_CLKOUT_SHIFT 1
> +
> +#define CS43130_7_0_MASK 0xFF
> +#define CS43130_15_8_MASK 0xFF00
> +#define CS43130_23_16_MASK 0xFF0000
> +
> +/* Reg CS43130_HP_OUT_CTL_1 */
> +#define CS43130_HP_IN_EN_SHIFT 3
> +#define CS43130_HP_IN_EN_MASK 0x08
> +
> +#define CS43130_ASP_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
> + SNDRV_PCM_FMTBIT_S16_LE | \
> + SNDRV_PCM_FMTBIT_S24_LE | \
> + SNDRV_PCM_FMTBIT_S32_LE)
> +
> +#define CS43130_XSP_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \
> + SNDRV_PCM_FMTBIT_S32_LE)
> +
> +enum cs43130_asp_rate {
> + CS43130_ASP_SPRATE_32K = 0,
> + CS43130_ASP_SPRATE_44_1K,
> + CS43130_ASP_SPRATE_48K,
> + CS43130_ASP_SPRATE_88_2K,
> + CS43130_ASP_SPRATE_96K,
> + CS43130_ASP_SPRATE_176_4K,
> + CS43130_ASP_SPRATE_192K,
> + CS43130_ASP_SPRATE_352_8K,
> + CS43130_ASP_SPRATE_384K,
> +};
> +
> +enum cs43130_mclk_src_sel {
> + CS43130_MCLK_SRC_XTAL = 0,
> + CS43130_MCLK_SRC_PLL,
> + CS43130_MCLK_SRC_RCO
> +};
> +
> +enum cs43130_mode {
> + CS43130_SLAVE_MODE = 0,
> + CS43130_MASTER_MODE
> +};
> +
> +enum cs43130_xtal_ibias {
> + CS43130_XTAL_IBIAS_15UA = 2,
> + CS43130_XTAL_IBIAS_12_5UA = 4,
> + CS43130_XTAL_IBIAS_7_5UA = 6,
> +};
> +
> +#define CS43130_AIF_BICK_RATE 1
> +#define CS43130_SYSCLK_MCLK 1
> +#define CS43130_NUM_SUPPLIES 5
> +static const char *const cs43130_supply_names[CS43130_NUM_SUPPLIES] = {
> + "VA",
> + "VP",
> + "VCP",
> + "VD",
> + "VL",
> +};
> +
> +#define CS43130_NUM_INT 5 /* number of interrupt status reg */
> +
> +struct cs43130_private {
> + struct snd_soc_codec *codec;
> + struct regmap *regmap;
> + struct regulator_bulk_data supplies[CS43130_NUM_SUPPLIES];
> + /* codec device ID */
> + unsigned int dev_id;
> + int mclk;
> + int sclk;
> + int xtal_ibias;
> +
> + bool pll_bypass;
> + int pll_out;
> + int mclk_int;
> + int dai_format;
> + int dai_mode;
> + int dai_bit;
> + int asp_size;
> + int fs;
> + bool bick_invert;
> + bool lrck_invert;
> + int bick;
> + struct gpio_desc *reset_gpio;
> +};
> +
> +#endif /* __CS43130_H__ */
> --
> 1.9.1
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH v2] ARM: dts: Add missing CPU frequencies for Exynos5422/5800
From: Bartlomiej Zolnierkiewicz @ 2016-12-15 11:55 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Kukjin Kim, Javier Martinez Canillas, Rob Herring, Mark Rutland,
Russell King, Doug Anderson, Andreas Faerber, Thomas Abraham,
Ben Gamari, Arjun K V, linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-pm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Add missing 2000MHz & 1900MHz OPPs (for A15 cores) and 1400MHz OPP
(for A7 cores). Also update common Odroid-XU3 Lite/XU3/XU4 thermal
cooling maps to account for new OPPs.
Since new OPPs are not available on all Exynos5422/5800 boards modify
dts files for Odroid-XU3 Lite (limited to 1.8 GHz / 1.3 GHz) & Peach
Pi (limited to 2.0 GHz / 1.3 GHz) accordingly.
Tested on Odroid-XU3 and XU3 Lite.
Cc: Doug Anderson <dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Cc: Javier Martinez Canillas <javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
Cc: Andreas Faerber <afaerber-l3A5Bk7waGM@public.gmane.org>
Cc: Thomas Abraham <thomas.ab-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Cc: Ben Gamari <ben-OfdNVJEh3GKkIYD+M5K+dQ@public.gmane.org>
Cc: Arjun K V <arjun.kv-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
---
v2:
- added comments about limitations of SoC revisions used by Odroid-XU3 Lite and
Peach Pi boards (suggested by Javier)
- removed redundant opp_a7_14 label
- added Arjun to Cc:
Javier, could you test it on Peach Pi board?
arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi | 14 ++++++-------
arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts | 22 +++++++++++++++++++++
arch/arm/boot/dts/exynos5800-peach-pi.dts | 9 ++++++++
arch/arm/boot/dts/exynos5800.dtsi | 15 ++++++++++++++
4 files changed, 53 insertions(+), 7 deletions(-)
Index: b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
===================================================================
--- a/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi 2016-12-15 12:43:54.365955950 +0100
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi 2016-12-15 12:43:54.361955949 +0100
@@ -118,7 +118,7 @@
/*
* When reaching cpu_alert3, reduce CPU
* by 2 steps. On Exynos5422/5800 that would
- * be: 1600 MHz and 1100 MHz.
+ * (usually) be: 1800 MHz and 1200 MHz.
*/
map3 {
trip = <&cpu_alert3>;
@@ -131,16 +131,16 @@
/*
* When reaching cpu_alert4, reduce CPU
- * further, down to 600 MHz (11 steps for big,
- * 7 steps for LITTLE).
+ * further, down to 600 MHz (13 steps for big,
+ * 8 steps for LITTLE).
*/
- map5 {
+ cooling_map5: map5 {
trip = <&cpu_alert4>;
- cooling-device = <&cpu0 3 7>;
+ cooling-device = <&cpu0 3 8>;
};
- map6 {
+ cooling_map6: map6 {
trip = <&cpu_alert4>;
- cooling-device = <&cpu4 3 11>;
+ cooling-device = <&cpu4 3 13>;
};
};
};
Index: b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts
===================================================================
--- a/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts 2016-12-15 12:43:54.365955950 +0100
+++ b/arch/arm/boot/dts/exynos5422-odroidxu3-lite.dts 2016-12-15 12:43:54.361955949 +0100
@@ -21,6 +21,28 @@
compatible = "hardkernel,odroid-xu3-lite", "samsung,exynos5800", "samsung,exynos5";
};
+/*
+ * Odroid XU3-Lite board uses SoC revision with lower maximum frequencies
+ * than Odroid XU3/XU4 boards: 1.8 GHz for A15 cores & 1.3 GHz for A7 cores.
+ * Therefore we need to update OPPs tables and thermal maps accordingly.
+ */
+&cluster_a15_opp_table {
+ /delete-node/opp@2000000000;
+ /delete-node/opp@1900000000;
+};
+
+&cluster_a7_opp_table {
+ /delete-node/opp@1400000000;
+};
+
+&cooling_map5 {
+ cooling-device = <&cpu0 3 7>;
+};
+
+&cooling_map6 {
+ cooling-device = <&cpu4 3 11>;
+};
+
&pwm {
/*
* PWM 0 -- fan
Index: b/arch/arm/boot/dts/exynos5800-peach-pi.dts
===================================================================
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts 2016-12-15 12:43:54.365955950 +0100
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts 2016-12-15 12:43:54.361955949 +0100
@@ -146,6 +146,15 @@
vdd-supply = <&ldo9_reg>;
};
+/*
+ * Peach Pi board uses SoC revision with lower maximum frequency for A7 cores
+ * (1.3 GHz instead of 1.4 GHz) than Odroid XU3/XU4 boards. Thus we need to
+ * update A7 OPPs table accordingly.
+ */
+&cluster_a7_opp_table {
+ /delete-property/opp@1400000000;
+};
+
&cpu0 {
cpu-supply = <&buck2_reg>;
};
Index: b/arch/arm/boot/dts/exynos5800.dtsi
===================================================================
--- a/arch/arm/boot/dts/exynos5800.dtsi 2016-12-15 12:43:54.365955950 +0100
+++ b/arch/arm/boot/dts/exynos5800.dtsi 2016-12-15 12:43:54.361955949 +0100
@@ -24,6 +24,16 @@
};
&cluster_a15_opp_table {
+ opp@2000000000 {
+ opp-hz = /bits/ 64 <2000000000>;
+ opp-microvolt = <1250000>;
+ clock-latency-ns = <140000>;
+ };
+ opp@1900000000 {
+ opp-hz = /bits/ 64 <1900000000>;
+ opp-microvolt = <1250000>;
+ clock-latency-ns = <140000>;
+ };
opp@1700000000 {
opp-microvolt = <1250000>;
};
@@ -85,6 +95,11 @@
};
&cluster_a7_opp_table {
+ opp@1400000000 {
+ opp-hz = /bits/ 64 <1400000000>;
+ opp-microvolt = <1250000>;
+ clock-latency-ns = <140000>;
+ };
opp@1300000000 {
opp-microvolt = <1250000>;
};
--
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] ARM: dts: sunxi: Change node name for pwrseq pin on Olinuxino-lime2-emmc
From: Emmanuel Vadot @ 2016-12-15 11:35 UTC (permalink / raw)
To: Maxime Ripard
Cc: mark.rutland, devicetree, linux, linux-kernel, wens, robh+dt,
linux-arm-kernel
In-Reply-To: <20161214153013.bkdm3pu3osepfnn2@lukather>
Hi Maxime,
On Wed, 14 Dec 2016 16:30:13 +0100
Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
> On Wed, Dec 14, 2016 at 03:57:24PM +0100, Emmanuel Vadot wrote:
> > The node name for the power seq pin is mmc2@0 like the mmc2_pins_a one.
> > This makes the original node (mmc2_pins_a) scrapped out of the dtb and
> > result in a unusable eMMC if U-Boot didn't configured the pins to the
> > correct functions.
> >
> > Changes since v1:
> > * Rename the node mmc2-rst-pin
>
> That changelog should be after the ---. Removed it and applied.
>
> Thanks!
> Maxime
Sorry, still kinda new at doing patches for Linux, will be more
carefull next time.
Quick question, when you say applied, applied where exactly ? I had a
quick look at your branches on git.kernel.org didn't find anything.
Thanks.
--
Emmanuel Vadot <manu@bidouilliste.com> <manu@freebsd.org>
^ permalink raw reply
* [RESEND PATCHv3 2/2] regulator: fixed: Handle optional overcurrent pin
From: Axel Haslam @ 2016-12-15 11:28 UTC (permalink / raw)
To: broonie-DgEjT+Ai2ygdnm+yROfE0A, lgirdwood-Re5JQEeQqe8AvxtiuMwx3w,
khilman-rdvid1DuHRBWk0Htik3J/w, nsekhar-l0cyMroinI0,
david-nq/r/kbU++upp/zk7JDF2g, robh+dt-DgEjT+Ai2ygdnm+yROfE0A
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Axel Haslam
In-Reply-To: <20161215112856.9541-1-ahaslam-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
Fixed regulators (ex. TPS2087D) may have a over current pin that
is activated on over current. Consumers may be interested to know
about over current events to take appropriate actions.
Allow the fix regulator to take in an optional gpio pin for over
current and send the respective event to the consumer.
Signed-off-by: Axel Haslam <ahaslam-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
---
drivers/regulator/fixed.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index a43b0e8..06ed2f6 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -33,10 +33,12 @@
#include <linux/acpi.h>
#include <linux/property.h>
#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
struct fixed_voltage_data {
struct regulator_desc desc;
struct regulator_dev *dev;
+ struct gpio_desc *oc_gpio;
};
@@ -135,7 +137,36 @@ acpi_get_fixed_voltage_config(struct device *dev,
return config;
}
+static irqreturn_t reg_fixed_overcurrent_irq(int irq, void *data)
+{
+ struct fixed_voltage_data *drvdata = data;
+
+ regulator_notifier_call_chain(drvdata->dev,
+ REGULATOR_EVENT_OVER_CURRENT, NULL);
+
+ return IRQ_HANDLED;
+}
+
+static int reg_fixed_get_error_flags(struct regulator_dev *dev,
+ unsigned int *flags)
+{
+ struct fixed_voltage_data *drvdata = rdev_get_drvdata(dev);
+ int oc_value;
+
+ *flags = 0;
+
+ if (!drvdata->oc_gpio)
+ return 0;
+
+ oc_value = gpiod_get_value_cansleep(drvdata->oc_gpio);
+ if (oc_value)
+ *flags = REGULATOR_ERROR_OVER_CURRENT;
+
+ return 0;
+}
+
static struct regulator_ops fixed_voltage_ops = {
+ .get_error_flags = reg_fixed_get_error_flags,
};
static int reg_fixed_voltage_probe(struct platform_device *pdev)
@@ -143,6 +174,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
struct fixed_voltage_config *config;
struct fixed_voltage_data *drvdata;
struct regulator_config cfg = { };
+ unsigned long irqflags = IRQF_ONESHOT;
int ret;
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
@@ -221,6 +253,33 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
cfg.driver_data = drvdata;
cfg.of_node = pdev->dev.of_node;
+
+ drvdata->oc_gpio = devm_gpiod_get_optional(&pdev->dev, "over-current",
+ GPIOF_DIR_IN);
+ if (IS_ERR(drvdata->oc_gpio)) {
+ ret = PTR_ERR(drvdata->oc_gpio);
+ dev_err(&pdev->dev,
+ "Failed to get over current gpio: %d\n", ret);
+ return ret;
+ }
+
+ if (drvdata->oc_gpio) {
+ if (gpiod_is_active_low(drvdata->oc_gpio))
+ irqflags |= IRQF_TRIGGER_FALLING;
+ else
+ irqflags |= IRQF_TRIGGER_RISING;
+
+ ret = devm_request_threaded_irq(&pdev->dev,
+ gpiod_to_irq(drvdata->oc_gpio), NULL,
+ reg_fixed_overcurrent_irq, irqflags,
+ "over_current", drvdata);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to request irq: %d\n", ret);
+ return ret;
+ }
+ }
+
drvdata->dev = devm_regulator_register(&pdev->dev, &drvdata->desc,
&cfg);
if (IS_ERR(drvdata->dev)) {
--
2.9.3
--
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
* [RESEND PATCHv3 1/2] regulator: fixed: dt: Allow an optional over current pin
From: Axel Haslam @ 2016-12-15 11:28 UTC (permalink / raw)
To: broonie-DgEjT+Ai2ygdnm+yROfE0A, lgirdwood-Re5JQEeQqe8AvxtiuMwx3w,
khilman-rdvid1DuHRBWk0Htik3J/w, nsekhar-l0cyMroinI0,
david-nq/r/kbU++upp/zk7JDF2g, robh+dt-DgEjT+Ai2ygdnm+yROfE0A
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Axel Haslam
In-Reply-To: <20161215112856.9541-1-ahaslam-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
Add support for an optional over current input pin which
can be used to send an over current event to the regulator
consumer.
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Signed-off-by: Axel Haslam <ahaslam-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
---
Documentation/devicetree/bindings/regulator/fixed-regulator.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt
index 4fae41d..b145abb 100644
--- a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt
@@ -11,6 +11,7 @@ If this property is missing, the default assumed is Active low.
- gpio-open-drain: GPIO is open drain type.
If this property is missing then default assumption is false.
-vin-supply: Input supply name.
+- over-current-gpios: Input gpio that signal an over current condition.
Any property defined as part of the core regulator
binding, defined in regulator.txt, can also be used.
@@ -26,6 +27,7 @@ Example:
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
gpio = <&gpio1 16 0>;
+ over-current-gpios = <&gpio1 18 0>;
startup-delay-us = <70000>;
enable-active-high;
regulator-boot-on;
--
2.9.3
--
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
* [RESEND PATCHv3 0/2] regulator: handling of error conditions for usb drivers
From: Axel Haslam @ 2016-12-15 11:28 UTC (permalink / raw)
To: broonie-DgEjT+Ai2ygdnm+yROfE0A, lgirdwood-Re5JQEeQqe8AvxtiuMwx3w,
khilman-rdvid1DuHRBWk0Htik3J/w, nsekhar-l0cyMroinI0,
david-nq/r/kbU++upp/zk7JDF2g, robh+dt-DgEjT+Ai2ygdnm+yROfE0A
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Axel Haslam
Some usb drivers rely on external power switches/regulators
for the port vbus, and some of these drivers are still using
a plain gpio to control the enable and over current
indicator pins.
To make these drivers more generic, we can use a regulator
to handle vbus, and send and over current event, but we are
missing a way to transmit the over current pin status, which
the usb layer may poll at any time.
These patches extend the fixed regulator driver to handle an optional
over current gpio pin.
Changes v3 -> 3.1
* added Acked-by for DT bindings
Changes v2 -> v3
* dropped merged patch to add new API
* rebased on top of regulator-next
Changes v1->v2
* add new API to get error status instead of extending events (Mark)
* use gpiod for fixed regulator: This spears us extra platform
data and bindings
Axel Haslam (2):
regulator: fixed: dt: Allow an optional over current pin
regulator: fixed: Handle optional overcurrent pin
.../bindings/regulator/fixed-regulator.txt | 2 +
drivers/regulator/fixed.c | 59 ++++++++++++++++++++++
2 files changed, 61 insertions(+)
--
2.9.3
--
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 2/2] xilinx_dma: Add reset support
From: Ramiro Oliveira @ 2016-12-15 11:26 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Ramiro Oliveira, dmaengine-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
vinod.koul-ral2JQCrhuEAvxtiuMwx3w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, michal.simek-gjFFaj9aHVfQT0dZR+AlfA,
soren.brinkmann-gjFFaj9aHVfQT0dZR+AlfA,
appana.durga.rao-gjFFaj9aHVfQT0dZR+AlfA,
anuragku-gjFFaj9aHVfQT0dZR+AlfA,
dan.j.williams-ral2JQCrhuEAvxtiuMwx3w,
CARLOS.PALMINHA-HKixBCOQz3hWk0Htik3J/w
In-Reply-To: <5658430.jXmKZEXWrS@avalon>
Hi Laurent,
Thank you for your feedback.
On 12/14/2016 8:16 PM, Laurent Pinchart wrote:
> Hi Ramiro,
>
> Thank you for the patch.
>
> On Wednesday 14 Dec 2016 17:18:24 Ramiro Oliveira wrote:
>> Add a DT property to control an optional external reset line
>>
>> Signed-off-by: Ramiro Oliveira <roliveir-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>
>> ---
>> drivers/dma/xilinx/xilinx_dma.c | 23 +++++++++++++++++++++++
>> 1 file changed, 23 insertions(+)
>>
>> diff --git a/drivers/dma/xilinx/xilinx_dma.c
>> b/drivers/dma/xilinx/xilinx_dma.c index 5c9f11b..b845224 100644
>> --- a/drivers/dma/xilinx/xilinx_dma.c
>> +++ b/drivers/dma/xilinx/xilinx_dma.c
>> @@ -46,6 +46,7 @@
>> #include <linux/slab.h>
>> #include <linux/clk.h>
>> #include <linux/io-64-nonatomic-lo-hi.h>
>> +#include <linux/reset.h>
>
> I had neatly sorted the header alphabetically until someone added clk.h and
> io-64-nonatomic-lo-hi.h :-( Could you please move reset.h just before slab.h ?
>
Sure. Actually I was tempted to reorder it, but I decided not to do it. I'll do
it now
>>
>> #include "../dmaengine.h"
>>
>> @@ -409,6 +410,7 @@ struct xilinx_dma_device {
>> struct clk *rxs_clk;
>> u32 nr_channels;
>> u32 chan_id;
>> + struct reset_control *rst;
>> };
>>
>> /* Macros */
>> @@ -2543,6 +2545,27 @@ static int xilinx_dma_probe(struct platform_device
>> *pdev) if (IS_ERR(xdev->regs))
>> return PTR_ERR(xdev->regs);
>>
>> + xdev->rst = devm_reset_control_get_optional(&pdev->dev, "reset");
>
> devm_reset_control_get_optional() is deprecated as explained in linux/reset.h,
> you should use devm_reset_control_get_optional_exclusive() or
> devm_reset_control_get_optional_shared() instead, as applicable.
>
> This being said, I'm wondering why the optional versions of those functions
> exist, as they do exactly the same as the non-optional versions. The API feels
> wrong, it should have been modelled like the GPIO API. Feel free to fix it if
> you want :-) But that's out of scope for this patch.
>
I missed the comment stating that devm_reset_control_get_optional() was deprecated.
I could fix it. Your sugestion is modelling these functions like the GPIO API?
>> + if (IS_ERR(xdev->rst)) {
>> + err = PTR_ERR(xdev->rst);
>> + switch (err) {
>> + case -ENOENT:
>
> If you drop the name as proposed in the review of patch 1/2 you don't have to
> check for -ENOENT.
>
I'll do that.
>> + case -ENOTSUPP:
>> + xdev->rst = NULL;
>> + break;
>
> Wrong indentation.
>
> You need to handle -EPROBE_DEFER and defer probing of the xilinx_dma device.
>
>> + default:
>> + dev_err(xdev->dev, "error getting reset %d\n", err);
>> + return err;
>
> Wrong indentation.
>
>> + }
>> + } else {
>> + err = reset_control_deassert(xdev->rst);
>> + if (err) {
>> + dev_err(xdev->dev, "failed to deassert reset: %d\n",
>> + err);
>
> Wrong indentation.
>
>> + return err;
>> + }
>> + }
>> +
>> /* Retrieve the DMA engine properties from the device tree */
>> xdev->has_sg = of_property_read_bool(node, "xlnx,include-sg");
>> if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
>
--
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 1/2] devicetree: power: add bindings for GPIO-driven power switches
From: Bartosz Golaszewski @ 2016-12-15 10:57 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Rob Herring, Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, Mark Rutland, linux-iio, linux-devicetree,
LKML, Kevin Hilman, Patrick Titiano, Neil Armstrong,
Linus Walleij, Alexandre Courbot, linux-gpio, Sebastian Reichel,
linux-pm, Mark Brown, Liam Girdwood
In-Reply-To: <54679B04-3A57-4F0E-8EE6-BB37785F8E10@jic23.retrosnub.co.uk>
2016-12-14 18:36 GMT+01:00 Jonathan Cameron <jic23@jic23.retrosnub.co.uk>:
>
>
> On 14 December 2016 16:58:21 GMT+00:00, Bartosz Golaszewski
> <bgolaszewski@baylibre.com> wrote:
>>2016-12-13 20:27 GMT+01:00 Rob Herring <robh@kernel.org>:
>>> On Sun, Dec 11, 2016 at 11:21:44PM +0100, Bartosz Golaszewski wrote:
>>>> Some boards are equipped with simple, GPIO-driven power load
>>switches.
>>>> An example of such ICs is the TI tps229* series.
>>>
>>> How is this different than a GPIO regulator? The input and output
>>> voltages just happen to be the same. I could be convinced this is
>>> different enough to have a different compatible, but it somewhat
>>seems
>>> you want to use this for IIO, so you are creating a different binding
>>> for that usecase.
>>>
>>
>>It's more of a fixed regulator I suppose. Do you mean adding a new
>>compatible to the fixed-regulator binding (e.g. "gpio-power-switch" or
>>"simple-power-switch") and then providing an iio driver for toggling
>>the switch?
>
> I am rather torn on whether the IIO interface makes any sense beyond that of
> convenience.
>
The question is: will the iio maintainers be ok with adding support
for interfaces different than iio (I guess so since Lars already
mentioned wanting to support the GPIO chardev)? If so, I'm ok with not
using the iio framework in the kernel.
> A bridge to a regulator in general might make sense to cover the case of a
> reg effectively
> acting as a DAC at the edge of the known hardware.
>
> Lars' point about perhaps adding support for the new gpio userspace stuff to
> libiio would in
> this case also be rather papering over the issue.
> There is known hardware there so we should describe it!
>
> I think we should be considering this as the general case of the Linux
> controlled power supply.
> How do we want to represent that?
> Ultimately does a general regulator userspace interface make sense?
>
> Classic case of people cutting our hardware in half and making boundaries
> beyond which lie dragons.
>
> I would love to see the general case covered.
>
It seems as if this is already covered by the userspace-consumer
regulator driver, but it doesn't speak device tree yet. I guess we
could reuse it by merging the proposed gpio-power-switch binding and
extending it to parse DT.
Best regards,
Bartosz Golaszewski
^ permalink raw reply
* Re: [PATCH 6/6] watchdog: ts4600: add driver for TS-4600 watchdog
From: kbuild test robot @ 2016-12-15 10:28 UTC (permalink / raw)
Cc: kbuild-all, linux-kernel, linux-watchdog, linux-arm-kernel,
devicetree, kernel, mark, kris, horms+renesas, treding, jonathanh,
f.fainelli, fabio.estevam, kernel, shawnguo, linux, linux, wim,
mark.rutland, robh+dt, damien.riegel, lucile.quirion, olof, arnd,
suzuki.poulose, linus.walleij, will.deacon, yamada.masahiro,
Sebastien Bourdelin
In-Reply-To: <20161214231237.17496-7-sebastien.bourdelin@savoirfairelinux.com>
[-- Attachment #1: Type: text/plain, Size: 1211 bytes --]
Hi Sebastien,
[auto build test ERROR on linus/master]
[also build test ERROR on v4.9]
[cannot apply to next-20161215]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Sebastien-Bourdelin/of-documentation-add-bindings-documentation-for-TS-4600/20161215-072238
config: i386-allyesconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All errors (new ones prefixed by >>):
drivers/built-in.o: In function `ts4600_wdt_start':
>> ts4600_wdt.c:(.text+0x2333d64): undefined reference to `ts_nbus_write'
drivers/built-in.o: In function `ts4600_wdt_stop':
ts4600_wdt.c:(.text+0x2333d85): undefined reference to `ts_nbus_write'
drivers/built-in.o: In function `ts4600_wdt_probe':
ts4600_wdt.c:(.text+0x2333e66): undefined reference to `ts_nbus_write'
>> ts4600_wdt.c:(.text+0x2333ee9): undefined reference to `ts_nbus_is_ready'
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 57052 bytes --]
^ permalink raw reply
* Re: [PATCH] ARM: dts: r8a7791: link DU to VSPDs
From: Magnus Damm @ 2016-12-15 9:59 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: Simon Horman [Horms], Linux-Renesas, Rob Herring, Mark Rutland,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Russell King - ARM Linux,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <1922293.x1RvWWSErN-gHKXc3Y1Z8zGSmamagVegGFoWSdPRAKMAL8bYrjMMd8@public.gmane.org>
Hi Sergei,
On Thu, Dec 15, 2016 at 7:07 AM, Sergei Shtylyov
<sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org> wrote:
> Add the "vsps" property to the DU device node in order to link this node to
> the VSPD nodes.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org>
>
> ---
> This patch is against the 'renesas-devel-20161212-v4.9' of Simon Horman's
> 'renesas.git' repo. It's only meaningful if the DU driver patch I've just
> posted is applied.
Next time, please consider pointing out the exact name of the patch
you are referring to.
Thanks,
/ magnus
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 1/7] PM / devfreq: exynos-bus: Add the detailed correlation for Exynos5433
From: Chanwoo Choi @ 2016-12-15 9:30 UTC (permalink / raw)
To: myungjoo.ham, kyungmin.park
Cc: rjw, chanwoo, linux-pm, linux-kernel, Chanwoo Choi, Rob Herring,
devicetree
In-Reply-To: <1481794243-5046-1-git-send-email-cw00.choi@samsung.com>
This patch adds the detailed corrleation between sub-blocks and VDD_INT power
line for Exynos5433. VDD_INT provided the power source to INT (Internal) block.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
---
Documentation/devicetree/bindings/devfreq/exynos-bus.txt | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/Documentation/devicetree/bindings/devfreq/exynos-bus.txt b/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
index d3ec8e676b6b..d085ef90d27c 100644
--- a/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
+++ b/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
@@ -123,6 +123,20 @@ Detailed correlation between sub-blocks and power line according to Exynos SoC:
|--- FSYS
|--- FSYS2
+- In case of Exynos5433, there is VDD_INT power line as following:
+ VDD_INT |--- G2D (parent device)
+ |--- MSCL
+ |--- GSCL
+ |--- JPEG
+ |--- MFC
+ |--- HEVC
+ |--- BUS0
+ |--- BUS1
+ |--- BUS2
+ |--- PERIS (Fixed clock rate)
+ |--- PERIC (Fixed clock rate)
+ |--- FSYS (Fixed clock rate)
+
Example1:
Show the AXI buses of Exynos3250 SoC. Exynos3250 divides the buses to
power line (regulator). The MIF (Memory Interface) AXI bus is used to
--
1.9.1
^ permalink raw reply related
* [PATCH v3] power: supply: bq24735-charger: optionally poll the ac-detect gpio
From: Peter Rosin @ 2016-12-15 9:28 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Peter Rosin, Sebastian Reichel, Rob Herring, Mark Rutland,
linux-pm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161214151026.5q6goxlfscv53tol@earth>
If the ac-detect gpio does not support interrupts, provide a fallback
to poll the gpio at a configurable interval.
Signed-off-by: Peter Rosin <peda-koto5C5qi+TLoDKTGw+V6w@public.gmane.org>
---
v2 -> v3 changes:
- use device_property_read_u32 instead of of_property_read_u32
v1 -> v2 changes:
- use poll-interval instead of ti,poll-interval-ms in the bindings
Cheers,
peda
.../bindings/power/supply/ti,bq24735.txt | 2 +
drivers/power/supply/bq24735-charger.c | 49 +++++++++++++++++++---
2 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/power/supply/ti,bq24735.txt b/Documentation/devicetree/bindings/power/supply/ti,bq24735.txt
index 3bf55757ceec..799d0e5d6f26 100644
--- a/Documentation/devicetree/bindings/power/supply/ti,bq24735.txt
+++ b/Documentation/devicetree/bindings/power/supply/ti,bq24735.txt
@@ -25,6 +25,8 @@ Optional properties :
- ti,external-control : Indicates that the charger is configured externally
and that the host should not attempt to enable/disable charging or set the
charge voltage/current.
+ - poll-interval : In case 'interrupts' is not specified, poll AC presence
+ on the ti,ac-detect-gpios GPIO with this interval (milliseconds).
Example:
diff --git a/drivers/power/supply/bq24735-charger.c b/drivers/power/supply/bq24735-charger.c
index 1d5c9206e0ed..8a0242c13b7e 100644
--- a/drivers/power/supply/bq24735-charger.c
+++ b/drivers/power/supply/bq24735-charger.c
@@ -50,6 +50,8 @@ struct bq24735 {
struct bq24735_platform *pdata;
struct mutex lock;
struct gpio_desc *status_gpio;
+ struct delayed_work poll;
+ u32 poll_interval;
bool charging;
};
@@ -209,11 +211,8 @@ static int bq24735_charger_is_charging(struct bq24735 *charger)
return !(ret & BQ24735_CHG_OPT_CHARGE_DISABLE);
}
-static irqreturn_t bq24735_charger_isr(int irq, void *devid)
+static void bq24735_update(struct bq24735 *charger)
{
- struct power_supply *psy = devid;
- struct bq24735 *charger = to_bq24735(psy);
-
mutex_lock(&charger->lock);
if (charger->charging && bq24735_charger_is_present(charger))
@@ -223,11 +222,29 @@ static irqreturn_t bq24735_charger_isr(int irq, void *devid)
mutex_unlock(&charger->lock);
- power_supply_changed(psy);
+ power_supply_changed(charger->charger);
+}
+
+static irqreturn_t bq24735_charger_isr(int irq, void *devid)
+{
+ struct power_supply *psy = devid;
+ struct bq24735 *charger = to_bq24735(psy);
+
+ bq24735_update(charger);
return IRQ_HANDLED;
}
+static void bq24735_poll(struct work_struct *work)
+{
+ struct bq24735 *charger = container_of(work, struct bq24735, poll.work);
+
+ bq24735_update(charger);
+
+ schedule_delayed_work(&charger->poll,
+ msecs_to_jiffies(charger->poll_interval));
+}
+
static int bq24735_charger_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -455,11 +472,32 @@ static int bq24735_charger_probe(struct i2c_client *client,
client->irq, ret);
return ret;
}
+ } else if (charger->status_gpio) {
+ ret = device_property_read_u32(&client->dev, "poll-interval",
+ &charger->poll_interval);
+ if (ret)
+ return 0;
+ if (!charger->poll_interval)
+ return 0;
+
+ INIT_DELAYED_WORK(&charger->poll, bq24735_poll);
+ schedule_delayed_work(&charger->poll,
+ msecs_to_jiffies(charger->poll_interval));
}
return 0;
}
+static int bq24735_charger_remove(struct i2c_client *client)
+{
+ struct bq24735 *charger = i2c_get_clientdata(client);
+
+ if (charger->poll_interval)
+ cancel_delayed_work_sync(&charger->poll);
+
+ return 0;
+}
+
static const struct i2c_device_id bq24735_charger_id[] = {
{ "bq24735-charger", 0 },
{}
@@ -478,6 +516,7 @@ static struct i2c_driver bq24735_charger_driver = {
.of_match_table = bq24735_match_ids,
},
.probe = bq24735_charger_probe,
+ .remove = bq24735_charger_remove,
.id_table = bq24735_charger_id,
};
--
2.1.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 v4 2/2] mtd: spi-nor: add rockchip serial flash controller driver
From: Shawn Lin @ 2016-12-15 9:27 UTC (permalink / raw)
To: David Woodhouse, Brian Norris
Cc: Marek Vasut, Cyrille Pitchen, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Heiko Stuebner,
Shawn Lin
In-Reply-To: <1481794068-241619-1-git-send-email-shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Add rockchip serial flash controller driver
Signed-off-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
---
Changes in v4:
- simplify the code of get_if_type
- use dma_dir to simplify the code
- simplify the rockchip_sfc_do_rd_wr
- some minor improvements
- add reset controller when doing resume
Changes in v3:
- use io{read32,write32}_rep to simplify the corner cases
- remove more unnecessary bit definitions
- some minor comment fixes and improvement
- fix wrong unregister function
- unify more code
- use nor to avoid constantly replicating the whole
sfc->flash[sfc->num_chip].nor
- add email for MODULE_AUTHOR
- remove #if 1 --- #endif
- extract DMA code to imporve the code structure
- reset all when failing to do dma
- pass sfc to get_if_type
- rename sfc-no-dma to sfc-no-DMA
Changes in v2:
- fix typos
- add some comment for buffer and others operations
- rename SFC_MAX_CHIP_NUM to MAX_CHIPSELECT_NUM
- use u8 for cs
- return -EINVAL for default case of get_if_type
- use readl_poll_*() to check timeout cases
- simplify and clarify some condition checks
- rework the bitshifts to simplify the code
- define SFC_CMD_DUMMY(x)
- fix ummap for dma read path and finish all the
cache maintenance.
- rename to rockchip_sfc_chip_priv and embed struct spi_nor
in it.
- add MODULE_AUTHOR
- add runtime PM and general PM support.
- Thanks for Marek's comments. Link:
http://lists.infradead.org/pipermail/linux-mtd/2016-November/070321.html
MAINTAINERS | 8 +
drivers/mtd/spi-nor/Kconfig | 7 +
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/rockchip-sfc.c | 872 +++++++++++++++++++++++++++++++++++++
4 files changed, 888 insertions(+)
create mode 100644 drivers/mtd/spi-nor/rockchip-sfc.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 1cd38a7..eb7e06d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10266,6 +10266,14 @@ L: linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
S: Odd Fixes
F: drivers/tty/serial/rp2.*
+ROCKCHIP SERIAL FLASH CONTROLLER DRIVER
+M: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
+L: linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
+L: linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
+S: Maintained
+F: Documentation/devicetree/bindings/mtd/rockchip-sfc.txt
+F: drivers/mtd/spi-nor/rockchip-sfc.c
+
ROSE NETWORK LAYER
M: Ralf Baechle <ralf-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org>
L: linux-hams-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 4a682ee..bf783a8 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -76,4 +76,11 @@ config SPI_NXP_SPIFI
Flash. Enable this option if you have a device with a SPIFI
controller and want to access the Flash as a mtd device.
+config SPI_ROCKCHIP_SFC
+ tristate "Rockchip Serial Flash Controller(SFC)"
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
+ depends on HAS_IOMEM && HAS_DMA
+ help
+ This enables support for rockchip serial flash controller.
+
endif # MTD_SPI_NOR
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 121695e..364d4c6 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o
obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
+obj-$(CONFIG_SPI_ROCKCHIP_SFC) += rockchip-sfc.o
diff --git a/drivers/mtd/spi-nor/rockchip-sfc.c b/drivers/mtd/spi-nor/rockchip-sfc.c
new file mode 100644
index 0000000..102c08f
--- /dev/null
+++ b/drivers/mtd/spi-nor/rockchip-sfc.c
@@ -0,0 +1,872 @@
+/*
+ * Rockchip Serial Flash Controller Driver
+ *
+ * Copyright (c) 2016, Rockchip Inc.
+ * Author: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/dma-mapping.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+
+/* System control */
+#define SFC_CTRL 0x0
+#define SFC_CTRL_COMMON_BITS_1 0x0
+#define SFC_CTRL_COMMON_BITS_2 0x1
+#define SFC_CTRL_COMMON_BITS_4 0x2
+#define SFC_CTRL_DATA_BITS_SHIFT 12
+#define SFC_CTRL_ADDR_BITS_SHIFT 10
+#define SFC_CTRL_CMD_BITS_SHIFT 8
+#define SFC_CTRL_PHASE_SEL_NEGETIVE BIT(1)
+
+/* Interrupt mask */
+#define SFC_IMR 0x4
+#define SFC_IMR_RX_FULL BIT(0)
+#define SFC_IMR_RX_UFLOW BIT(1)
+#define SFC_IMR_TX_OFLOW BIT(2)
+#define SFC_IMR_TX_EMPTY BIT(3)
+#define SFC_IMR_TRAN_FINISH BIT(4)
+#define SFC_IMR_BUS_ERR BIT(5)
+#define SFC_IMR_NSPI_ERR BIT(6)
+#define SFC_IMR_DMA BIT(7)
+/* Interrupt clear */
+#define SFC_ICLR 0x8
+#define SFC_ICLR_RX_FULL BIT(0)
+#define SFC_ICLR_RX_UFLOW BIT(1)
+#define SFC_ICLR_TX_OFLOW BIT(2)
+#define SFC_ICLR_TX_EMPTY BIT(3)
+#define SFC_ICLR_TRAN_FINISH BIT(4)
+#define SFC_ICLR_BUS_ERR BIT(5)
+#define SFC_ICLR_NSPI_ERR BIT(6)
+#define SFC_ICLR_DMA BIT(7)
+/* FIFO threshold level */
+#define SFC_FTLR 0xc
+#define SFC_FTLR_TX_SHIFT 0
+#define SFC_FTLR_TX_MASK 0x1f
+#define SFC_FTLR_RX_SHIFT 8
+#define SFC_FTLR_RX_MASK 0x1f
+/* Reset FSM and FIFO */
+#define SFC_RCVR 0x10
+#define SFC_RCVR_RESET BIT(0)
+/* Enhanced mode */
+#define SFC_AX 0x14
+/* Address Bit number */
+#define SFC_ABIT 0x18
+/* Interrupt status */
+#define SFC_ISR 0x1c
+#define SFC_ISR_RX_FULL_SHIFT BIT(0)
+#define SFC_ISR_RX_UFLOW_SHIFT BIT(1)
+#define SFC_ISR_TX_OFLOW_SHIFT BIT(2)
+#define SFC_ISR_TX_EMPTY_SHIFT BIT(3)
+#define SFC_ISR_TX_FINISH_SHIFT BIT(4)
+#define SFC_ISR_BUS_ERR_SHIFT BIT(5)
+#define SFC_ISR_NSPI_ERR_SHIFT BIT(6)
+#define SFC_ISR_DMA_SHIFT BIT(7)
+/* FIFO status */
+#define SFC_FSR 0x20
+#define SFC_FSR_TX_IS_FULL BIT(0)
+#define SFC_FSR_TX_IS_EMPTY BIT(1)
+#define SFC_FSR_RX_IS_EMPTY BIT(2)
+#define SFC_FSR_RX_IS_FULL BIT(3)
+/* FSM status */
+#define SFC_SR 0x24
+#define SFC_SR_IS_IDLE 0x0
+#define SFC_SR_IS_BUSY 0x1
+/* Raw interrupt status */
+#define SFC_RISR 0x28
+#define SFC_RISR_RX_FULL BIT(0)
+#define SFC_RISR_RX_UNDERFLOW BIT(1)
+#define SFC_RISR_TX_OVERFLOW BIT(2)
+#define SFC_RISR_TX_EMPTY BIT(3)
+#define SFC_RISR_TRAN_FINISH BIT(4)
+#define SFC_RISR_BUS_ERR BIT(5)
+#define SFC_RISR_NSPI_ERR BIT(6)
+#define SFC_RISR_DMA BIT(7)
+/* Master trigger */
+#define SFC_DMA_TRIGGER 0x80
+/* Src or Dst addr for master */
+#define SFC_DMA_ADDR 0x84
+/* Command */
+#define SFC_CMD 0x100
+#define SFC_CMD_IDX_SHIFT 0
+#define SFC_CMD_DUMMY_SHIFT 8
+#define SFC_CMD_DIR_RD 0
+#define SFC_CMD_DIR_WR 1
+#define SFC_CMD_DIR_SHIFT 12
+#define SFC_CMD_ADDR_ZERO (0x0 << 14)
+#define SFC_CMD_ADDR_24BITS (0x1 << 14)
+#define SFC_CMD_ADDR_32BITS (0x2 << 14)
+#define SFC_CMD_ADDR_FRS (0x3 << 14)
+#define SFC_CMD_TRAN_BYTES_SHIFT 16
+#define SFC_CMD_CS_SHIFT 30
+/* Address */
+#define SFC_ADDR 0x104
+/* Data */
+#define SFC_DATA 0x108
+
+#define SFC_MAX_CHIPSELECT_NUM 4
+#define SFC_DMA_MAX_LEN 0x4000
+#define SFC_CMD_DUMMY(x) \
+ ((x) << SFC_CMD_DUMMY_SHIFT)
+
+enum rockchip_sfc_iftype {
+ IF_TYPE_STD,
+ IF_TYPE_DUAL,
+ IF_TYPE_QUAD,
+};
+
+struct rockchip_sfc;
+struct rockchip_sfc_chip_priv {
+ u8 cs;
+ u32 clk_rate;
+ struct spi_nor nor;
+ struct rockchip_sfc *sfc;
+};
+
+struct rockchip_sfc {
+ struct device *dev;
+ struct mutex lock;
+ void __iomem *regbase;
+ struct clk *hclk;
+ struct clk *clk;
+ /* virtual mapped addr for dma_buffer */
+ void *buffer;
+ dma_addr_t dma_buffer;
+ struct completion cp;
+ struct rockchip_sfc_chip_priv flash[SFC_MAX_CHIPSELECT_NUM];
+ u32 num_chip;
+ bool use_dma;
+ /* use negative edge of hclk to latch data */
+ bool negative_edge;
+};
+
+static int get_if_type(struct rockchip_sfc *sfc, enum read_mode flash_read)
+{
+ if (flash_read == SPI_NOR_DUAL)
+ return IF_TYPE_DUAL;
+ else if (flash_read == SPI_NOR_QUAD)
+ return IF_TYPE_QUAD;
+ else if (flash_read == SPI_NOR_NORMAL ||
+ flash_read == SPI_NOR_FAST)
+ return IF_TYPE_STD;
+
+ dev_err(sfc->dev, "unsupported SPI read mode\n");
+ return -EINVAL;
+}
+
+static int rockchip_sfc_reset(struct rockchip_sfc *sfc)
+{
+ int err;
+ u32 status;
+
+ writel_relaxed(SFC_RCVR_RESET, sfc->regbase + SFC_RCVR);
+
+ err = readl_poll_timeout(sfc->regbase + SFC_RCVR, status,
+ !(status & SFC_RCVR_RESET), 20,
+ jiffies_to_usecs(HZ));
+ if (err)
+ dev_err(sfc->dev, "SFC reset never finished\n");
+
+ /* Still need to clear the masked interrupt from RISR */
+ writel_relaxed(SFC_ICLR_RX_FULL | SFC_ICLR_RX_UFLOW |
+ SFC_ICLR_TX_OFLOW | SFC_ICLR_TX_EMPTY |
+ SFC_ICLR_TRAN_FINISH | SFC_ICLR_BUS_ERR |
+ SFC_ICLR_NSPI_ERR | SFC_ICLR_DMA,
+ sfc->regbase + SFC_ICLR);
+ return err;
+}
+
+static int rockchip_sfc_init(struct rockchip_sfc *sfc)
+{
+ int err;
+
+ err = rockchip_sfc_reset(sfc);
+ if (err)
+ return err;
+
+ /* Mask all eight interrupts */
+ writel_relaxed(0xff, sfc->regbase + SFC_IMR);
+
+ /*
+ * Phase configure for sfc to latch data by using
+ * ahb clock, and this configuration should be Soc
+ * specific.
+ */
+ if (sfc->negative_edge)
+ writel_relaxed(SFC_CTRL_PHASE_SEL_NEGETIVE,
+ sfc->regbase + SFC_CTRL);
+ else
+ writel_relaxed(0, sfc->regbase + SFC_CTRL);
+
+ return 0;
+}
+
+static int rockchip_sfc_prep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ int ret;
+
+ mutex_lock(&sfc->lock);
+ pm_runtime_get_sync(sfc->dev);
+
+ ret = clk_set_rate(sfc->clk, priv->clk_rate);
+ if (ret)
+ goto out;
+
+ ret = clk_prepare_enable(sfc->clk);
+ if (ret)
+ goto out;
+
+ return 0;
+
+out:
+ mutex_unlock(&sfc->lock);
+ return ret;
+}
+
+static void rockchip_sfc_unprep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+
+ clk_disable_unprepare(sfc->clk);
+ mutex_unlock(&sfc->lock);
+ pm_runtime_mark_last_busy(sfc->dev);
+ pm_runtime_put_autosuspend(sfc->dev);
+}
+
+static int rockchip_sfc_wait_op_finish(struct rockchip_sfc *sfc)
+{
+ int err;
+ u32 status;
+
+ /*
+ * Note: tx and rx share the same fifo, so the rx's water level
+ * is the same as rx's, which means this function could be reused
+ * for checking the read operations as well.
+ */
+ err = readl_poll_timeout(sfc->regbase + SFC_FSR, status,
+ status & SFC_FSR_TX_IS_EMPTY,
+ 20, jiffies_to_usecs(2 * HZ));
+ if (err)
+ dev_err(sfc->dev, "SFC fifo never empty\n");
+
+ return err;
+}
+
+static int rockchip_sfc_op_reg(struct spi_nor *nor,
+ u8 opcode, int len, u8 optype)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ u32 reg;
+ bool tx_no_empty, rx_no_empty, is_busy;
+ int err;
+
+ reg = readl_relaxed(sfc->regbase + SFC_FSR);
+ tx_no_empty = !(reg & SFC_FSR_TX_IS_EMPTY);
+ rx_no_empty = !(reg & SFC_FSR_RX_IS_EMPTY);
+
+ is_busy = readl_relaxed(sfc->regbase + SFC_SR);
+
+ if (tx_no_empty || rx_no_empty || is_busy) {
+ err = rockchip_sfc_reset(sfc);
+ if (err)
+ return err;
+ }
+
+ reg = opcode << SFC_CMD_IDX_SHIFT;
+ reg |= len << SFC_CMD_TRAN_BYTES_SHIFT;
+ reg |= priv->cs << SFC_CMD_CS_SHIFT;
+ reg |= optype << SFC_CMD_DIR_SHIFT;
+
+ writel_relaxed(reg, sfc->regbase + SFC_CMD);
+
+ return rockchip_sfc_wait_op_finish(sfc);
+}
+
+static void rockchip_sfc_read_fifo(struct rockchip_sfc *sfc, u8 *buf, int len)
+{
+ u32 tmp, i;
+ int total_len = len;
+
+ /* 32-bit access only */
+ if (len >= 4 && !((u32)buf & 0x03)) {
+ ioread32_rep(sfc->regbase + SFC_DATA, buf, len >> 2);
+ len %= 4;
+ buf += total_len - len;
+ }
+
+ /* read the rest bytes */
+ for (i = 0; i < len; i++) {
+ if (!(i & 0x03))
+ tmp = readl_relaxed(sfc->regbase + SFC_DATA);
+ buf[i] = (tmp >> ((i & 0x03) * 8)) & 0xff;
+ }
+}
+
+static int rockchip_sfc_read_reg(struct spi_nor *nor, u8 opcode,
+ u8 *buf, int len)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ int ret;
+
+ ret = rockchip_sfc_op_reg(nor, opcode, len, SFC_CMD_DIR_RD);
+ if (ret)
+ return ret;
+
+ rockchip_sfc_read_fifo(sfc, buf, len);
+
+ return 0;
+}
+
+static int rockchip_sfc_write_reg(struct spi_nor *nor, u8 opcode,
+ u8 *buf, int len)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ u32 dwords;
+
+ /* Align bytes to dwords */
+ dwords = DIV_ROUND_UP(len, sizeof(u32));
+ iowrite32_rep(sfc->regbase + SFC_DATA, buf, dwords);
+
+ return rockchip_sfc_op_reg(nor, opcode, len, SFC_CMD_DIR_WR);
+}
+
+static inline void rockchip_sfc_setup_transfer(struct spi_nor *nor,
+ loff_t from_to,
+ size_t len, u8 op_type)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ u32 reg;
+ u8 if_type = 0;
+
+ if_type = get_if_type(sfc, nor->flash_read);
+ writel_relaxed((if_type << SFC_CTRL_DATA_BITS_SHIFT) |
+ (if_type << SFC_CTRL_ADDR_BITS_SHIFT) |
+ (if_type << SFC_CTRL_CMD_BITS_SHIFT) |
+ (sfc->negative_edge ? SFC_CTRL_PHASE_SEL_NEGETIVE : 0),
+ sfc->regbase + SFC_CTRL);
+
+ if (op_type == SFC_CMD_DIR_WR)
+ reg = nor->program_opcode << SFC_CMD_IDX_SHIFT;
+ else
+ reg = nor->read_opcode << SFC_CMD_IDX_SHIFT;
+
+ reg |= op_type << SFC_CMD_DIR_SHIFT;
+ reg |= (nor->addr_width == 4) ?
+ SFC_CMD_ADDR_32BITS : SFC_CMD_ADDR_24BITS;
+
+ reg |= priv->cs << SFC_CMD_CS_SHIFT;
+ reg |= len << SFC_CMD_TRAN_BYTES_SHIFT;
+
+ if (op_type == SFC_CMD_DIR_RD)
+ reg |= SFC_CMD_DUMMY(nor->read_dummy);
+
+ /* Should minus one as 0x0 means 1 bit flash address */
+ writel_relaxed(nor->addr_width * 8 - 1, sfc->regbase + SFC_ABIT);
+ writel_relaxed(reg, sfc->regbase + SFC_CMD);
+ writel_relaxed(from_to, sfc->regbase + SFC_ADDR);
+}
+
+static int rockchip_sfc_do_dma_transfer(struct spi_nor *nor, loff_t from_to,
+ dma_addr_t dma_buf, size_t len,
+ u8 op_type)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ u32 reg;
+ int err = 0;
+
+ init_completion(&sfc->cp);
+
+ writel_relaxed(SFC_ICLR_RX_FULL | SFC_ICLR_RX_UFLOW |
+ SFC_ICLR_TX_OFLOW | SFC_ICLR_TX_EMPTY |
+ SFC_ICLR_TRAN_FINISH | SFC_ICLR_BUS_ERR |
+ SFC_ICLR_NSPI_ERR | SFC_ICLR_DMA,
+ sfc->regbase + SFC_ICLR);
+
+ /* Enable transfer complete interrupt */
+ reg = readl_relaxed(sfc->regbase + SFC_IMR);
+ reg &= ~SFC_IMR_TRAN_FINISH;
+ writel_relaxed(reg, sfc->regbase + SFC_IMR);
+
+ rockchip_sfc_setup_transfer(nor, from_to, len, op_type);
+ writel_relaxed(dma_buf, sfc->regbase + SFC_DMA_ADDR);
+
+ /*
+ * Start dma but note that the sfc->dma_buffer is derived from
+ * dmam_alloc_coherent so we don't actually need any sync operations
+ * for coherent dma memory.
+ */
+ writel_relaxed(0x1, sfc->regbase + SFC_DMA_TRIGGER);
+
+ /* Wait for the interrupt. */
+ if (!wait_for_completion_timeout(&sfc->cp, msecs_to_jiffies(2000))) {
+ dev_err(sfc->dev, "DMA wait for transfer finish timeout\n");
+ err = -ETIMEDOUT;
+ }
+
+ /* Disable transfer finish interrupt */
+ reg = readl_relaxed(sfc->regbase + SFC_IMR);
+ reg |= SFC_IMR_TRAN_FINISH;
+ writel_relaxed(reg, sfc->regbase + SFC_IMR);
+
+ if (err) {
+ rockchip_sfc_reset(sfc);
+ return err;
+ }
+
+ return rockchip_sfc_wait_op_finish(sfc);
+}
+
+static inline int rockchip_sfc_pio_write(struct rockchip_sfc *sfc, u_char *buf,
+ size_t len)
+{
+ u32 dwords;
+
+ /*
+ * Align bytes to dwords, although we will write some extra
+ * bytes to fifo but the transfer bytes number in SFC_CMD
+ * register will make sure we just send out the expected
+ * byte numbers and the extra bytes will be clean before
+ * setting up the next transfer. We should always round up
+ * to align to DWORD as the ahb for Rockchip Socs won't
+ * support non-aligned-to-DWORD transfer.
+ */
+ dwords = DIV_ROUND_UP(len, sizeof(u32));
+ iowrite32_rep(sfc->regbase + SFC_DATA, buf, dwords);
+
+ return rockchip_sfc_wait_op_finish(sfc);
+}
+
+static inline int rockchip_sfc_pio_read(struct rockchip_sfc *sfc, u_char *buf,
+ size_t len)
+{
+ rockchip_sfc_read_fifo(sfc, buf, len);
+
+ return rockchip_sfc_wait_op_finish(sfc);
+}
+
+static int rockchip_sfc_pio_transfer(struct spi_nor *nor, loff_t from_to,
+ size_t len, u_char *buf, u8 op_type)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+
+ rockchip_sfc_setup_transfer(nor, from_to, len, op_type);
+
+ if (op_type == SFC_CMD_DIR_WR)
+ return rockchip_sfc_pio_write(sfc, buf, len);
+ else
+ return rockchip_sfc_pio_read(sfc, buf, len);
+}
+
+static int rockchip_sfc_dma_transfer(struct spi_nor *nor, loff_t from_to,
+ size_t len, u_char *buf, u8 op_type)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ size_t offset;
+ int ret;
+ dma_addr_t dma_addr = 0;
+ int dma_dir;
+
+ dma_dir = (op_type == SFC_CMD_DIR_RD) ?
+ DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+ for (offset = 0; offset < len; offset += SFC_DMA_MAX_LEN) {
+ size_t trans = min_t(size_t, SFC_DMA_MAX_LEN, len - offset);
+
+ dma_addr = dma_map_single(NULL, (void *)buf, trans, dma_dir);
+
+ if (dma_mapping_error(sfc->dev, dma_addr)) {
+ /*
+ * If we use pre-allocated dma_buffer, we need to
+ * do a copy here.
+ */
+ if (op_type == SFC_CMD_DIR_WR)
+ memcpy(sfc->buffer, buf + offset, trans);
+
+ dma_addr = 0;
+ }
+
+ if (op_type == SFC_CMD_DIR_WR)
+ /*
+ * Flush the write data from write_buf to dma_addr
+ * if using dynamic allocated dma buffer before dma
+ * moves data from dma_addr to fifo.
+ */
+ dma_sync_single_for_device(sfc->dev, dma_addr,
+ trans, DMA_TO_DEVICE);
+
+
+ /* If failing to map dma, use pre-allocated area instead */
+ ret = rockchip_sfc_do_dma_transfer(nor, from_to + offset,
+ dma_addr ? dma_addr :
+ sfc->dma_buffer,
+ trans, op_type);
+
+ if (dma_addr) {
+ /*
+ * Invalidate the read data from dma_addr if using
+ * dynamic allocated dma buffer after dma moves data
+ * from fifo to dma_addr.
+ */
+ if (op_type == SFC_CMD_DIR_RD)
+ dma_sync_single_for_cpu(sfc->dev, dma_addr,
+ trans, DMA_FROM_DEVICE);
+
+ dma_unmap_single(NULL, dma_addr,
+ trans, dma_dir);
+ }
+
+ if (ret) {
+ dev_warn(nor->dev, "DMA read timeout\n");
+ return ret;
+ }
+ /*
+ * If we use pre-allocated dma_buffer for read, we need to
+ * do a copy here.
+ */
+ if (!dma_addr && (op_type == SFC_CMD_DIR_RD))
+ memcpy(buf + offset, sfc->buffer, trans);
+ }
+
+ return len;
+}
+
+static ssize_t rockchip_sfc_do_rd_wr(struct spi_nor *nor, loff_t from_to,
+ size_t len, u_char *buf, u32 op_type)
+{
+ struct rockchip_sfc_chip_priv *priv = nor->priv;
+ struct rockchip_sfc *sfc = priv->sfc;
+ int ret;
+
+ if (likely(sfc->use_dma))
+ return rockchip_sfc_dma_transfer(nor, from_to, len,
+ buf, op_type);
+
+ /* Fall back to PIO mode if DMA isn't present */
+ ret = rockchip_sfc_pio_transfer(nor, from_to, len,
+ (u_char *)buf, op_type);
+ if (ret) {
+ if (op_type == SFC_CMD_DIR_RD)
+ dev_warn(nor->dev, "PIO read timeout\n");
+ else
+ dev_warn(nor->dev, "PIO write timeout\n");
+ return ret;
+ }
+
+ return len;
+}
+
+static ssize_t rockchip_sfc_read(struct spi_nor *nor, loff_t from,
+ size_t len, u_char *read_buf)
+{
+ return rockchip_sfc_do_rd_wr(nor, from, len,
+ read_buf, SFC_CMD_DIR_RD);
+}
+
+static ssize_t rockchip_sfc_write(struct spi_nor *nor, loff_t to,
+ size_t len, const u_char *write_buf)
+{
+ return rockchip_sfc_do_rd_wr(nor, to, len,
+ (u_char *)write_buf,
+ SFC_CMD_DIR_WR);
+}
+
+static int rockchip_sfc_register(struct device_node *np,
+ struct rockchip_sfc *sfc)
+{
+ struct device *dev = sfc->dev;
+ struct mtd_info *mtd;
+ struct spi_nor *nor;
+ int ret;
+
+ nor = &sfc->flash[sfc->num_chip].nor;
+ nor->dev = dev;
+ spi_nor_set_flash_node(nor, np);
+
+ ret = of_property_read_u8(np, "reg", &sfc->flash[sfc->num_chip].cs);
+ if (ret) {
+ dev_err(dev, "No reg property for %s\n",
+ np->full_name);
+ return ret;
+ }
+
+ ret = of_property_read_u32(np, "spi-max-frequency",
+ &sfc->flash[sfc->num_chip].clk_rate);
+ if (ret) {
+ dev_err(dev, "No spi-max-frequency property for %s\n",
+ np->full_name);
+ return ret;
+ }
+
+ sfc->flash[sfc->num_chip].sfc = sfc;
+ nor->priv = &(sfc->flash[sfc->num_chip]);
+
+ nor->prepare = rockchip_sfc_prep;
+ nor->unprepare = rockchip_sfc_unprep;
+ nor->read_reg = rockchip_sfc_read_reg;
+ nor->write_reg = rockchip_sfc_write_reg;
+ nor->read = rockchip_sfc_read;
+ nor->write = rockchip_sfc_write;
+ nor->erase = NULL;
+ ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD);
+ if (ret)
+ return ret;
+
+ mtd = &(nor->mtd);
+ mtd->name = np->name;
+ ret = mtd_device_register(mtd, NULL, 0);
+ if (ret)
+ return ret;
+
+ sfc->num_chip++;
+ return 0;
+}
+
+static void rockchip_sfc_unregister_all(struct rockchip_sfc *sfc)
+{
+ int i;
+
+ for (i = 0; i < sfc->num_chip; i++)
+ mtd_device_unregister(&sfc->flash[i].nor.mtd);
+}
+
+static int rockchip_sfc_register_all(struct rockchip_sfc *sfc)
+{
+ struct device *dev = sfc->dev;
+ struct device_node *np;
+ int ret;
+
+ for_each_available_child_of_node(dev->of_node, np) {
+ ret = rockchip_sfc_register(np, sfc);
+ if (ret)
+ goto fail;
+
+ if (sfc->num_chip == SFC_MAX_CHIPSELECT_NUM) {
+ dev_warn(dev, "Exceeds the max cs limitation\n");
+ break;
+ }
+ }
+
+ return 0;
+
+fail:
+ dev_err(dev, "Failed to register all chips\n");
+ /* Unregister all the _registered_ nor flash */
+ rockchip_sfc_unregister_all(sfc);
+ return ret;
+}
+
+static irqreturn_t rockchip_sfc_irq_handler(int irq, void *dev_id)
+{
+ struct rockchip_sfc *sfc = dev_id;
+ u32 reg;
+
+ reg = readl_relaxed(sfc->regbase + SFC_RISR);
+ dev_dbg(sfc->dev, "Get irq: 0x%x\n", reg);
+
+ /* Clear interrupt */
+ writel_relaxed(reg, sfc->regbase + SFC_ICLR);
+
+ if (reg & SFC_RISR_TRAN_FINISH)
+ complete(&sfc->cp);
+
+ return IRQ_HANDLED;
+}
+
+static int rockchip_sfc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct rockchip_sfc *sfc;
+ int ret;
+
+ sfc = devm_kzalloc(dev, sizeof(*sfc), GFP_KERNEL);
+ if (!sfc)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, sfc);
+ sfc->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ sfc->regbase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(sfc->regbase))
+ return PTR_ERR(sfc->regbase);
+
+ sfc->clk = devm_clk_get(&pdev->dev, "sfc");
+ if (IS_ERR(sfc->clk)) {
+ dev_err(&pdev->dev, "Failed to get sfc interface clk\n");
+ return PTR_ERR(sfc->clk);
+ }
+
+ sfc->hclk = devm_clk_get(&pdev->dev, "hsfc");
+ if (IS_ERR(sfc->hclk)) {
+ dev_err(&pdev->dev, "Failed to get sfc ahp clk\n");
+ return PTR_ERR(sfc->hclk);
+ }
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_warn(dev, "Unable to set dma mask\n");
+ return ret;
+ }
+
+ sfc->buffer = dmam_alloc_coherent(dev, SFC_DMA_MAX_LEN,
+ &sfc->dma_buffer, GFP_KERNEL);
+ if (!sfc->buffer)
+ return -ENOMEM;
+
+ mutex_init(&sfc->lock);
+
+ ret = clk_prepare_enable(sfc->hclk);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to enable hclk\n");
+ goto err_hclk;
+ }
+
+ ret = clk_prepare_enable(sfc->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to enable clk\n");
+ goto err_clk;
+ }
+
+ sfc->use_dma = !of_property_read_bool(sfc->dev->of_node,
+ "rockchip,sfc-no-DMA");
+
+ sfc->negative_edge = of_device_is_compatible(sfc->dev->of_node,
+ "rockchip,rk1108-sfc");
+ /* Find the irq */
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
+ dev_err(dev, "Failed to get the irq\n");
+ goto err_irq;
+ }
+
+ ret = devm_request_irq(dev, ret, rockchip_sfc_irq_handler,
+ 0, pdev->name, sfc);
+ if (ret) {
+ dev_err(dev, "Failed to request irq\n");
+ goto err_irq;
+ }
+
+ sfc->num_chip = 0;
+ ret = rockchip_sfc_init(sfc);
+ if (ret)
+ goto err_irq;
+
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
+ pm_runtime_use_autosuspend(&pdev->dev);
+
+ ret = rockchip_sfc_register_all(sfc);
+ if (ret)
+ goto err_register;
+
+ clk_disable_unprepare(sfc->clk);
+ pm_runtime_put_autosuspend(&pdev->dev);
+ return 0;
+
+err_register:
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+err_irq:
+ clk_disable_unprepare(sfc->clk);
+err_clk:
+ clk_disable_unprepare(sfc->hclk);
+err_hclk:
+ mutex_destroy(&sfc->lock);
+ return ret;
+}
+
+static int rockchip_sfc_remove(struct platform_device *pdev)
+{
+ struct rockchip_sfc *sfc = platform_get_drvdata(pdev);
+
+ pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
+ rockchip_sfc_unregister_all(sfc);
+ mutex_destroy(&sfc->lock);
+ clk_disable_unprepare(sfc->clk);
+ clk_disable_unprepare(sfc->hclk);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+int rockchip_sfc_runtime_suspend(struct device *dev)
+{
+ struct rockchip_sfc *sfc = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(sfc->hclk);
+ return 0;
+}
+
+int rockchip_sfc_runtime_resume(struct device *dev)
+{
+ struct rockchip_sfc *sfc = dev_get_drvdata(dev);
+
+ clk_prepare_enable(sfc->hclk);
+ return rockchip_sfc_reset(sfc);
+}
+#endif /* CONFIG_PM */
+
+static const struct of_device_id rockchip_sfc_dt_ids[] = {
+ { .compatible = "rockchip,sfc"},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rockchip_sfc_dt_ids);
+
+static const struct dev_pm_ops rockchip_sfc_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(rockchip_sfc_runtime_suspend,
+ rockchip_sfc_runtime_resume, NULL)
+};
+
+static struct platform_driver rockchip_sfc_driver = {
+ .driver = {
+ .name = "rockchip-sfc",
+ .of_match_table = rockchip_sfc_dt_ids,
+ .pm = &rockchip_sfc_dev_pm_ops,
+ },
+ .probe = rockchip_sfc_probe,
+ .remove = rockchip_sfc_remove,
+};
+module_platform_driver(rockchip_sfc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Rockchip Serial Flash Controller Driver");
+MODULE_AUTHOR("Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>");
--
1.9.1
--
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 v4 1/2] mtd: spi-nor: Bindings for Rockchip serial flash controller
From: Shawn Lin @ 2016-12-15 9:27 UTC (permalink / raw)
To: David Woodhouse, Brian Norris
Cc: Marek Vasut, Cyrille Pitchen, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Heiko Stuebner,
Shawn Lin
In-Reply-To: <1481794068-241619-1-git-send-email-shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Add binding document for the Rockchip serial flash controller.
Signed-off-by: Shawn Lin <shawn.lin-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
Changes in v4:
- use uppercase DMA for description
Changes in v3: None
Changes in v2: None
.../devicetree/bindings/mtd/rockchip-sfc.txt | 31 ++++++++++++++++++++++
1 file changed, 31 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mtd/rockchip-sfc.txt
diff --git a/Documentation/devicetree/bindings/mtd/rockchip-sfc.txt b/Documentation/devicetree/bindings/mtd/rockchip-sfc.txt
new file mode 100644
index 0000000..2a889c9
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/rockchip-sfc.txt
@@ -0,0 +1,31 @@
+Rockchip Serial Flash Controller
+
+Required properties:
+- compatible : Should be
+ "rockchip,rk1108-sfc", "rockchip,sfc" for ROCKCHIP RK1108.
+- address-cells : Should be 1.
+- size-cells : Should be 0.
+- clocks: Must contain two entries for each entry in clock-names.
+- clock-names: Shall be "sfc" for the transfer-clock, and "hsfc" for
+ the peripheral clock.
+- interrupts : Should contain the interrupt for the device.
+- reg: Physical base address of the controller and length of memory mapped.
+
+Optional properties:
+- rockchip,sfc-no-dma: Indicate the controller doesn't support DMA transfer.
+
+Example:
+nor_flash: sfc@301c0000 {
+ compatible = "rockchip,rk1108-sfc", "rockchip,sfc";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>;
+ clock-names = "sfc", "hsfc";
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x301c0000 0x1000>;
+ spi-nor@0 {
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <12000000>;
+ reg = <0>;
+ };
+};
--
1.9.1
--
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 v4 0/2] Add rockchip serial flash controller support
From: Shawn Lin @ 2016-12-15 9:27 UTC (permalink / raw)
To: David Woodhouse, Brian Norris
Cc: Marek Vasut, Cyrille Pitchen, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Heiko Stuebner,
Shawn Lin
Here is another try for adding serial flash controller
, namely SFC, found on Rockchip RK1108 platform.
Feature:
(1) Support x1, x2, x4 data bits mode
(2) Support up to 4 chip select
(3) Support two independent clock domain: AHB clock and SPI clock
(4) Support DMA master up to 16KB/transfer
Test environment:
This patchset was tested on RK1108 evb boards with Winboud flash
(w25q256) and working fine with PIO or DMA mode.
How-to:
Any rockchip guys who are interested in testing it could refer to
the following steps:
(1) enable CONFIG_MTD_M25P80
(2) enable CONFIG_SPI_ROCKCHIP_SFC
(3) enable CONFIG_MTD_CMDLINE_PARTS
(4) enable CONFIG_SQUASHFS
(4) CONFIG_CMDLINE="root=/dev/mtdblock2
mtdparts=spi-nor:256k@0(loader)ro,8m(kernel)ro,7m(rootfs),-(freedisk)"
Of course, you should check the partition layout if you modify it. Also
you could pass it from your loader to the kernel's cmdline.
(5) Add dts support:
nor_flash: sfc@301c0000 {
compatible = "rockchip,rk1108-sfc", "rockchip,sfc";
#address-cells = <1>;
#size-cells = <0>;
clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>;
clock-names = "sfc", "hsfc";
interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
reg = <0x301c0000 0x1000>;
/* If you want to use PIO mode, activate this */
#rockchip,sfc-no-dma;
spi-nor@0 {
compatible = "jedec,spi-nor";
spi-max-frequency = <12000000>;
reg = <0>;
}
};
please make sure your DT's mdtid matchs what you assgin to the
mdtparts(cmdline), namely they are both *spi-nor* here.
With enabling DBG for cmdlinepart.c, you could get following log and
boot kernel and rootfs successfully.
[ 0.481420] rockchip-sfc 301c0000.sfc: w25q256 (32768 Kbytes)
[ 0.481962] DEBUG-CMDLINE-PART: parsing
<256k@0(loader)ro,8m(kernel)ro,7m(rootfs)ro,-(freedisk)>
[ 0.482897] DEBUG-CMDLINE-PART: partition 3: name
<freedisk>, offset ffffffffffffffff, size ffffffffffffffff, mask flags 0
[ 0.484021] DEBUG-CMDLINE-PART: partition 2: name
<rootfs>, offset ffffffffffffffff, size 700000, mask flags 400
[ 0.485066] DEBUG-CMDLINE-PART: partition 1: name
<kernel>, offset ffffffffffffffff, size 800000, mask flags 400
[ 0.486108] DEBUG-CMDLINE-PART: partition 0: name
<loader>, offset 0, size 40000, mask flags 400
[ 0.487152] DEBUG-CMDLINE-PART: mtdid=<spi-nor> num_parts=<4>
[ 0.487827] 4 cmdlinepart partitions found on MTD device spi-nor
[ 0.488370] Creating 4 MTD partitions on "spi-nor":
[ 0.488826] 0x000000000000-0x000000040000 : "loader"
[ 0.492340] 0x000000040000-0x000000840000 : "kernel"
[ 0.495679] 0x000000840000-0x000000f40000 : "rootfs"
[ 0.499241] 0x000000f40000-0x000002000000 : "freedisk"
[root@arm-linux]#
[root@arm-linux]#mount
/dev/root on / type squashfs (ro,relatime)
devtmpfs on /dev type devtmpfs
(rw,relatime,size=26124k,nr_inodes=6531,mode=755)
proc on /proc type proc (rw,relatime)
none on /tmp type ramfs (rw,relatime)
none on /var type ramfs (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
debug on /sys/kernel/debug type debugfs (rw,relatime)
none on /dev/pts type devpts (rw,relatime,mode=600,ptmxmode=000)
Changes in v4:
- use uppercase DMA for description
- simplify the code of get_if_type
- use dma_dir to simplify the code
- simplify the rockchip_sfc_do_rd_wr
- some minor improvements
- add reset controller when doing resume
Changes in v3:
- use io{read32,write32}_rep to simplify the corner cases
- remove more unnecessary bit definitions
- some minor comment fixes and improvement
- fix wrong unregister function
- unify more code
- use nor to avoid constantly replicating the whole
sfc->flash[sfc->num_chip].nor
- add email for MODULE_AUTHOR
- remove #if 1 --- #endif
- extract DMA code to imporve the code structure
- reset all when failing to do dma
- pass sfc to get_if_type
- rename sfc-no-dma to sfc-no-DMA
Changes in v2:
- fix typos
- add some comment for buffer and others operations
- rename SFC_MAX_CHIP_NUM to MAX_CHIPSELECT_NUM
- use u8 for cs
- return -EINVAL for default case of get_if_type
- use readl_poll_*() to check timeout cases
- simplify and clarify some condition checks
- rework the bitshifts to simplify the code
- define SFC_CMD_DUMMY(x)
- fix ummap for dma read path and finish all the
cache maintenance.
- rename to rockchip_sfc_chip_priv and embed struct spi_nor
in it.
- add MODULE_AUTHOR
- add runtime PM and general PM support.
- Thanks for Marek's comments. Link:
http://lists.infradead.org/pipermail/linux-mtd/2016-November/070321.html
Shawn Lin (2):
mtd: spi-nor: Bindings for Rockchip serial flash controller
mtd: spi-nor: add rockchip serial flash controller driver
.../devicetree/bindings/mtd/rockchip-sfc.txt | 31 +
MAINTAINERS | 8 +
drivers/mtd/spi-nor/Kconfig | 7 +
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/rockchip-sfc.c | 872 +++++++++++++++++++++
5 files changed, 919 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mtd/rockchip-sfc.txt
create mode 100644 drivers/mtd/spi-nor/rockchip-sfc.c
--
1.9.1
--
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: [RFC] New Device Tree property - "bonding"
From: Geert Uytterhoeven @ 2016-12-15 9:07 UTC (permalink / raw)
To: Ramesh Shanmugasundaram
Cc: Rob Herring, Laurent Pinchart, frowand.list@gmail.com,
mark.rutland@arm.com, pantelis.antoniou@konsulko.com,
Chris Paterson, Geert Uytterhoeven,
laurent.pinchart+renesas@ideasonboard.com,
devicetree@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
Maxime Ripard
In-Reply-To: <SG2PR06MB1038FDD0F2C70D6CB0AED298C3820@SG2PR06MB1038.apcprd06.prod.outlook.com>
On Tue, Dec 6, 2016 at 6:45 PM, Ramesh Shanmugasundaram
<ramesh.shanmugasundaram@bp.renesas.com> wrote:
>> >> On Monday 05 Dec 2016 09:57:32 Rob Herring wrote:
>> >> > On Mon, Dec 5, 2016 at 8:40 AM, Laurent Pinchart wrote:
>> >> > > On Monday 05 Dec 2016 08:18:34 Rob Herring wrote:
>> >> > >> On Fri, Nov 25, 2016 at 10:55 AM, Ramesh Shanmugasundaram wrote:
>> >> > >>> Hello DT maintainers,
>> >> > >>>
>> >> > >>> In one of the Renesas SoCs we have a device called DRIF
>> >> > >>> (Digital Radio
>> >> > >>> Interface) controller. A DRIF channel contains 4 external pins
>> >> > >>> - SCK, SYNC, Data pins D0 & D1.
>> >> > >>>
>> >> > >>> Internally a DRIF channel is made up of two SPI slave devices
>> >> > >>> (also called sub-channels here) that share common CLK & SYNC
>> >> > >>> signals but have their own resource set. The DRIF channel can
>> >> > >>> have either one of the sub-channel active at a time or both.
>> >> > >>> When both sub-channels are active, they need to be managed
>> >> > >>> together as one device as they share same CLK & SYNC. We plan
>> >> > >>> to tie these two sub-channels together with a new property called
>> "renesas,bonding".
>> >> > >>
>> >> > >> Is there no need to describe the master device? No GPIOs,
>> >> > >> regulators or other sideband controls needed? If that's never
>> >> > >> needed (which seems doubtful), then I would do something
>> >> > >> different here probably with the master device as a child of one
>> >> > >> DRIF and then phandles to master from the other DRIFs.
>> >> > >> Otherwise, this looks
>> >> fine to me.
>> >> > >
>> >> > > Here's a bit of background.
>> >> > >
>> >> > > The DRIF is an SPI receiver. It has three input pins, a clock
>> >> > > line, a data line and a sync signal. The device is designed to be
>> >> > > connected to a variety of data sources, usually plain SPI (1 data
>> >> > > line), IIS (1 data
>> >> > > line) but also radio tuners that output I/Q data
>> >> > > (http://www.ni.com/tutorial/4805/en/) over two data lines.
>> >> > >
>> >> > > In the case of IQ each data sample is split in two I and Q values
>> >> > > (typically 16 to 20 bits each in this case), and the values are
>> >> > > transmitted serially over one data line each. The synchronization
>> >> > > and clock signals are common to both data lines. The DRIF is
>> >> > > optimized for this use case as the DRIF instances in the SoC
>> >> > > (each of them having independent clocks, interrupts and control
>> >> > > registers) are grouped by two, and the two instances in a group
>> >> > > handle a single data line each but share the same clock and sync
>> input.
>> >> > >
>> >> > > On the software side we need to group the I and Q values, which
>> >> > > are DMA'ed to memory by the two DRIF instances, and make them
>> >> > > available to userspace. The V4L2 API used here in SDR (Software
>> >> > > Defined Radio) mode supports such use cases and exposes a single
>> >> > > device node to userspace that allows control of the two DRIF
>> >> > > instances as a single device. To be able to implement this we
>> >> > > need kernel code to be aware of DRIF groups and, while binding to
>> >> > > the DRIF instances separately, expose only one V4L2 device to
>> userspace for each group.
>> >> > >
>> >> > > There's no master or slave instance from a hardware point of
>> >> > > view, but the two instances are not interchangeable as they carry
>> >> > > separate
>> >> information.
>> >> > > They must thus be identified at the driver level.
>> >> >
>> >> > By master, I meant the external master device that generates the IQ
>> >> > data, not which of the internal DRIF blocks is a master of the other.
>> >> > So back to my question, does the external master device need to be
>> >> > described? I worry the answer now for a simple case is no, but then
>> >> > later people are going to have cases needing to describe more. We
>> >> > need to answer this question first before we can decide what this
>> >> > binding should look like.
>> >>
>> >> Oh yes the external device certainly needs to be described. As it is
>> >> controlled through a separate, general-purpose I2C or SPI controller,
>> >> it should be a child node of that controller. The DRIF handles the
>> >> data interface only, not the control interface of the external device.
>> >
>> > Yes, as Laurent mentioned, the external master will be described
>> separately. The data interface with the master is described through port
>> nodes. E.g.
>> >
>> > port {
>> > drif0_ep: endpoint {
>> > remote-endpoint = <&tuner_ep>;
>> > };
>> > };
>> >
>> > Do we agree on this model please?
>>
>> Well, that's not complete as you should have both DRIF0 and DRIF1 having
>> connections to the tuner. Then you can walk the graph and find everything,
>> and you then don't need the bonding property.
>
> Assuming the third party tuner exposes it's two data lines as two endpoints, it seems possible with of_graph.h apis to walk through tuner end points and get the phandle of the other DRIF device. However, there are couple of points coming to mind.
>
> - The ctrl pins shared between two DRIFs needs to be enabled in one of the DRIF device. Do we choose this device arbitrarily? Do we expose the CTRL signal properties (msb/lsb first, polarity etc) on both DRIF devices? Should we think about scalability?
>
> - It mandates the third party tuner device to expose it's two data lines as two endpoints. It assumes that a single third party master device controls both the data lines coming to each DRIF device.
>
> The bonding property looks a bit cleaner on these aspects because it describes only the DRIF device.
Does of_graph and endpoints need to be mandatory?
I can easily imagine using a single DRIF device as a receive-only MSIOF SPI
slave, without a tuner connected.
Cfr. spi-slave-system-control from my SPI skave mode support series
(https://lwn.net/Articles/700433/).
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ 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