* GPIO triggers kernel reboot
From: Geert Uytterhoeven @ 2014-01-27 8:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <8761p5hmni.fsf@lebrac.rtp-net.org>
On Mon, Jan 27, 2014 at 9:08 AM, Arnaud Patard
<arnaud.patard@rtp-net.org> wrote:
>>> It's certainly possible, and it's also easily done from user-space.
>>> Something like this is more policy than function. It's also a potential
>>> security issue. As such I'd expect it highly unlikely that the kernel
>>> maintainers would allow it to go upstream. Give it a try though.
>>
>> Ok, thats what I also think ...
>>
>>> I'd approach this from user-space. Add in the gpio-keys driver and use the
>>> input-event-daemon to trigger a reboot. Super easy.
>>
>> Yes, that was also my suggestion, but is there a way to do this without
>> user space usage in a generic way?
>
> I think that you can register an input handler for that. iirc, there was
> a driver doing something similar for apm.
According to Documentation/sysctl/kernel.txt, the default for the
"ctrl-alt-del" input is to just reboot.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at 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
* [PATCH 4/9] idle: move the cpuidle entry point to the generic idle loop
From: Daniel Lezcano @ 2014-01-27 8:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390802904-28399-5-git-send-email-nicolas.pitre@linaro.org>
On 01/27/2014 07:08 AM, Nicolas Pitre wrote:
> In order to integrate cpuidle with the scheduler, we must have a better
> proximity in the core code with what cpuidle is doing and not delegate
> such interaction to arch code.
>
> Architectures implementing arch_cpu_idle() should simply enter
> a cheap idle mode in the absence of a proper cpuidle driver.
>
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
This patch without the next ones will lead to an extra call to
cpuidle_idle_call.
cpuidle_idle_call
arch_cpu_idle
cpuidle_idle_call
x86_idle
But I guess it is acceptable as it is fixed with the next patches of the
serie.
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---
> kernel/cpu/idle.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/kernel/cpu/idle.c b/kernel/cpu/idle.c
> index 4e327e211b..a6f40ad9f8 100644
> --- a/kernel/cpu/idle.c
> +++ b/kernel/cpu/idle.c
> @@ -3,6 +3,7 @@
> */
> #include <linux/sched.h>
> #include <linux/cpu.h>
> +#include <linux/cpuidle.h>
> #include <linux/tick.h>
> #include <linux/mm.h>
> #include <linux/stackprotector.h>
> @@ -94,7 +95,8 @@ static void cpu_idle_loop(void)
> if (!current_clr_polling_and_test()) {
> stop_critical_timings();
> rcu_idle_enter();
> - arch_cpu_idle();
> + if (cpuidle_idle_call())
> + arch_cpu_idle();
> WARN_ON_ONCE(irqs_disabled());
> rcu_idle_exit();
> start_critical_timings();
>
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [PATCH 5/9] ARM: remove redundant cpuidle_idle_call()
From: Daniel Lezcano @ 2014-01-27 8:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390802904-28399-6-git-send-email-nicolas.pitre@linaro.org>
On 01/27/2014 07:08 AM, Nicolas Pitre wrote:
> The core idle loop now takes care of it.
>
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---
> arch/arm/kernel/process.c | 16 +++++-----------
> 1 file changed, 5 insertions(+), 11 deletions(-)
>
> diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
> index 725b8c95e0..34a59b7614 100644
> --- a/arch/arm/kernel/process.c
> +++ b/arch/arm/kernel/process.c
> @@ -30,7 +30,6 @@
> #include <linux/uaccess.h>
> #include <linux/random.h>
> #include <linux/hw_breakpoint.h>
> -#include <linux/cpuidle.h>
> #include <linux/leds.h>
> #include <linux/reboot.h>
>
> @@ -133,7 +132,11 @@ EXPORT_SYMBOL_GPL(arm_pm_restart);
>
> void (*arm_pm_idle)(void);
>
> -static void default_idle(void)
> +/*
> + * Called from the core idle loop.
> + */
> +
> +void arch_cpu_idle(void)
> {
> if (arm_pm_idle)
> arm_pm_idle();
> @@ -163,15 +166,6 @@ void arch_cpu_idle_dead(void)
> #endif
>
> /*
> - * Called from the core idle loop.
> - */
> -void arch_cpu_idle(void)
> -{
> - if (cpuidle_idle_call())
> - default_idle();
> -}
> -
> -/*
> * Called by kexec, immediately prior to machine_kexec().
> *
> * This must completely disable all secondary CPUs; simply causing those CPUs
>
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [PATCH 3/4] ASoC: tda998x: add DT documentation
From: Jean-Francois Moine @ 2014-01-27 8:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1390813480.git.moinejf@free.fr>
Add devicetree documentation about the NXP TDA998x CODEC.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
Documentation/devicetree/bindings/sound/tda998x.txt | 14 ++++++++++++++
1 file changed, 14 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/tda998x.txt
diff --git a/Documentation/devicetree/bindings/sound/tda998x.txt b/Documentation/devicetree/bindings/sound/tda998x.txt
new file mode 100644
index 0000000..30273a6
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tda998x.txt
@@ -0,0 +1,14 @@
+Device-Tree bindings for the NXP TDA998x HDMI transmitter
+
+Required properties:
+ - compatible: must be "nxp,tda998x-codec".
+ - audio-ports: one or two values.
+ The first value defines the I2S input port.
+ The second one, if present, defines the S/PDIF input port.
+
+Example node:
+
+ hdmi_codec: hdmi-codec {
+ compatible = "nxp,tda998x-codec";
+ audio-ports = <0x03>, <0x04>;
+ };
--
1.8.5.3
^ permalink raw reply related
* [PATCH 6/9] PPC: remove redundant cpuidle_idle_call()
From: Daniel Lezcano @ 2014-01-27 8:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390802904-28399-7-git-send-email-nicolas.pitre@linaro.org>
On 01/27/2014 07:08 AM, Nicolas Pitre wrote:
> The core idle loop now takes care of it. However a few things need
> checking:
>
> - Invocation of cpuidle_idle_call() in pseries_lpar_idle() happened
> through arch_cpu_idle() and was therefore always preceded by a call
> to ppc64_runlatch_off(). To preserve this property now that
> cpuidle_idle_call() is invoked directly from core code, a call to
> ppc64_runlatch_off() has been added to idle_loop_prolog() in
> platforms/pseries/processor_idle.c.
>
> - Similarly, cpuidle_idle_call() was followed by ppc64_runlatch_off()
> so a call to the later has been added to idle_loop_epilog().
>
> - And since arch_cpu_idle() always made sure to re-enable IRQs if they
> were not enabled, this is now
> done in idle_loop_epilog() as well.
>
> The above was made in order to keep the execution flow close to the
> original. I don't know if that was strictly necessary. Someone well
> aquainted with the platform details might find some room for possible
> optimizations.
>
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
Added Preeti U Murthy as recipient.
> ---
> arch/powerpc/platforms/pseries/processor_idle.c | 5 ++++
> arch/powerpc/platforms/pseries/setup.c | 34 ++++++++++---------------
> 2 files changed, 19 insertions(+), 20 deletions(-)
>
> diff --git a/arch/powerpc/platforms/pseries/processor_idle.c b/arch/powerpc/platforms/pseries/processor_idle.c
> index a166e38bd6..72ddfe3d2f 100644
> --- a/arch/powerpc/platforms/pseries/processor_idle.c
> +++ b/arch/powerpc/platforms/pseries/processor_idle.c
> @@ -33,6 +33,7 @@ static struct cpuidle_state *cpuidle_state_table;
>
> static inline void idle_loop_prolog(unsigned long *in_purr)
> {
> + ppc64_runlatch_off();
> *in_purr = mfspr(SPRN_PURR);
> /*
> * Indicate to the HV that we are idle. Now would be
> @@ -49,6 +50,10 @@ static inline void idle_loop_epilog(unsigned long in_purr)
> wait_cycles += mfspr(SPRN_PURR) - in_purr;
> get_lppaca()->wait_state_cycles = cpu_to_be64(wait_cycles);
> get_lppaca()->idle = 0;
> +
> + if (irqs_disabled())
> + local_irq_enable();
> + ppc64_runlatch_on();
> }
>
> static int snooze_loop(struct cpuidle_device *dev,
> diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
> index c1f1908587..7604c19d54 100644
> --- a/arch/powerpc/platforms/pseries/setup.c
> +++ b/arch/powerpc/platforms/pseries/setup.c
> @@ -39,7 +39,6 @@
> #include <linux/irq.h>
> #include <linux/seq_file.h>
> #include <linux/root_dev.h>
> -#include <linux/cpuidle.h>
> #include <linux/of.h>
> #include <linux/kexec.h>
>
> @@ -356,29 +355,24 @@ early_initcall(alloc_dispatch_log_kmem_cache);
>
> static void pseries_lpar_idle(void)
> {
> - /* This would call on the cpuidle framework, and the back-end pseries
> - * driver to go to idle states
> + /*
> + * Default handler to go into low thread priority and possibly
> + * low power mode by cedeing processor to hypervisor
> */
> - if (cpuidle_idle_call()) {
> - /* On error, execute default handler
> - * to go into low thread priority and possibly
> - * low power mode by cedeing processor to hypervisor
> - */
>
> - /* Indicate to hypervisor that we are idle. */
> - get_lppaca()->idle = 1;
> + /* Indicate to hypervisor that we are idle. */
> + get_lppaca()->idle = 1;
>
> - /*
> - * Yield the processor to the hypervisor. We return if
> - * an external interrupt occurs (which are driven prior
> - * to returning here) or if a prod occurs from another
> - * processor. When returning here, external interrupts
> - * are enabled.
> - */
> - cede_processor();
> + /*
> + * Yield the processor to the hypervisor. We return if
> + * an external interrupt occurs (which are driven prior
> + * to returning here) or if a prod occurs from another
> + * processor. When returning here, external interrupts
> + * are enabled.
> + */
> + cede_processor();
>
> - get_lppaca()->idle = 0;
> - }
> + get_lppaca()->idle = 0;
> }
>
> /*
>
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [PATCH 7/9] SH: remove redundant cpuidle_idle_call()
From: Daniel Lezcano @ 2014-01-27 8:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390802904-28399-8-git-send-email-nicolas.pitre@linaro.org>
On 01/27/2014 07:08 AM, Nicolas Pitre wrote:
> The core idle loop now takes care of it.
>
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---
> arch/sh/kernel/idle.c | 4 +---
> 1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c
> index 2ea4483fd7..be616ee0cf 100644
> --- a/arch/sh/kernel/idle.c
> +++ b/arch/sh/kernel/idle.c
> @@ -16,7 +16,6 @@
> #include <linux/thread_info.h>
> #include <linux/irqflags.h>
> #include <linux/smp.h>
> -#include <linux/cpuidle.h>
> #include <linux/atomic.h>
> #include <asm/pgalloc.h>
> #include <asm/smp.h>
> @@ -40,8 +39,7 @@ void arch_cpu_idle_dead(void)
>
> void arch_cpu_idle(void)
> {
> - if (cpuidle_idle_call())
> - sh_idle();
> + sh_idle();
> }
>
> void __init select_idle_routine(void)
>
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [PATCH 8/9] X86: remove redundant cpuidle_idle_call()
From: Daniel Lezcano @ 2014-01-27 8:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390802904-28399-9-git-send-email-nicolas.pitre@linaro.org>
On 01/27/2014 07:08 AM, Nicolas Pitre wrote:
> The core idle loop now takes care of it.
>
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---
> arch/x86/kernel/process.c | 5 +----
> 1 file changed, 1 insertion(+), 4 deletions(-)
>
> diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
> index 3fb8d95ab8..4505e2a950 100644
> --- a/arch/x86/kernel/process.c
> +++ b/arch/x86/kernel/process.c
> @@ -298,10 +298,7 @@ void arch_cpu_idle_dead(void)
> */
> void arch_cpu_idle(void)
> {
> - if (cpuidle_idle_call())
> - x86_idle();
> - else
> - local_irq_enable();
For the record, it was pointless to enable the local irq here because it
is handled by the cpuidle framework when exiting the idle state.
> + x86_idle();
> }
>
> /*
>
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [PATCH 1/3] mmc: add support for power-on sequencing through DT
From: Jyri Sarha @ 2014-01-27 8:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOMZO5DdTP0gimwdsBUZK3wXrnUd2FN3w-FszLQkvCwM8gvPpg@mail.gmail.com>
On 01/24/2014 07:35 PM, Fabio Estevam wrote:
> On Mon, Jan 20, 2014 at 2:48 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
>
>> So far so good. Now, what about this external oscillator which has its
>> own separate power control. My immediate thought is that this can be
>> specified via card_ext_clock - I would simply need to declare a fixed-rate
>> clock with either a regulator (power switch) controlled via a gpio (which
>> would probably be closer to the hardware) or a gpio as an enable... ah,
>> that requires me to write a common clock driver for that bit since this
>> is currently not modelled by CCF...
>
> Jiry Sarha posted a gpio controlled clock proposal:
> http://www.spinics.net/lists/devicetree/msg16651.html
>
I have not received too much feedback to my patch yet. CCF is a bit new
territory to me, but I think having a separate stackable clk-gpio would
be more flexible than having the gpio property implemented in
clk-fixed-rate.
Anyway, I am happy do it either way as long as I can get a gpio
-controlled clock implementation into the main line.
Cheers,
Jyri
^ permalink raw reply
* [PATCH 1/2] ARM: dts: imx6: edmqmx6: fix wrong usbotg pingroup
From: Sascha Hauer @ 2014-01-27 8:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390419567-2643-2-git-send-email-silvio.fricke@gmail.com>
On Wed, Jan 22, 2014 at 08:39:26PM +0100, Silvio F wrote:
> Signed-off-by: Silvio F <silvio.fricke@gmail.com>
Verified this on the schematics, so:
Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
> index b8a1ff4..6706d1b 100644
> --- a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
> +++ b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
> @@ -266,7 +266,7 @@
> };
>
> pinctrl_usbotg: usbotggrp {
> - fsl,pins = <MX6QDL_USBOTG_PINGRP1>;
> + fsl,pins = <MX6QDL_USBOTG_PINGRP2>;
> };
>
> pinctrl_usdhc3: usdhc3grp {
> --
> 1.8.5.2
>
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH 4/4] ASoC: tda998x: adjust the audio hw parameters from EDID
From: Jean-Francois Moine @ 2014-01-27 8:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1390813480.git.moinejf@free.fr>
The supported audio parameters are described in the EDID which is
received by the HDMI transmitter from the connected screen.
Use these ones to adjust the audio stream parameters.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
drivers/gpu/drm/i2c/tda998x_drv.c | 15 ++++++++
include/drm/i2c/tda998x.h | 1 +
sound/soc/codecs/tda998x.c | 79 ++++++++++++++++++++++++++++++++++++++-
3 files changed, 94 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 186c751..3c8b4d7 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -45,6 +45,8 @@ struct tda998x_priv {
wait_queue_head_t wq_edid;
volatile int wq_edid_wait;
struct drm_encoder *encoder;
+
+ u8 *eld;
};
#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
@@ -731,6 +733,14 @@ tda998x_configure_audio(struct tda998x_priv *priv,
}
/* tda998x codec interface */
+u8 *tda998x_audio_get_eld(struct i2c_client *client)
+{
+ struct tda998x_priv *priv = i2c_get_clientdata(client);
+
+ return priv->eld;
+}
+EXPORT_SYMBOL_GPL(tda998x_audio_get_eld);
+
void tda998x_audio_update(struct i2c_client *client,
int format,
int port)
@@ -1186,6 +1196,11 @@ tda998x_encoder_get_modes(struct drm_encoder *encoder,
drm_mode_connector_update_edid_property(connector, edid);
n = drm_add_edid_modes(connector, edid);
priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid);
+
+ /* keep the EDID as ELD for the audio subsystem */
+ drm_edid_to_eld(connector, edid);
+ priv->eld = connector->eld;
+
kfree(edid);
}
diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
index 0459931..64aaaa8 100644
--- a/include/drm/i2c/tda998x.h
+++ b/include/drm/i2c/tda998x.h
@@ -26,6 +26,7 @@ struct tda998x_encoder_params {
unsigned audio_sample_rate;
};
+u8 *tda998x_audio_get_eld(struct i2c_client *client);
void tda998x_audio_update(struct i2c_client *client,
int format,
int port);
diff --git a/sound/soc/codecs/tda998x.c b/sound/soc/codecs/tda998x.c
index d724f7d..500ac61 100644
--- a/sound/soc/codecs/tda998x.c
+++ b/sound/soc/codecs/tda998x.c
@@ -91,10 +91,79 @@ static int tda_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct tda_priv *priv = snd_soc_codec_get_drvdata(dai->codec);
+ u8 *eld = NULL;
+ static unsigned rates_mask[] = {
+ SNDRV_PCM_RATE_32000,
+ SNDRV_PCM_RATE_44100,
+ SNDRV_PCM_RATE_48000,
+ SNDRV_PCM_RATE_88200,
+ SNDRV_PCM_RATE_96000,
+ SNDRV_PCM_RATE_176400,
+ SNDRV_PCM_RATE_192000,
+ };
/* memorize the used DAI */
priv->dai_id = dai->id;
+ /* get the ELD from the tda998x driver */
+ if (!priv->i2c_client)
+ tda_get_encoder(priv);
+ if (priv->i2c_client)
+ eld = tda998x_audio_get_eld(priv->i2c_client);
+
+ /* adjust the hw params from the ELD (EDID) */
+ if (eld) {
+ struct snd_soc_dai_driver *dai_drv = dai->driver;
+ struct snd_soc_pcm_stream *stream = &dai_drv->playback;
+ u8 *sad;
+ int sad_count;
+ unsigned eld_ver, mnl, rates, rate_mask, i;
+ unsigned max_channels, fmt;
+ u64 formats;
+
+ eld_ver = eld[0] >> 3;
+ if (eld_ver != 2 && eld_ver != 31)
+ return 0;
+
+ mnl = eld[4] & 0x1f;
+ if (mnl > 16)
+ return 0;
+
+ sad_count = eld[5] >> 4;
+ sad = eld + 20 + mnl;
+
+ /* Start from the basic audio settings */
+ max_channels = 2;
+ rates = 0;
+ fmt = 0;
+ while (sad_count--) {
+ switch (sad[0] & 0x78) {
+ case 0x08: /* PCM */
+ max_channels = max(max_channels, (sad[0] & 7) + 1u);
+ rates |= sad[1];
+ fmt |= sad[2] & 0x07;
+ break;
+ }
+ sad += 3;
+ }
+
+ for (rate_mask = i = 0; i < ARRAY_SIZE(rates_mask); i++)
+ if (rates & 1 << i)
+ rate_mask |= rates_mask[i];
+ formats = 0;
+ if (fmt & 1)
+ formats |= SNDRV_PCM_FMTBIT_S16_LE;
+ if (fmt & 2)
+ formats |= SNDRV_PCM_FMTBIT_S20_3LE;
+ if (fmt & 4)
+ formats |= SNDRV_PCM_FMTBIT_S24_LE;
+
+ /* change the snd_soc_pcm_stream values of the driver */
+ stream->rates = rate_mask;
+ stream->channels_max = max_channels;
+ stream->formats = formats;
+ }
+
/* start the TDA998x audio */
return tda_start_stop(priv, 1);
}
@@ -193,9 +262,17 @@ static const struct snd_soc_codec_driver soc_codec_tda998x = {
static int tda998x_dev_probe(struct platform_device *pdev)
{
+ struct snd_soc_dai_driver *dai_drv;
+
+ /* copy the DAI driver to a writable area */
+ dai_drv = devm_kzalloc(&pdev->dev, sizeof(tda998x_dai), GFP_KERNEL);
+ if (!dai_drv)
+ return -ENOMEM;
+ memcpy(dai_drv, tda998x_dai, sizeof(tda998x_dai));
+
return snd_soc_register_codec(&pdev->dev,
&soc_codec_tda998x,
- tda998x_dai, ARRAY_SIZE(tda998x_dai));
+ dai_drv, ARRAY_SIZE(tda998x_dai));
}
static int tda998x_dev_remove(struct platform_device *pdev)
--
1.8.5.3
^ permalink raw reply related
* [PATCH v2 4/5] ASoC: tda998x: adjust the audio hw parameters from EDID
From: Jean-Francois Moine @ 2014-01-27 8:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1391081933.git.moinejf@free.fr>
The supported audio parameters are described in the EDID which is
received by the HDMI transmitter from the connected screen.
Use these ones to adjust the audio stream parameters.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
drivers/gpu/drm/i2c/tda998x_drv.c | 15 ++++++++
include/drm/i2c/tda998x.h | 1 +
sound/soc/codecs/tda998x.c | 79 ++++++++++++++++++++++++++++++++++++++-
3 files changed, 94 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 2643be4..92cbc40 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -46,6 +46,8 @@ struct tda998x_priv {
wait_queue_head_t wq_edid;
volatile int wq_edid_wait;
struct drm_encoder *encoder;
+
+ u8 *eld;
};
#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
@@ -732,6 +734,14 @@ tda998x_configure_audio(struct tda998x_priv *priv,
}
/* tda998x codec interface */
+u8 *tda998x_audio_get_eld(struct i2c_client *client)
+{
+ struct tda998x_priv *priv = i2c_get_clientdata(client);
+
+ return priv->eld;
+}
+EXPORT_SYMBOL_GPL(tda998x_audio_get_eld);
+
void tda998x_audio_update(struct i2c_client *client,
int format,
int port)
@@ -1186,6 +1196,11 @@ tda998x_encoder_get_modes(struct drm_encoder *encoder,
drm_mode_connector_update_edid_property(connector, edid);
n = drm_add_edid_modes(connector, edid);
priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid);
+
+ /* keep the EDID as ELD for the audio subsystem */
+ drm_edid_to_eld(connector, edid);
+ priv->eld = connector->eld;
+
kfree(edid);
}
diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
index 7e4806d..99387ae 100644
--- a/include/drm/i2c/tda998x.h
+++ b/include/drm/i2c/tda998x.h
@@ -27,6 +27,7 @@ struct tda998x_encoder_params {
unsigned audio_sample_rate;
};
+u8 *tda998x_audio_get_eld(struct i2c_client *client);
void tda998x_audio_update(struct i2c_client *client,
int format,
int port);
diff --git a/sound/soc/codecs/tda998x.c b/sound/soc/codecs/tda998x.c
index 585cdb6..7f21749 100644
--- a/sound/soc/codecs/tda998x.c
+++ b/sound/soc/codecs/tda998x.c
@@ -84,10 +84,79 @@ static int tda_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct tda_priv *priv = snd_soc_codec_get_drvdata(dai->codec);
+ u8 *eld = NULL;
+ static unsigned rates_mask[] = {
+ SNDRV_PCM_RATE_32000,
+ SNDRV_PCM_RATE_44100,
+ SNDRV_PCM_RATE_48000,
+ SNDRV_PCM_RATE_88200,
+ SNDRV_PCM_RATE_96000,
+ SNDRV_PCM_RATE_176400,
+ SNDRV_PCM_RATE_192000,
+ };
/* memorize the used DAI */
priv->dai_id = dai->id;
+ /* get the ELD from the tda998x driver */
+ if (!priv->i2c_client)
+ tda_get_encoder(priv);
+ if (priv->i2c_client)
+ eld = tda998x_audio_get_eld(priv->i2c_client);
+
+ /* adjust the hw params from the ELD (EDID) */
+ if (eld) {
+ struct snd_soc_dai_driver *dai_drv = dai->driver;
+ struct snd_soc_pcm_stream *stream = &dai_drv->playback;
+ u8 *sad;
+ int sad_count;
+ unsigned eld_ver, mnl, rates, rate_mask, i;
+ unsigned max_channels, fmt;
+ u64 formats;
+
+ eld_ver = eld[0] >> 3;
+ if (eld_ver != 2 && eld_ver != 31)
+ return 0;
+
+ mnl = eld[4] & 0x1f;
+ if (mnl > 16)
+ return 0;
+
+ sad_count = eld[5] >> 4;
+ sad = eld + 20 + mnl;
+
+ /* Start from the basic audio settings */
+ max_channels = 2;
+ rates = 0;
+ fmt = 0;
+ while (sad_count--) {
+ switch (sad[0] & 0x78) {
+ case 0x08: /* PCM */
+ max_channels = max(max_channels, (sad[0] & 7) + 1u);
+ rates |= sad[1];
+ fmt |= sad[2] & 0x07;
+ break;
+ }
+ sad += 3;
+ }
+
+ for (rate_mask = i = 0; i < ARRAY_SIZE(rates_mask); i++)
+ if (rates & 1 << i)
+ rate_mask |= rates_mask[i];
+ formats = 0;
+ if (fmt & 1)
+ formats |= SNDRV_PCM_FMTBIT_S16_LE;
+ if (fmt & 2)
+ formats |= SNDRV_PCM_FMTBIT_S20_3LE;
+ if (fmt & 4)
+ formats |= SNDRV_PCM_FMTBIT_S24_LE;
+
+ /* change the snd_soc_pcm_stream values of the driver */
+ stream->rates = rate_mask;
+ stream->channels_max = max_channels;
+ stream->formats = formats;
+ }
+
/* start the TDA998x audio */
return tda_start_stop(priv);
}
@@ -203,9 +272,17 @@ static const struct snd_soc_codec_driver soc_codec_tda998x = {
static int tda998x_dev_probe(struct platform_device *pdev)
{
+ struct snd_soc_dai_driver *dai_drv;
+
+ /* copy the DAI driver to a writable area */
+ dai_drv = devm_kzalloc(&pdev->dev, sizeof(tda998x_dai), GFP_KERNEL);
+ if (!dai_drv)
+ return -ENOMEM;
+ memcpy(dai_drv, tda998x_dai, sizeof(tda998x_dai));
+
return snd_soc_register_codec(&pdev->dev,
&soc_codec_tda998x,
- tda998x_dai, ARRAY_SIZE(tda998x_dai));
+ dai_drv, ARRAY_SIZE(tda998x_dai));
}
static int tda998x_dev_remove(struct platform_device *pdev)
--
1.9.rc1
^ permalink raw reply related
* [PATCH v3 4/5] ASoC: tda998x: adjust the audio hw parameters from EDID
From: Jean-Francois Moine @ 2014-01-27 8:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1391274627.git.moinejf@free.fr>
The supported audio parameters are described in the EDID which is
received by the HDMI transmitter from the connected screen.
Use these ones to adjust the audio stream parameters.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
drivers/gpu/drm/i2c/tda998x_drv.c | 15 ++++++++
include/drm/i2c/tda998x.h | 1 +
sound/soc/codecs/tda998x.c | 79 ++++++++++++++++++++++++++++++++++++++-
3 files changed, 94 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 68f0b7b..b833fa5 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -47,6 +47,8 @@ struct tda998x_priv {
wait_queue_head_t wq_edid;
volatile int wq_edid_wait;
struct drm_encoder *encoder;
+
+ u8 *eld;
};
#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
@@ -733,6 +735,14 @@ tda998x_configure_audio(struct tda998x_priv *priv,
}
/* tda998x codec interface */
+u8 *tda998x_audio_get_eld(struct i2c_client *client)
+{
+ struct tda998x_priv *priv = i2c_get_clientdata(client);
+
+ return priv->eld;
+}
+EXPORT_SYMBOL_GPL(tda998x_audio_get_eld);
+
void tda998x_audio_update(struct i2c_client *client,
int format,
int port)
@@ -1187,6 +1197,11 @@ tda998x_encoder_get_modes(struct drm_encoder *encoder,
drm_mode_connector_update_edid_property(connector, edid);
n = drm_add_edid_modes(connector, edid);
priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid);
+
+ /* keep the EDID as ELD for the audio subsystem */
+ drm_edid_to_eld(connector, edid);
+ priv->eld = connector->eld;
+
kfree(edid);
}
diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
index 7e4806d..99387ae 100644
--- a/include/drm/i2c/tda998x.h
+++ b/include/drm/i2c/tda998x.h
@@ -27,6 +27,7 @@ struct tda998x_encoder_params {
unsigned audio_sample_rate;
};
+u8 *tda998x_audio_get_eld(struct i2c_client *client);
void tda998x_audio_update(struct i2c_client *client,
int format,
int port);
diff --git a/sound/soc/codecs/tda998x.c b/sound/soc/codecs/tda998x.c
index 34d7086..0493163 100644
--- a/sound/soc/codecs/tda998x.c
+++ b/sound/soc/codecs/tda998x.c
@@ -64,10 +64,79 @@ static int tda_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct tda_priv *priv = snd_soc_codec_get_drvdata(dai->codec);
+ u8 *eld = NULL;
+ static unsigned rates_mask[] = {
+ SNDRV_PCM_RATE_32000,
+ SNDRV_PCM_RATE_44100,
+ SNDRV_PCM_RATE_48000,
+ SNDRV_PCM_RATE_88200,
+ SNDRV_PCM_RATE_96000,
+ SNDRV_PCM_RATE_176400,
+ SNDRV_PCM_RATE_192000,
+ };
/* memorize the used DAI */
priv->dai_id = dai->id;
+ /* get the ELD from the tda998x driver */
+ if (!priv->i2c_client)
+ tda_get_encoder(priv);
+ if (priv->i2c_client)
+ eld = tda998x_audio_get_eld(priv->i2c_client);
+
+ /* adjust the hw params from the ELD (EDID) */
+ if (eld) {
+ struct snd_soc_dai_driver *dai_drv = dai->driver;
+ struct snd_soc_pcm_stream *stream = &dai_drv->playback;
+ u8 *sad;
+ int sad_count;
+ unsigned eld_ver, mnl, rates, rate_mask, i;
+ unsigned max_channels, fmt;
+ u64 formats;
+
+ eld_ver = eld[0] >> 3;
+ if (eld_ver != 2 && eld_ver != 31)
+ return 0;
+
+ mnl = eld[4] & 0x1f;
+ if (mnl > 16)
+ return 0;
+
+ sad_count = eld[5] >> 4;
+ sad = eld + 20 + mnl;
+
+ /* Start from the basic audio settings */
+ max_channels = 2;
+ rates = 0;
+ fmt = 0;
+ while (sad_count--) {
+ switch (sad[0] & 0x78) {
+ case 0x08: /* PCM */
+ max_channels = max(max_channels, (sad[0] & 7) + 1u);
+ rates |= sad[1];
+ fmt |= sad[2] & 0x07;
+ break;
+ }
+ sad += 3;
+ }
+
+ for (rate_mask = i = 0; i < ARRAY_SIZE(rates_mask); i++)
+ if (rates & 1 << i)
+ rate_mask |= rates_mask[i];
+ formats = 0;
+ if (fmt & 1)
+ formats |= SNDRV_PCM_FMTBIT_S16_LE;
+ if (fmt & 2)
+ formats |= SNDRV_PCM_FMTBIT_S20_3LE;
+ if (fmt & 4)
+ formats |= SNDRV_PCM_FMTBIT_S24_LE;
+
+ /* change the snd_soc_pcm_stream values of the driver */
+ stream->rates = rate_mask;
+ stream->channels_max = max_channels;
+ stream->formats = formats;
+ }
+
/* start the TDA998x audio */
return tda_start_stop(priv);
}
@@ -182,9 +251,17 @@ static const struct snd_soc_codec_driver soc_codec_tda998x = {
static int tda998x_dev_probe(struct platform_device *pdev)
{
+ struct snd_soc_dai_driver *dai_drv;
+
+ /* copy the DAI driver to a writable area */
+ dai_drv = devm_kzalloc(&pdev->dev, sizeof(tda998x_dai), GFP_KERNEL);
+ if (!dai_drv)
+ return -ENOMEM;
+ memcpy(dai_drv, tda998x_dai, sizeof(tda998x_dai));
+
return snd_soc_register_codec(&pdev->dev,
&soc_codec_tda998x,
- tda998x_dai, ARRAY_SIZE(tda998x_dai));
+ dai_drv, ARRAY_SIZE(tda998x_dai));
}
static int tda998x_dev_remove(struct platform_device *pdev)
--
1.9.rc1
^ permalink raw reply related
* [PATCH 2/2] ARM: dts: imx6: edmqmx6: remove wrong gpio in usb_otg_vbus regulator
From: Sascha Hauer @ 2014-01-27 8:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390419567-2643-3-git-send-email-silvio.fricke@gmail.com>
On Wed, Jan 22, 2014 at 08:39:27PM +0100, Silvio F wrote:
> Signed-off-by: Silvio F <silvio.fricke@gmail.com>
> ---
> arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
> index 6706d1b..de54e46 100644
> --- a/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
> +++ b/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts
> @@ -46,7 +46,6 @@
> regulator-name = "usb_otg_vbus";
> regulator-min-microvolt = <5000000>;
> regulator-max-microvolt = <5000000>;
> - gpio = <&gpio7 12 0>;
This gpio drives a switch between SoCs USB D+/D- lines and the external
connector, so using a regulator here is the wrong approach. The question
now is: What is the correct approach to make sure the switch is closed
when needed? How does it work now? Is the switch on by reset default?
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH 1/3] mmc: add support for power-on sequencing through DT
From: Chen-Yu Tsai @ 2014-01-27 8:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52E61C28.1020207@ti.com>
Hi,
On Mon, Jan 27, 2014 at 4:43 PM, Jyri Sarha <jsarha@ti.com> wrote:
> On 01/24/2014 07:35 PM, Fabio Estevam wrote:
>>
>> On Mon, Jan 20, 2014 at 2:48 PM, Russell King - ARM Linux
>> <linux@arm.linux.org.uk> wrote:
>>
>>> So far so good. Now, what about this external oscillator which has its
>>> own separate power control. My immediate thought is that this can be
>>> specified via card_ext_clock - I would simply need to declare a
>>> fixed-rate
>>> clock with either a regulator (power switch) controlled via a gpio (which
>>> would probably be closer to the hardware) or a gpio as an enable... ah,
>>> that requires me to write a common clock driver for that bit since this
>>> is currently not modelled by CCF...
>>
>>
>> Jiry Sarha posted a gpio controlled clock proposal:
>> http://www.spinics.net/lists/devicetree/msg16651.html
>>
>
> I have not received too much feedback to my patch yet. CCF is a bit new
> territory to me, but I think having a separate stackable clk-gpio would be
> more flexible than having the gpio property implemented in clk-fixed-rate.
Not sure where stacking external clocks would be used, but sounds like a
fixed factor clock? Maybe you should add DT support to that if that's what
you need or have.
> Anyway, I am happy do it either way as long as I can get a gpio -controlled
> clock implementation into the main line.
Cheers,
ChenYu
^ permalink raw reply
* [PATCH 0/4] add a TDA998x CODEC
From: Jean-Francois Moine @ 2014-01-27 9:04 UTC (permalink / raw)
To: linux-arm-kernel
The TDA998x HDMI transmitter accepts audio input from either I2S or S/PDIF.
Theses inputs have different intrinsic constraints and these constraints
may be modified by the audio parameters of the connected video device.
The choice of I2S or S/PDIF may be the done by the user or by automatic
processing (DPCM?) at each audio starting time. This asks for a dynamic
audio input switch in the HDMI driver.
This patch series implements the TDA998x specific CODEC.
A simple function call mechanism is used for exchanges between the
CODEC and the HDMI driver.
Jean-Francois Moine (4):
drm/i2c: tda998x: add a function for dynamic audio input switch
ASoC: tda998x: add a codec driver for TDA998x
ASoC: tda998x: add DT documentation
ASoC: tda998x: adjust the audio hw parameters from EDID
.../devicetree/bindings/sound/tda998x.txt | 14 +
drivers/gpu/drm/i2c/tda998x_drv.c | 58 +++-
include/drm/i2c/tda998x.h | 8 +-
sound/soc/codecs/Kconfig | 7 +
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/tda998x.c | 304 +++++++++++++++++++++
6 files changed, 390 insertions(+), 3 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/tda998x.txt
create mode 100644 sound/soc/codecs/tda998x.c
--
1.8.5.3
^ permalink raw reply
* [PATCH 2/4] ARM: dts: cm-fx6: add SATA support
From: Igor Grinberg @ 2014-01-27 9:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140127073754.GB4765@S2101-09.ap.freescale.net>
On 01/27/14 09:37, Shawn Guo wrote:
> On Tue, Jan 21, 2014 at 06:13:30PM +0200, Igor Grinberg wrote:
>> Enable SATA on cm-fx6.
>>
>> Signed-off-by: Igor Grinberg <grinberg@compulab.co.il>
>> ---
>> arch/arm/boot/dts/imx6q-cm-fx6.dts | 4 ++++
>> 1 file changed, 4 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/imx6q-cm-fx6.dts b/arch/arm/boot/dts/imx6q-cm-fx6.dts
>> index 94cc6b5..07f90a5 100644
>> --- a/arch/arm/boot/dts/imx6q-cm-fx6.dts
>> +++ b/arch/arm/boot/dts/imx6q-cm-fx6.dts
>> @@ -69,3 +69,7 @@
>> pinctrl-0 = <&pinctrl_uart4>;
>> status = "okay";
>> };
>> +
>> +&sata {
>> + status = "okay";
>> +};
>
> Please sort these labeled nodes alphabetically.
Ok.
I'll wait for the "pingrp macros" to settle down and resend.
Thanks!
--
Regards,
Igor.
^ permalink raw reply
* imx6: usbhc2/3 and HSIC
From: Christian Gmeiner @ 2014-01-27 9:22 UTC (permalink / raw)
To: linux-arm-kernel
Hi all...
does anyone used the usbhc2 or usbhc3 in HSIC mode? I am trying my
luck but I do not
get it to work. Is there anything special I need to take care of?
thanks
--
Christian Gmeiner, MSc
^ permalink raw reply
* imx6: usbhc2/3 and HSIC
From: Lucas Stach @ 2014-01-27 9:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAH9NwWckD5Rmr9oW2Gr071V2p0FjRJcttYpB4qQNEWTxDEJ6qw@mail.gmail.com>
Hi Christian,
Am Montag, den 27.01.2014, 10:22 +0100 schrieb Christian Gmeiner:
> Hi all...
>
> does anyone used the usbhc2 or usbhc3 in HSIC mode? I am trying my
> luck but I do not
> get it to work. Is there anything special I need to take care of?
>
I remember we had this working on a board back in the 3.10 days. The
only thing I remember which is specific to HSIC is in the attached
patch. This isn't really clean and should be done in a better way for
mainline, but maybe it provides some pointers for you.
Regards,
Lucas
------------------------------>8------------------------------------
>From 5af9a0597a329a2c4af012fd0fb54f525b45f625 Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer@pengutronix.de>
Date: Mon, 28 Jan 2013 13:08:08 +0100
Subject: [PATCH] ARM/USB i.MX6: Add HSIC support
On i.MX6 HOST2 and HOST3 are HSIC only ports. These have the special
requirement that they need the to set a pullup on the strobe line
after initialization.
Fortunately only one routing option for the HSIC ports exist, so we
can put the pinmux setup completely into the i.MX6 dtsi file.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
arch/arm/boot/dts/imx6q.dtsi | 32 ++++++++++++++++++++++++++++++++
arch/arm/boot/dts/imx6qdl.dtsi | 8 ++++++++
drivers/usb/chipidea/ci13xxx_imx.c | 10 ++++++++++
drivers/usb/chipidea/usbmisc_imx.c | 5 +++++
4 files changed, 55 insertions(+)
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 21e675848bd1..18ffb5f91439 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -253,6 +253,38 @@
};
};
+ usbh2 {
+ pinctrl_usbh2: usbh2grp {
+ fsl,pins = <
+ MX6Q_PAD_RGMII_TXC__USB_H2_DATA 0x13030
+ MX6Q_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x13030
+ >;
+ };
+
+ pinctrl_usbh2_enabled: usbh2grp-enabled {
+ fsl,pins = <
+ MX6Q_PAD_RGMII_TXC__USB_H2_DATA 0x13030
+ MX6Q_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x17030
+ >;
+ };
+ };
+
+ usbh3 {
+ pinctrl_usbh3: usbh3grp-1 {
+ fsl,pins = <
+ MX6Q_PAD_RGMII_RX_CTL__USB_H3_DATA 0x13030
+ MX6Q_PAD_RGMII_RXC__USB_H3_STROBE 0x13030
+ >;
+ };
+
+ pinctrl_usbh3_enabled: usbh3grp-enabled {
+ fsl,pins = <
+ MX6Q_PAD_RGMII_RX_CTL__USB_H3_DATA 0x13030
+ MX6Q_PAD_RGMII_RXC__USB_H3_STROBE 0x17030
+ >;
+ };
+ };
+
usdhc2 {
pinctrl_usdhc2_1: usdhc2grp-1 {
fsl,pins = <
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 9e8296e4c343..884c512eff04 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -626,7 +626,11 @@
interrupts = <0 41 0x04>;
clocks = <&clks 162>;
fsl,usbmisc = <&usbmisc 2>;
+ phy_type = "hsic";
status = "disabled";
+ pinctrl-names = "default", "enabled";
+ pinctrl-0 = <&pinctrl_usbh2>;
+ pinctrl-1 = <&pinctrl_usbh2_enabled>;
};
usbh3: usb at 02184600 {
@@ -635,7 +639,11 @@
interrupts = <0 42 0x04>;
clocks = <&clks 162>;
fsl,usbmisc = <&usbmisc 3>;
+ phy_type = "hsic";
status = "disabled";
+ pinctrl-names = "default", "enabled";
+ pinctrl-0 = <&pinctrl_usbh3>;
+ pinctrl-1 = <&pinctrl_usbh3_enabled>;
};
usbmisc: usbmisc: usbmisc at 02184800 {
diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c
index 2ec9052c7bb7..f770328d4901 100644
--- a/drivers/usb/chipidea/ci13xxx_imx.c
+++ b/drivers/usb/chipidea/ci13xxx_imx.c
@@ -99,6 +99,7 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
struct resource *res;
int ret;
struct usb_phy *phy;
+ struct pinctrl *pinctrl;
if (of_find_property(pdev->dev.of_node, "fsl,usbmisc", NULL)
&& !usbmisc_ops)
@@ -197,6 +198,15 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
pm_runtime_no_callbacks(&pdev->dev);
pm_runtime_enable(&pdev->dev);
+ pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (!IS_ERR(pinctrl)) {
+ struct pinctrl_state *state;
+
+ state = pinctrl_lookup_state(pinctrl, "enabled");
+ if (!IS_ERR(state))
+ pinctrl_select_state(pinctrl, state);
+ }
+
return 0;
disable_device:
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index 588bae8eef5e..e29c5aa51b07 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -145,6 +145,11 @@ static int usbmisc_imx6q_init(struct device *dev)
spin_unlock_irqrestore(&usbmisc->lock, flags);
}
+ if (usbdev->index == 2 || usbdev->index == 3) {
+ writel(0x00003000, usbmisc->base + usbdev->index * 4);
+ writel(0x80001842, usbmisc->base + 0x8 + usbdev->index * 4);
+ }
+
return 0;
}
--
1.8.5.2
--
Pengutronix e.K. | Lucas Stach |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-5076 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply related
* [PATCH v2 2/4] pinctrl: st: Add software edge trigger interrupt support.
From: Linus Walleij @ 2014-01-27 9:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140124082859.GJ8586@lee--X1>
On Fri, Jan 24, 2014 at 9:28 AM, Lee Jones <lee.jones@linaro.org> wrote:
>> > +/*
>> > + * As edge triggers are not supported at hardware level, it is supported by
>> > + * software by exploiting the level trigger support in hardware.
>>
>> (...)
>>
>> All this is quite hard to understand. Maybe it's just because
>> it's hard overall. Edge triggers are not supported by hardware
>> so we use the hardware edge trigger support?
>>
>> That is a bit oxymoronic...
>
> That's not what is says. Read it again. :)
Argh yeah I was wrong ... it's perfectly consistent with the
implementation. Sorry for being such a slow brain this last
friday.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 1/3] mmc: add support for power-on sequencing through DT
From: Jyri Sarha @ 2014-01-27 9:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAGb2v64RbXZS_5nvXf9_t=Q=+zrBa=eF-f-xcZTxaMLYSQkNrw@mail.gmail.com>
On 01/27/2014 10:54 AM, Chen-Yu Tsai wrote:
> Hi,
>
> On Mon, Jan 27, 2014 at 4:43 PM, Jyri Sarha <jsarha@ti.com> wrote:
>> On 01/24/2014 07:35 PM, Fabio Estevam wrote:
...
>> I have not received too much feedback to my patch yet. CCF is a bit new
>> territory to me, but I think having a separate stackable clk-gpio would be
>> more flexible than having the gpio property implemented in clk-fixed-rate.
>
> Not sure where stacking external clocks would be used, but sounds like a
> fixed factor clock? Maybe you should add DT support to that if that's what
> you need or have.
>
Ah, but then there is also the problem of having to change
clk_register_fixed_rate() in the CCF api, which is called from all over
the place.
Of course I could add a new clk_register_fixed_rate_gpio(), but still it
does not look to me like the way to go.
Cheers,
Jyri
^ permalink raw reply
* [PATCHv2] arm64: Add CONFIG_CC_STACKPROTECTOR
From: Will Deacon @ 2014-01-27 9:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390604955-6309-1-git-send-email-lauraa@codeaurora.org>
Hi Laura,
On Fri, Jan 24, 2014 at 11:09:15PM +0000, Laura Abbott wrote:
> arm64 currently lacks support for -fstack-protector. Add
> similar functionality to arm to detect stack corruption.
[...]
> +/*
> + * Initialize the stackprotector canary value.
> + *
> + * NOTE: this must only be called from functions that never return,
> + * and it must always be inlined.
> + */
> +static __always_inline void boot_init_stack_canary(void)
> +{
> + unsigned long canary;
> +
> + /* Try to get a semi random initial value. */
> + get_random_bytes(&canary, sizeof(canary));
> + canary ^= LINUX_VERSION_CODE;
> +
> + current->stack_canary = canary;
Do we actually need this line now?
Will
^ permalink raw reply
* [PATCH 1/3] mmc: add support for power-on sequencing through DT
From: Ulf Hansson @ 2014-01-27 10:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52E54540.8080304@gmail.com>
On 26 January 2014 18:26, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> On 21.01.2014 19:34, Tomasz Figa wrote:
>>
>> Hi,
>>
>> On 20.01.2014 04:56, Olof Johansson wrote:
>>>
>>> This patch enables support for power-on sequencing of SDIO peripherals
>>> through DT.
>>>
>>> In general, it's quite common that wifi modules and other similar
>>> peripherals have several signals in addition to the SDIO interface that
>>> needs wiggling before the module will power on. It's common to have a
>>> reference clock, one or several power rails and one or several lines
>>> for reset/enable type functions.
>>>
>>> The binding as written today introduces a number of reset gpios,
>>> a regulator and a clock specifier. The code will handle up to 2 gpio
>>> reset lines, but it's trivial to increase to more than that if needed
>>> at some point.
>>>
>>> Implementation-wise, the MMC core has been changed to handle this during
>>> host power up, before the host interface is powered on. I have not yet
>>> implemented the power-down side, I wanted people to have a chance for
>>> reporting back w.r.t. issues (or comments on the bindings) first.
>>>
>>> I have not tested the regulator portion, since the system and module
>>> I'm working on doesn't need one (Samsung Chromebook with Marvell
>>> 8797-based wifi). Testing of those portions (and reporting back) would
>>> be appreciated.
>>
>>
>> While I fully agree that this is an important problem that needs to be
>> solved, I really don't think this is the right way, because:
>>
>> a) power-up sequence is really specific to the MMC device and often it's
>> not simply a matter of switching on one regulator or one clock, e.g.
>> specific time constraints need to be met.
>>
>> b) you can have WLAN chips in which SDIO is just one of the options to
>> use as host interface, which may be also HSIC, I2C or UART. Really. See
>> [1].
>>
>> c) this is leaking device specific details to generic host code, which
>> isn't really elegant.
>>
>> Now, to make this a bit more constructive, [2] is a solution that I came
>> up with (not perfect either), which simply adds a separate platform
>> device for the low level part of the chip. I believe this is a better
>> solution because:
>>
>> a) you can often see such WLAN/BT combo chip as a set of separate
>> devices, e.g. SDIO WLAN, UART BT and a simple PMIC or management IC,
>> which provides power/reset control, out of band signalling and etc. for
>> the first two, so it isn't that bad to have a separate device node for
>> the last one,
>>
>> b) you have full freedom of defining your DT binding with whatever data
>> you need, any number of clocks, regulators, GPIOs and even out of band
>> interrupts (IMHO the most important one).
>>
>> c) you can implement power-on, power-off sequences as needed for your
>> particular device,
>>
>> d) you have full separation of device-specific data from MMC core (or
>> any other subsystem simply used as a way to perform I/O to the chip).
>>
>> Now what's missing there is a way to signal the MMC core or any other
>> transport that a device showed up and the controller should be woken up
>> out of standby and scan of the bus initialized. This could be done by
>> explicitly specifying the device as a subnode of the
>> MMC/UART/USB(HSIC)/I2C or whatever with a link (phandle) to the power
>> controller of the chip or the other way around - a link to the
>> MMC/UART/... controller from the power controller node.
>
>
> I've looked a bit around MMC core code and got some basic idea how things
> look. I will definitely need some guidance, or at least some opinions, from
> MMC guys, as some MMC core changes are unavoidable.
>
> Now, the device-specific code is not really an issue, existing drivers
> usually already have their ways of powering the chips on and off, based on
> platform data. Everything needed here is to retrieve needed resources
> (GPIOs, clocks, regulators) using DT, which should be trivial.
>
> The worse part is the interaction between MMC and power controller driver
> (the platform driver part of WLAN driver, if you look at brcmfmac as an
> example). I believe that we need following things:
>
> a) A way to tell the MMC controller that there is no card detection
> mechanism available on given slot and it also should not be polling the slot
> to check card presence. Something like a "manual card detect" that would be
> triggered by another kernel entity that controls whether the MMC device is
> present (i.e. WLAN driver). We already have "broken-cd" property, but it
> only implies the former, wasting time on needless polling.
There is already a host capability that I think we could use to handle
this. MMC_CAP_NONREMOVABLE, the corresponding DT binding string is
"non-removable", and it may be set per host device.
Using this cap means the mmc_rescan process that runs to detect new
cards, will only be executed once and during boot. So, we need to make
sure all resources and powers are provided to the card at this point.
Otherwise the card will not be detected.
In the SDIO case, to save power, the SDIO func driver may use runtime
PM to tell the mmc core power about whether the card needs to be
powered. Typically from the WLAN driver's probe() and "interface
up/down" the runtime PM reference for the SDIO func device, should be
adjusted with pm_runtime_get|put.
>
> b) A mechanism to bind the power controller to used MMC slot. Something like
> "mmc-bus = <&mmc2>;" property in device node of the power controller and a
> function like of_find_mmc_controller_by_node(), which would be an MMC
> counterpart of I2C's of_find_i2c_adapter_by_node(). To avoid races, it
> should probably take a reference on MMC host that would have to be dropped
> explicitly whenever it is not needed anymore.
I suppose an "MMC slot" can be translated to "MMC host"?
What I am trying to understand is how the mmc core (or if we push it
to be handled from the mmc host's .set_ios callback) shall be able to
tell the power controller driver to enable/disable it's resources.
Somehow we need the struct device available to handle that. Then I
guess operating on it using runtime PM would be a solution that would
be quite nice!?
>
> c) A method to notify the MMC subsystem that card presence has changed. We
> already have something like this in drivers/mmc/core/slot-gpio.c, but used
> for a simple GPIO-based card detection. If the main part of
> mmc_gpio_cd_irqt() could be turned into an exported helper, e.g.
> mmc_force_card_detect(host) then basically we would have everything needed.
I am not sure I understand why this is needed. I think it would be
more convenient to use MMC_CAP_NONREMOVABLE instead as stated earlier.
But please elaborate, I might have missed something.
>
> Unfortunately, I don't have more time left for today to create patches and
> test them, so for now, I'd like to hear opinion of MMC maintainers about
> this approach. Do you find this acceptable?
>
> By the way, it seems like slot-gpio.c could replace a lot of custom GPIO
> card detection code used in MMC host drivers, e.g. sdhci-s3c. Is there any
> reason why it couldn't?
I suppose most host driver's should convert to the slot-gpio API, it's
is just a matter of someone to send the patches. :-)
Kind regards
Ulf Hansson
>
> Best regards,
> Tomasz
^ permalink raw reply
* [PATCH v10] clk: add MOXA ART SoCs clock driver
From: Mark Rutland @ 2014-01-27 10:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390308261-4026-1-git-send-email-jonas.jensen@gmail.com>
On Tue, Jan 21, 2014 at 12:44:21PM +0000, Jonas Jensen wrote:
> MOXA ART SoCs allow to determine PLL output and APB frequencies
> by reading registers holding multiplier and divisor information.
>
> Add a clock driver for this SoC.
>
> Signed-off-by: Jonas Jensen <jonas.jensen@gmail.com>
> ---
>
> Notes:
> Thanks for the reply Sudeep, changes are in v10.
>
> Changes since v9:
>
> 1. rebase drivers/clk/Makefile to next-20140121
> 2. remove unnecessary switch
> 3. use a more elaborate commit message
>
> Applies to next-20140121
>
> .../bindings/clock/moxa,moxart-clock.txt | 48 +++++++++++
> drivers/clk/Makefile | 1 +
> drivers/clk/clk-moxart.c | 99 ++++++++++++++++++++++
> 3 files changed, 148 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt
> create mode 100644 drivers/clk/clk-moxart.c
>
> diff --git a/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt b/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt
> new file mode 100644
> index 0000000..242e3fc
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt
> @@ -0,0 +1,48 @@
> +Device Tree Clock bindings for arch-moxart
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +MOXA ART SoCs allow to determine PLL output and APB frequencies
> +by reading registers holding multiplier and divisor information.
> +
> +
> +PLL:
> +
> +Required properties:
> +- compatible : Must be "moxa,moxart-pll-clock"
> +- #clock-cells : Should be 0
> +- reg : Should contain registers location and length
> +- clocks : Should contain phandle to parent clock
Nit: clocks are referenced with a clock-specifier (which might be zero
cells), not just a phandle.
How about:
clocks: should contain a phandle + clock-specifier for the parent clock
> +
> +Optional properties:
> +- clock-output-names : Should contain clock name
> +
> +
> +APB:
> +
> +Required properties:
> +- compatible : Must be "moxa,moxart-apb-clock"
> +- #clock-cells : Should be 0
> +- reg : Should contain registers location and length
> +- clocks : Should contain phandle to parent clock
Likewise.
> +
> +Optional properties:
> +- clock-output-names : Should contain clock name
> +
> +
> +For example:
> +
> + clk_pll: clk_pll at 98100000 {
> + compatible = "moxa,moxart-pll-clock";
> + #clock-cells = <0>;
> + reg = <0x98100000 0x34>;
> + };
> +
> + clk_apb: clk_apb at 98100000 {
> + compatible = "moxa,moxart-apb-clock";
> + #clock-cells = <0>;
> + reg = <0x98100000 0x34>;
> + clocks = <&clk_pll>;
> + };
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 58b2d72..24361bf 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -12,6 +12,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-composite.o
> # SoCs specific
> obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
> obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
> +obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o
> obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
> obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
> obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/
> diff --git a/drivers/clk/clk-moxart.c b/drivers/clk/clk-moxart.c
> new file mode 100644
> index 0000000..7021748
> --- /dev/null
> +++ b/drivers/clk/clk-moxart.c
> @@ -0,0 +1,99 @@
> +/*
> + * MOXA ART SoCs clock driver.
> + *
> + * Copyright (C) 2013 Jonas Jensen
> + *
> + * Jonas Jensen <jonas.jensen@gmail.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/clkdev.h>
> +
> +void __init moxart_of_pll_clk_init(struct device_node *node)
> +{
> + static void __iomem *base;
> + struct clk *clk, *ref_clk;
> + unsigned long rate;
> + unsigned int mul;
> + const char *name = node->name;
> +
> + of_property_read_string(node, "clock-output-names", &name);
> +
> + base = of_iomap(node, 0);
> + if (!base) {
> + pr_err("%s: of_iomap failed\n", node->full_name);
> + return;
> + }
> +
> + mul = readl(base + 0x30) >> 3 & 0x3f;
> + iounmap(base);
> +
> + ref_clk = of_clk_get(node, 0);
> + if (IS_ERR(ref_clk)) {
> + pr_err("%s: of_clk_get failed\n", node->full_name);
> + return;
> + }
> +
> + rate = mul * clk_get_rate(ref_clk);
> +
> + clk = clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
If this clock has a parent, Surely CLK_IS_ROOT is not appropriate by its
definition:
#define CLK_IS_ROOT BIT(4) /* root clk, has no parent */
Surely this is a fixed factor clock rather than a fixed rate clock?
> + if (IS_ERR(clk)) {
> + pr_err("%s: clk_register_fixed_rate failed\n", node->full_name);
> + return;
> + }
> +
> + clk_register_clkdev(clk, NULL, name);
> + of_clk_add_provider(node, of_clk_src_simple_get, clk);
> +}
> +CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock",
> + moxart_of_pll_clk_init);
> +
> +void __init moxart_of_apb_clk_init(struct device_node *node)
> +{
> + static void __iomem *base;
> + struct clk *clk, *pll_clk;
> + unsigned long rate;
> + unsigned int div, val;
> + unsigned int div_idx[] = { 2, 3, 4, 6, 8};
> + const char *name = node->name;
> +
> + of_property_read_string(node, "clock-output-names", &name);
> +
> + base = of_iomap(node, 0);
> + if (!base) {
> + pr_err("%s: of_iomap failed\n", node->full_name);
> + return;
> + }
> +
> + val = readl(base + 0xc) >> 4 & 0x7;
> + iounmap(base);
> +
> + if (val > 4)
> + val = 0;
> + div = div_idx[val];
> +
> + pll_clk = of_clk_get(node, 0);
> + if (IS_ERR(pll_clk)) {
> + pr_err("%s: of_clk_get failed\n", node->full_name);
> + return;
> + }
> +
> + rate = clk_get_rate(pll_clk) / (div * 2);
> +
> + clk = clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
Likewise.
Thanks,
Mark.
^ permalink raw reply
* [PATCH v5 07/14] ahci-platform: "Library-ise" ahci_probe functionality
From: Roger Quadros @ 2014-01-27 10:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1390417489-5354-8-git-send-email-hdegoede@redhat.com>
Hi,
On 01/22/2014 09:04 PM, Hans de Goede wrote:
> ahci_probe consists of 3 steps:
> 1) Get resources (get mmio, clks, regulator)
> 2) Enable resources, handled by ahci_platform_enable_resouces
> 3) The more or less standard ahci-host controller init sequence
>
> This commit refactors step 1 and 3 into separate functions, so the platform
> drivers for AHCI implementations which need a specific order in step 2,
> and / or need to do some custom register poking at some time, can re-use
> ahci-platform.c code without needing to copy and paste it.
>
> Note that ahci_platform_init_host's prototype takes the 3 non function
> members of ahci_platform_data as arguments, the idea is that drivers using
> the new exported utility functions will not use ahci_platform_data at all,
> and hopefully in the future ahci_platform_data can go away entirely.
>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
> drivers/ata/ahci_platform.c | 158 ++++++++++++++++++++++++------------------
> include/linux/ahci_platform.h | 14 ++++
> 2 files changed, 106 insertions(+), 66 deletions(-)
>
> diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
> index 1cce7a2..b260ebe 100644
> --- a/drivers/ata/ahci_platform.c
> +++ b/drivers/ata/ahci_platform.c
> @@ -150,60 +150,31 @@ void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
> EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
>
>
> -static void ahci_put_clks(struct ahci_host_priv *hpriv)
> -{
> - int c;
> -
> - for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
> - clk_put(hpriv->clks[c]);
> -}
> -
> -static int ahci_probe(struct platform_device *pdev)
> +struct ahci_host_priv *ahci_platform_get_resources(
> + struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> - struct ahci_platform_data *pdata = dev_get_platdata(dev);
> - const struct platform_device_id *id = platform_get_device_id(pdev);
> - struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0];
> - const struct ata_port_info *ppi[] = { &pi, NULL };
> struct ahci_host_priv *hpriv;
> - struct ata_host *host;
> - struct resource *mem;
> struct clk *clk;
> - int i, irq, max_clk, n_ports, rc;
> -
> - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> - if (!mem) {
> - dev_err(dev, "no mmio space\n");
> - return -EINVAL;
> - }
> -
> - irq = platform_get_irq(pdev, 0);
> - if (irq <= 0) {
> - dev_err(dev, "no irq\n");
> - return -EINVAL;
> - }
> -
> - if (pdata && pdata->ata_port_info)
> - pi = *pdata->ata_port_info;
> + int i, max_clk, rc;
>
> hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
> if (!hpriv) {
> dev_err(dev, "can't alloc ahci_host_priv\n");
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
> }
>
> - hpriv->flags |= (unsigned long)pi.private_data;
> -
> - hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
> + hpriv->mmio = devm_ioremap_resource(dev,
> + platform_get_resource(pdev, IORESOURCE_MEM, 0));
> if (!hpriv->mmio) {
> - dev_err(dev, "can't map %pR\n", mem);
> - return -ENOMEM;
> + dev_err(dev, "no mmio space\n");
> + return ERR_PTR(-EINVAL);
> }
>
> hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
> if (IS_ERR(hpriv->target_pwr)) {
> if (PTR_ERR(hpriv->target_pwr) == -EPROBE_DEFER)
> - return -EPROBE_DEFER;
> + return ERR_PTR(-EPROBE_DEFER);
> hpriv->target_pwr = NULL;
> }
>
> @@ -223,27 +194,48 @@ static int ahci_probe(struct platform_device *pdev)
> hpriv->clks[i] = clk;
> }
>
> - rc = ahci_platform_enable_resources(hpriv);
> - if (rc)
> - goto free_clk;
> + return hpriv;
>
> - /*
> - * Some platforms might need to prepare for mmio region access,
> - * which could be done in the following init call. So, the mmio
> - * region shouldn't be accessed before init (if provided) has
> - * returned successfully.
> - */
> - if (pdata && pdata->init) {
> - rc = pdata->init(dev, hpriv);
> - if (rc)
> - goto disable_resources;
> - }
> +free_clk:
> + while (--i >= 0)
> + clk_put(hpriv->clks[i]);
> + return ERR_PTR(rc);
> +}
> +EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
> +
> +void ahci_platform_put_resources(struct ahci_host_priv *hpriv)
> +{
> + int c;
> +
> + for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
> + clk_put(hpriv->clks[c]);
> +}
> +EXPORT_SYMBOL_GPL(ahci_platform_put_resources);
> +
> +
> +int ahci_platform_init_host(struct platform_device *pdev,
> + struct ahci_host_priv *hpriv,
> + const struct ata_port_info *pi_template,
> + unsigned int force_port_map,
> + unsigned int mask_port_map)
> +{
> + struct device *dev = &pdev->dev;
> + struct ata_port_info pi = *pi_template;
> + const struct ata_port_info *ppi[] = { &pi, NULL };
> + struct ata_host *host;
> + int i, irq, n_ports, rc;
>
> - ahci_save_initial_config(dev, hpriv,
> - pdata ? pdata->force_port_map : 0,
> - pdata ? pdata->mask_port_map : 0);
> + irq = platform_get_irq(pdev, 0);
> + if (irq <= 0) {
> + dev_err(dev, "no irq\n");
> + return -EINVAL;
> + }
>
> /* prepare host */
> + hpriv->flags |= (unsigned long)pi.private_data;
> +
> + ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
> +
> if (hpriv->cap & HOST_CAP_NCQ)
> pi.flags |= ATA_FLAG_NCQ;
>
> @@ -260,10 +252,8 @@ static int ahci_probe(struct platform_device *pdev)
> n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
>
> host = ata_host_alloc_pinfo(dev, ppi, n_ports);
> - if (!host) {
> - rc = -ENOMEM;
> - goto pdata_exit;
> - }
> + if (!host)
> + return -ENOMEM;
>
> host->private_data = hpriv;
>
> @@ -278,7 +268,8 @@ static int ahci_probe(struct platform_device *pdev)
> for (i = 0; i < host->n_ports; i++) {
> struct ata_port *ap = host->ports[i];
>
> - ata_port_desc(ap, "mmio %pR", mem);
> + ata_port_desc(ap, "mmio %pR",
> + platform_get_resource(pdev, IORESOURCE_MEM, 0));
> ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
>
> /* set enclosure management message type */
> @@ -292,13 +283,48 @@ static int ahci_probe(struct platform_device *pdev)
>
> rc = ahci_reset_controller(host);
> if (rc)
> - goto pdata_exit;
> + return rc;
>
> ahci_init_controller(host);
> ahci_print_info(host, "platform");
>
> - rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
> - &ahci_platform_sht);
> + return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
> + &ahci_platform_sht);
> +}
> +EXPORT_SYMBOL_GPL(ahci_platform_init_host);
> +
> +static int ahci_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct ahci_platform_data *pdata = dev_get_platdata(dev);
> + const struct platform_device_id *id = platform_get_device_id(pdev);
> + struct ahci_host_priv *hpriv;
> + int rc;
> +
> + hpriv = ahci_platform_get_resources(pdev);
> + if (IS_ERR(hpriv))
> + return PTR_ERR(hpriv);
> +
> + rc = ahci_platform_enable_resources(hpriv);
> + if (rc)
> + goto put_resources;
> +
> + /*
> + * Some platforms might need to prepare for mmio region access,
> + * which could be done in the following init call. So, the mmio
> + * region shouldn't be accessed before init (if provided) has
> + * returned successfully.
> + */
> + if (pdata && pdata->init) {
> + rc = pdata->init(dev, hpriv);
> + if (rc)
> + goto disable_resources;
> + }
> +
> + rc = ahci_platform_init_host(pdev, hpriv,
> + &ahci_port_info[id ? id->driver_data : 0],
> + pdata ? pdata->force_port_map : 0,
> + pdata ? pdata->mask_port_map : 0);
> if (rc)
> goto pdata_exit;
>
> @@ -308,8 +334,8 @@ pdata_exit:
> pdata->exit(dev);
> disable_resources:
> ahci_platform_disable_resources(hpriv);
> -free_clk:
> - ahci_put_clks(hpriv);
> +put_resources:
> + ahci_platform_put_resources(hpriv);
> return rc;
> }
>
> @@ -323,7 +349,7 @@ static void ahci_host_stop(struct ata_host *host)
> pdata->exit(dev);
>
> ahci_platform_disable_resources(hpriv);
> - ahci_put_clks(hpriv);
> + ahci_platform_put_resources(hpriv);
> }
>
> #ifdef CONFIG_PM_SLEEP
> diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
> index 5e5f85e..1dc7602 100644
> --- a/include/linux/ahci_platform.h
> +++ b/include/linux/ahci_platform.h
> @@ -20,7 +20,13 @@
> struct device;
> struct ata_port_info;
> struct ahci_host_priv;
> +struct platform_device;
>
> +/*
> + * Note ahci_platform_data is deprecated. New drivers which need to override
> + * any of these, should instead declare there own platform_driver struct, and
> + * use ahci_platform* functions in their own probe, suspend and resume methods.
> + */
> struct ahci_platform_data {
> int (*init)(struct device *dev, struct ahci_host_priv *hpriv);
> void (*exit)(struct device *dev);
> @@ -35,5 +41,13 @@ int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
> void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
> int ahci_platform_enable_resources(struct ahci_host_priv *hpriv);
> void ahci_platform_disable_resources(struct ahci_host_priv *hpriv);
> +struct ahci_host_priv *ahci_platform_get_resources(
> + struct platform_device *pdev);
Why not use 'struct device' as the argument?
> +void ahci_platform_put_resources(struct ahci_host_priv *hpriv);
Can we have 'struct device' as the argument? Else it becomes
impossible to get 'struct device' from 'hpriv' if we need to call e.g.
pm_runtime_*() APIs.
> +int ahci_platform_init_host(struct platform_device *pdev,
> + struct ahci_host_priv *hpriv,
> + const struct ata_port_info *pi_template,
> + unsigned int force_port_map,
> + unsigned int mask_port_map);
>
> #endif /* _AHCI_PLATFORM_H */
>
cheers,
-roger
^ permalink raw reply
* [PATCH] drivers: bus: fix CCI driver kcalloc call parameters swap
From: Lorenzo Pieralisi @ 2014-01-27 10:50 UTC (permalink / raw)
To: linux-arm-kernel
This patch fixes a bug/typo in the CCI driver kcalloc usage
that inadvertently swapped the parameters order in the
kcalloc call and went unnoticed.
Reported-by: Xia Feng <xiafeng@allwinnertech.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
---
drivers/bus/arm-cci.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index b6739cb..962fd35 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -979,7 +979,7 @@ static int cci_probe(void)
nb_cci_ports = cci_config->nb_ace + cci_config->nb_ace_lite;
- ports = kcalloc(sizeof(*ports), nb_cci_ports, GFP_KERNEL);
+ ports = kcalloc(nb_cci_ports, sizeof(*ports), GFP_KERNEL);
if (!ports)
return -ENOMEM;
--
1.8.2.2
^ permalink raw reply related
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