* [PATCH v5 7/7] ARM: dts: sun8i-h3: Add HDMI audio and video to the Orange PI 2
From: Jean-Francois Moine @ 2016-10-22 11:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1477142934.git.moinejf@free.fr>
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
The same patch may be applied to other H3 based boards (Orange PI xx).
---
arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
index e5bcaba..799ceb9 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
@@ -56,6 +56,7 @@
serial0 = &uart0;
/* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */
ethernet1 = &rtl8189;
+ lcd0 = &lcd0;
};
chosen {
@@ -105,16 +106,32 @@
};
};
+&de {
+ status = "okay";
+};
+
&ehci1 {
status = "okay";
};
+&hdmi {
+ status = "okay";
+};
+
+&i2s2 {
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};
+&lcd0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
--
2.10.1
^ permalink raw reply related
* [PATCH v3 3/6] pwm: imx: support output polarity inversion
From: Boris Brezillon @ 2016-10-22 10:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161021234939.1a4f51f4@jawa>
Hi Lukasz,
On Fri, 21 Oct 2016 23:49:39 +0200
Lukasz Majewski <l.majewski@majess.pl> wrote:
> Hi Stefan,
>
> > On 2016-10-20 01:30, Lukasz Majewski wrote:
> > > Hi Stefan,
> > >
> > >> Hi Stefan,
> > >>
> > >> > On 2016-10-12 15:15, Lukasz Majewski wrote:
> > >> > > Hi Stefan,
> > >> > >
> > >> > >> On 2016-10-07 08:11, Bhuvanchandra DV wrote:
> > >> > >> > From: Lothar Wassmann <LW@KARO-electronics.de>
> > >> > >> >
> > >> > >> > The i.MX pwm unit on i.MX27 and newer SoCs provides a
> > >> > >> > configurable output polarity. This patch adds support to
> > >> > >> > utilize this feature where available.
> > >> > >> >
> > >> > >> > Signed-off-by: Lothar Wa?mann <LW@KARO-electronics.de>
> > >> > >> > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > >> > >> > Signed-off-by: Bhuvanchandra DV
> > >> > >> > <bhuvanchandra.dv@toradex.com> Acked-by: Shawn Guo
> > >> > >> > <shawn.guo@linaro.org> Reviewed-by: Sascha Hauer
> > >> > >> > <s.hauer@pengutronix.de> ---
> > >> > >> > Documentation/devicetree/bindings/pwm/imx-pwm.txt | 6 +--
> > >> > >> > drivers/pwm/pwm-imx.c | 51
> > >> > >> > +++++++++++++++++++++-- 2 files changed, 51 insertions(+), 6
> > >> > >> > deletions(-)
> > >> > >> >
> > >> > >> > diff --git
> > >> > >> > a/Documentation/devicetree/bindings/pwm/imx-pwm.txt
> > >> > >> > b/Documentation/devicetree/bindings/pwm/imx-pwm.txt index
> > >> > >> > e00c2e9..c61bdf8 100644 ---
> > >> > >> > a/Documentation/devicetree/bindings/pwm/imx-pwm.txt +++
> > >> > >> > b/Documentation/devicetree/bindings/pwm/imx-pwm.txt @@ -6,8
> > >> > >> > +6,8 @@ Required properties:
> > >> > >> > - "fsl,imx1-pwm" for PWM compatible with the one
> > >> > >> > integrated on i.MX1
> > >> > >> > - "fsl,imx27-pwm" for PWM compatible with the one
> > >> > >> > integrated on i.MX27
> > >> > >> > - reg: physical base address and length of the controller's
> > >> > >> > registers -- #pwm-cells: should be 2. See pwm.txt in this
> > >> > >> > directory for a description of
> > >> > >> > - the cells format.
> > >> > >> > +- #pwm-cells: 2 for i.MX1 and 3 for i.MX27 and newer SoCs.
> > >> > >> > See pwm.txt
> > >> > >> > + in this directory for a description of the cells format.
> > >> > >> > - clocks : Clock specifiers for both ipg and per clocks.
> > >> > >> > - clock-names : Clock names should include both "ipg" and
> > >> > >> > "per" See the clock consumer binding,
> > >> > >> > @@ -17,7 +17,7 @@ See the clock consumer binding,
> > >> > >> > Example:
> > >> > >> >
> > >> > >> > pwm1: pwm at 53fb4000 {
> > >> > >> > - #pwm-cells = <2>;
> > >> > >> > + #pwm-cells = <3>;
> > >> > >> > compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
> > >> > >> > reg = <0x53fb4000 0x4000>;
> > >> > >> > clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
> > >> > >> > diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
> > >> > >> > index d600fd5..c37d223 100644
> > >> > >> > --- a/drivers/pwm/pwm-imx.c
> > >> > >> > +++ b/drivers/pwm/pwm-imx.c
> > >> > >> > @@ -38,6 +38,7 @@
> > >> > >> > #define MX3_PWMCR_DOZEEN (1 << 24)
> > >> > >> > #define MX3_PWMCR_WAITEN (1 << 23)
> > >> > >> > #define MX3_PWMCR_DBGEN (1 << 22)
> > >> > >> > +#define MX3_PWMCR_POUTC (1 << 18)
> > >> > >> > #define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
> > >> > >> > #define MX3_PWMCR_CLKSRC_IPG (1 << 16)
> > >> > >> > #define MX3_PWMCR_SWR (1 << 3)
> > >> > >> > @@ -180,6 +181,9 @@ static int imx_pwm_config_v2(struct
> > >> > >> > pwm_chip *chip, if (enable)
> > >> > >> > cr |= MX3_PWMCR_EN;
> > >> > >> >
> > >> > >> > + if (pwm->args.polarity == PWM_POLARITY_INVERSED)
> > >> > >> > + cr |= MX3_PWMCR_POUTC;
> > >> > >> > +
> > >> > >>
> > >> > >> This seems wrong to me, the config callback is meant for
> > >> > >> period/duty cycle only.
> > >
> > > Unfortunately, it also resets the PWM IP block and setups it again
> > > (by writing to PWMCR register).
Well, this is an implementation problem. If you were reading the
MX3_PWMCR register and masking it with MX3_PWMCR_POUTC to keep the
value set by ->set_polarity() that wouldn't be a problem.
> > > In that function we setup for
> > > example MX3_PWMCR_DOZEEN
> > > and MX3_PWMCR_DBGEN. Why cannot we setup polarity as well?
I think there's no real problem in setting the polarity again in
->config(), it's just that it feels weird to have it set twice (in
->set_polarity() and in ->config()).
> > >
> > >
> > > I've double checked the backlight and pwm code flow.
> > >
> > > Please find following snippet:
> > >
> > > [ 0.135545] ######### imx_pwm_probe
> > > [ 0.135581] PWM supports output inversion
> > > [ 0.136864] ######### pwm_backlight_probe
> > > [ 0.136913] backlight supply power not found, using dummy
> > > regulator [ 0.136984] ######### imx_pwm_set_polarity 1
> > > [ 0.136995] imx_pwm_set_polarity: polarity set to inverted cr:
> > > 0x40000 0xf08f8000
> > > [ 0.137005] #########0 imx_pwm_config_v2 cr: 0x40000
> > > [ 0.137683] #########1 imx_pwm_config_v2 cr: 0x0 0xf08f8000
> > > [ 0.137693] #########2 imx_pwm_config_v2 cr: 0x1c20050
> > > [ 0.137702] #########3 imx_pwm_config_v2 cr: 0x1c20050 0xf08f8000
> > > [ 0.137711] @@@@@@@@@@ pwm_apply_state
>
> Maybe a bit more logs:
>
> [ 0.135451] ######### imx_pwm_probe
> [ 0.135488] PWM supports output inversion
> [ 0.136777] ######### pwm_backlight_probe
> [ 0.136826] backlight supply power not found, using dummy regulator
> [ 0.136893] ********* pwm_apply_state state->enabled: 0
> [ 0.136902] ######### imx_pwm_set_polarity 1
> [ 0.136913] imx_pwm_set_polarity: polarity set to inverted cr: 0x40000 0xf08f8000
> [ 0.136923] #########0 imx_pwm_config_v2 cr: 0x40000
> [ 0.137692] #########1 imx_pwm_config_v2 cr: 0x0 0xf08f8000
> [ 0.137701] #########2 imx_pwm_config_v2 cr: 0x1c20050
> [ 0.137710] #########3 imx_pwm_config_v2 cr: 0x1c20050 0xf08f8000
> [ 0.137720] @@@@@@@@@@ pwm_apply_state
> [ 0.137856] ********* pwm_apply_state state->enabled: 0
> [ 0.137869] #########0 imx_pwm_config_v2 cr: 0x1c20050
> [ 0.138904] #########1 imx_pwm_config_v2 cr: 0x0 0xf08f8000
> [ 0.138913] #########2 imx_pwm_config_v2 cr: 0x1c20050
> [ 0.138921] #########3 imx_pwm_config_v2 cr: 0x1c20050 0xf08f8000
> [ 0.138928] @@@@@@@@@@ pwm_apply_state
> [ 0.138940] ********* pwm_apply_state state->enabled: 1
> ^^^^^^^^^^^^^^^^^^ this is called from
> pwm_backlight_power_on() from pwm_bl probe function
>
> The problem here is not the lack of ->apply() callback, but the requirement to
> perform software reset on the pwm_v2 fifo when the pwm_v2 is NOT enabled (state->enabled: 0).
Not sure what a PWM fifo is, or which software reset you are talking
about. If you're talking about the disable()+set_polarity()+enable()
dance, then, this is required by some PWM controllers which do not
support changing the PWM polarity while the PWM is running.
>
> As fair as I can see the pwm_state has following members: period, duty cycle, polarity and enabled.
> I'm fine to implement ->apply() callback, which would change above values.
>
> However, there is a problem with ->config() (imx_pwm_config_v2 @ pwm-imx.c) and imx pwm_v2 software
> FIFO reset.
->config() will not be used if you implement ->apply(), and ->apply()
should take care of all the nasty details that should be taken care of
on your PWM controller.
Say for example that you need to disable the PWM before changing the
polarity, then your ->apply() function should check if the PWM is
enabled, if that's the case it should disable it, set the new polarity,
possibly re-apply the period and duty config and finally re-enable the
PWM.
> We can set polarity in any other kernel subsystem, which uses PWM (backlight in this example) and
> then this setting would disappear when we call pwm_apply_state with state->enabled = 0 (as presented
> in the log). This imposes setting polarity at ->config when we enable the PWM (as this patch does).
That's really a driver problem, not a PWM user or PWM core problem. If
you have to take extra precautions when enabling the PWM (like
re-applying the polarity), then you can do that in your ->apply()
implementation.
>
>
>
> > >
> > > Here the pwm_backlight_probe calls set_polarity callback available
> > > in pwm - the polarity is set (the 0x40000 value).
> > >
> > > The above operation is performed in pwm_apply_state (@
> > > drivers/pwm/core.c). In the same function, latter we call the
> > > pwm->chip->ops->config(), which is the pointer to config_v2.
> > > Since the PWM is not yet enabled, this function performs SW reset
> > > and PWM inversion setting is cleared.
> >
> > That function should not do that.
>
> I do agree that it shouldn't. Correct me if I'm wrong, but it seems like an
> PWM HW requirement to perform the reset.
>
> >It was probably already problematic
> > in the old times, it is definitely now with the atomic PWM stuff.
>
> The "atomic"[*] code (with ->apply() provided) will not solve this issue.
Of course it will solve the problem, because in ->apply() you're passed
all the information you need, and if you have to re-apply the polarity
setting, you can (which was not the case with the old pwm_ops
interface).
>
> >
> > >
> > > Possible solutions:
> > >
> > > 1. Leave the original patch from Bhuvanchandra as it was (I'm for
> > > this option)
> >
> > That really seems like a hack to me, and makes transition to the
> > atomic PWM API more complex.
>
> Could you be more specific here?
>
> As I mentioned before, the problem is not with the lack of
> "atomic" API.
And I really think it is.
>
> For me the problem is with other subsystems (like pwm backlight)
> which do require polarity inversion to work properly.
Nope, it's just that, with the old pwm_ops interface, your driver was
not able to apply things in the right order. With the ->apply() it can.
>
> >
> > If we can't make it happen properly in the current state of affairs,
>
> We can set polarity properly with this patch. The only thing which needs fixing
> and another revision of the patch) is the removal of condition:
>
> - if (polarity == pwm->args.polarity)
> - return 0;
>
> at imx_pwm_set_polarity() function.
Yes, you can probably add even more hacks, but as Stefan said, it's
probably better to switch to the atomic interface, because by doing you
would greatly simplify the logic.
>
> > we probably should first move to the atomic API.
> >
> > It really should not be that hard, since we already do almost
> > everything in one function (imx_pwm_config_v2). We probably can
> > almost just assign that function to the new apply function pointer
> > and read information from the new state struct.
>
> We do need to configure polarity according to DT value during the pwm
> config_v2 configuration after PWM IP software reset.
And again, forget about ->config(), it should not be called if you
implement ->apply() (actually, you should even drop it completely). So
really, you should try implementing ->apply() and see what happens.
>
> >
> > There are examples for instance here:
> > https://patchwork.kernel.org/patch/7228221/
>
> The atomicity[*]:
>
> - It seems to me that this "atomicity" is just embracing all the ->enable, ->disable
> and ->set_polarity in one -> apply callback. Is this just conceptual clean up or is
> there any other reason for it (I'm just curious) ?
No, it's not just a conceptual cleanup. Some hardware are capable of
updating the PWM config atomically (which means they will update the
config at the end of the current period cycle), and by doing that we
also prevent any glitches on the PWM signal.
With the old API, this was simply impossible to do, because the
enable/disable, set_polarity and config calls were separated. With the
atomic API, we can.
Now, let's say your controller is not guaranteeing atomicity. It's
still interesting to implement the ->apply() function, because this way
you can handle all those complex sequences that are required on some HW.
To sum-up, I really think you should listen to Stefan and try to
implement the atomic hook (AKA ->apply()).
Regards,
Boris
^ permalink raw reply
* [PATCH v3 3/6] pwm: imx: support output polarity inversion
From: Boris Brezillon @ 2016-10-22 10:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161007151129.6043-4-bhuvanchandra.dv@toradex.com>
On Fri, 7 Oct 2016 20:41:26 +0530
Bhuvanchandra DV <bhuvanchandra.dv@toradex.com> wrote:
> From: Lothar Wassmann <LW@KARO-electronics.de>
>
> The i.MX pwm unit on i.MX27 and newer SoCs provides a configurable output
> polarity. This patch adds support to utilize this feature where available.
>
> Signed-off-by: Lothar Wa?mann <LW@KARO-electronics.de>
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Bhuvanchandra DV <bhuvanchandra.dv@toradex.com>
> Acked-by: Shawn Guo <shawn.guo@linaro.org>
> Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> Documentation/devicetree/bindings/pwm/imx-pwm.txt | 6 +--
> drivers/pwm/pwm-imx.c | 51 +++++++++++++++++++++--
> 2 files changed, 51 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/pwm/imx-pwm.txt b/Documentation/devicetree/bindings/pwm/imx-pwm.txt
> index e00c2e9..c61bdf8 100644
> --- a/Documentation/devicetree/bindings/pwm/imx-pwm.txt
> +++ b/Documentation/devicetree/bindings/pwm/imx-pwm.txt
> @@ -6,8 +6,8 @@ Required properties:
> - "fsl,imx1-pwm" for PWM compatible with the one integrated on i.MX1
> - "fsl,imx27-pwm" for PWM compatible with the one integrated on i.MX27
> - reg: physical base address and length of the controller's registers
> -- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
> - the cells format.
> +- #pwm-cells: 2 for i.MX1 and 3 for i.MX27 and newer SoCs. See pwm.txt
> + in this directory for a description of the cells format.
> - clocks : Clock specifiers for both ipg and per clocks.
> - clock-names : Clock names should include both "ipg" and "per"
> See the clock consumer binding,
> @@ -17,7 +17,7 @@ See the clock consumer binding,
> Example:
>
> pwm1: pwm at 53fb4000 {
> - #pwm-cells = <2>;
> + #pwm-cells = <3>;
> compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
> reg = <0x53fb4000 0x4000>;
> clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
> diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
> index d600fd5..c37d223 100644
> --- a/drivers/pwm/pwm-imx.c
> +++ b/drivers/pwm/pwm-imx.c
> @@ -38,6 +38,7 @@
> #define MX3_PWMCR_DOZEEN (1 << 24)
> #define MX3_PWMCR_WAITEN (1 << 23)
> #define MX3_PWMCR_DBGEN (1 << 22)
> +#define MX3_PWMCR_POUTC (1 << 18)
> #define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
> #define MX3_PWMCR_CLKSRC_IPG (1 << 16)
> #define MX3_PWMCR_SWR (1 << 3)
> @@ -180,6 +181,9 @@ static int imx_pwm_config_v2(struct pwm_chip *chip,
> if (enable)
> cr |= MX3_PWMCR_EN;
>
> + if (pwm->args.polarity == PWM_POLARITY_INVERSED)
> + cr |= MX3_PWMCR_POUTC;
> +
> writel(cr, imx->mmio_base + MX3_PWMCR);
>
> return 0;
> @@ -240,27 +244,62 @@ static void imx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
> clk_disable_unprepare(imx->clk_per);
> }
>
> -static struct pwm_ops imx_pwm_ops = {
> +static int imx_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
> + enum pwm_polarity polarity)
> +{
> + struct imx_chip *imx = to_imx_chip(chip);
> + u32 val;
> +
> + if (polarity == pwm->args.polarity)
> + return 0;
> +
> + val = readl(imx->mmio_base + MX3_PWMCR);
> +
> + if (polarity == PWM_POLARITY_INVERSED)
> + val |= MX3_PWMCR_POUTC;
> + else
> + val &= ~MX3_PWMCR_POUTC;
> +
> + writel(val, imx->mmio_base + MX3_PWMCR);
> +
> + dev_dbg(imx->chip.dev, "%s: polarity set to %s\n", __func__,
> + polarity == PWM_POLARITY_INVERSED ? "inverted" : "normal");
> +
> + return 0;
> +}
I'll read the discussion Lukasz and Stefan had before reviewing this
part ;-).
> +
> +static struct pwm_ops imx_pwm_ops_v1 = {
> .enable = imx_pwm_enable,
> .disable = imx_pwm_disable,
> .config = imx_pwm_config,
> .owner = THIS_MODULE,
> };
>
> +static struct pwm_ops imx_pwm_ops_v2 = {
> + .enable = imx_pwm_enable,
> + .disable = imx_pwm_disable,
> + .set_polarity = imx_pwm_set_polarity,
> + .config = imx_pwm_config,
> + .owner = THIS_MODULE,
> +};
> +
> struct imx_pwm_data {
> int (*config)(struct pwm_chip *chip,
> struct pwm_device *pwm, int duty_ns, int period_ns);
> void (*set_enable)(struct pwm_chip *chip, bool enable);
> + struct pwm_ops *pwm_ops;
Probably better to make that consistent: drop the ->config() and
->set_enable() hooks, and make both v1 and v2 define their own pwm_ops.
If you have common logic that is shared between v1 and v2, you can just
create helper functions implementing this common logic and call them
from your version-specific implementation.
> };
>
> static struct imx_pwm_data imx_pwm_data_v1 = {
> .config = imx_pwm_config_v1,
> .set_enable = imx_pwm_set_enable_v1,
> + .pwm_ops = &imx_pwm_ops_v1,
> };
>
> static struct imx_pwm_data imx_pwm_data_v2 = {
> .config = imx_pwm_config_v2,
> .set_enable = imx_pwm_set_enable_v2,
> + .pwm_ops = &imx_pwm_ops_v2,
> };
>
> static const struct of_device_id imx_pwm_dt_ids[] = {
> @@ -282,6 +321,8 @@ static int imx_pwm_probe(struct platform_device *pdev)
> if (!of_id)
> return -ENODEV;
>
> + data = of_id->data;
> +
> imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
> if (imx == NULL)
> return -ENOMEM;
> @@ -300,18 +341,22 @@ static int imx_pwm_probe(struct platform_device *pdev)
> return PTR_ERR(imx->clk_ipg);
> }
>
> - imx->chip.ops = &imx_pwm_ops;
> + imx->chip.ops = data->pwm_ops;
> imx->chip.dev = &pdev->dev;
> imx->chip.base = -1;
> imx->chip.npwm = 1;
> imx->chip.can_sleep = true;
> + if (data->pwm_ops->set_polarity) {
> + dev_dbg(&pdev->dev, "PWM supports output inversion\n");
> + imx->chip.of_xlate = of_pwm_xlate_with_flags;
> + imx->chip.of_pwm_n_cells = 3;
> + }
Not that I really care, but you are breaking the DT ABI here. One
solution to avoid that would be to retrieve #pwm-cells here and
decide which ->of_xlate should be used based on this information.
>
> r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> imx->mmio_base = devm_ioremap_resource(&pdev->dev, r);
> if (IS_ERR(imx->mmio_base))
> return PTR_ERR(imx->mmio_base);
>
> - data = of_id->data;
> imx->config = data->config;
> imx->set_enable = data->set_enable;
>
^ permalink raw reply
* [PATCH v5 6/7] ARM: dts: sun8i-h3: Add HDMI audio and video to the Banana Pi M2+
From: Jean-Francois Moine @ 2016-10-22 10:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1477142934.git.moinejf@free.fr>
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
---
The patch for the Banana Pi M3 (A83T) is the same as this one.
---
arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts b/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts
index 06fddaa..2e81de8 100644
--- a/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts
+++ b/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts
@@ -55,6 +55,7 @@
aliases {
serial0 = &uart0;
serial1 = &uart1;
+ lcd0 = &lcd0;
};
chosen {
@@ -93,6 +94,10 @@
};
};
+&de {
+ status = "okay";
+};
+
&ehci1 {
status = "okay";
};
@@ -101,12 +106,24 @@
status = "okay";
};
+&hdmi {
+ status = "okay";
+};
+
+&i2s2 {
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};
+&lcd0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
--
2.10.1
^ permalink raw reply related
* [PATCH] i2c: rk3x: Give the tuning value 0 during rk3x_i2c_v0_calc_timings
From: David Wu @ 2016-10-22 8:43 UTC (permalink / raw)
To: linux-arm-kernel
We found a bug that i2c transfer sometimes failed on 3066a board with
stabel-4.8, the con register would be updated by uninitialized tuning
value, it made the i2c transfer failed.
So give the tuning value to be zero during rk3x_i2c_v0_calc_timings.
Signed-off-by: David Wu <david.wu@rock-chips.com>
---
drivers/i2c/busses/i2c-rk3x.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 50702c7..df22066 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -694,6 +694,8 @@ static int rk3x_i2c_v0_calc_timings(unsigned long clk_rate,
t_calc->div_low--;
t_calc->div_high--;
+ /* Give the tuning value 0, that would not update con register */
+ t_calc->tuning = 0;
/* Maximum divider supported by hw is 0xffff */
if (t_calc->div_low > 0xffff) {
t_calc->div_low = 0xffff;
--
1.9.1
^ permalink raw reply related
* [PATCH/RFC 4/4] soc: renesas: Identify SoC and register with the SoC bus
From: Geert Uytterhoeven @ 2016-10-22 7:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <12094567.68HcWl4d5O@wuerfel>
Hi Arnd,
On Fri, Oct 21, 2016 at 11:16 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Friday, October 21, 2016 8:16:00 PM CEST Geert Uytterhoeven wrote:
>> On Wed, Oct 19, 2016 at 12:59 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>> > On Wednesday, October 19, 2016 10:02:57 AM CEST Geert Uytterhoeven wrote:
>> >> On Mon, Oct 10, 2016 at 4:23 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>> > I'd prefer seeing a separate soc driver for that one.
>> >> Some SoCs have only CCCR, others have only PRR, some have both.
>> >> On some SoCs one of them can be accessed from the RealTime CPU
>> >> core (SH) only.
>> >> On some SoCs the register is not documented, but present.
>> >> If the PRR exists, it's a better choice, as it contains additional information
>> >> in the high order bits (representing the presence of each big (CA15/CA57),
>> >> little (CA7/CA53), and RT (CR7) CPU core). Currently we don't use that
>> >> information, though.
>> >>
>> >> Grouping them in some other way means we would loose the family name,
>> >> which is exposed through soc_dev_attr->family.
>> >> The usefulness of family names is debatable though, as this is more an
>> >> issue of marketing business.
>> >
>> > How about having a table to look up the family name by the value
>> > of the PRR or CCCR then?
>>
>> Unfortunately there exist SoCs from different families using the same
>> product ID.
>>
>> And different SoCs from the same family may have a revision register
>> or not (e.g. R-Car H1 has, M1A hasn't).
>
> Is this something we expect to see more of in the future, or can
> we expect future chips to handle this more consistently?
I expect to see more of these in the future.
Perhaps I just should forget about the product IDs and (marketing) families,
and just stick the CCCR/PRR addresses in the of_device_ids?
Then we'll have SoC names (e.g. "r8a7791") and (optional) revisions
(e.g. "ES1.0") to match on.
>> > How about this:
>> >
>> > The driver could report the hardcoded strings for the SoCs it already
>> > knows about (you have the table anyway) and not report the revision
>> > unless there is a regmap containing the CCCR or the PRR, in which
>> > case you use that. Future SoCs will provide the PRR (I assume
>> > CCCR is only used on the older ones) through a syscon regmap
>> > that we can use to find out the exact revision as well.
>> >
>> > The existing DT files can gain the syscon device so you can report
>> > the revision on those machines as well, unless you use an old DTB.
>>
>> Hmm... That means that if we have to add a driver quirk to distinguish
>> between different revisions of the same SoC, we have to update the
>> DTB anyway, to add the CCCR/PRR device node.
>> We might as well just change the compatible value in that DTB for the
>> device that needs the quirk. Which is what we'd like to avoid in the
>> first place.
>
> Do you have a specific example in mind? If this is only a theoretical
> problem, we can worry about it when we get there, and then decide
> if we add a hardcoded register after all.
For R-Car H3, there are small differences between ES1.0 and ES1.1,
and more and larger differences between ES1.x and ES2.0, which
need different handling (patches already floating around).
For (old) R-Car H1, the SATA driver already handles "renesas,sata-r8a7790-es1",
but so far there didn't exist an established process to specify how that
compatible value would end up in the DTB (the in-kernel DTS doesn't have it).
There may be more differences I'm not aware of.
>> > Why not just drop all the #ifdef here? There should be very little
>> > overhead in size, especially if all the data is __initconst.
>>
>> It still saves ca. 3 KiB for a kernel for a single SoC.
>
> Fair enough, that is more than I was expecting from looking at the
> source. It's probably the of_device_id structures for the most part.
Yep, ca. 200 bytes per ID.
> Please just add the __maybe_unused then, to save us a patch in case
> we make -Wunused-const the default in the future.
Sure.
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] iommu: arm-smmu-v2: Enable 16 bit ASID
From: Geetha sowjanya @ 2016-10-22 5:02 UTC (permalink / raw)
To: linux-arm-kernel
Support up to 16 bit ASID. This patch enables
16 bit ASID when supported.
Signed-off-by: Geetha sowjanya <gakula@cavium.com>
Acked-by: Tirumalesh Chalamarla <Tirumalesh.Chalamarla@cavium.com>
---
drivers/iommu/arm-smmu.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index c841eb7..9740846 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -258,6 +258,9 @@ enum arm_smmu_s2cr_privcfg {
#define TTBCR2_SEP_SHIFT 15
#define TTBCR2_SEP_UPSTREAM (0x7 << TTBCR2_SEP_SHIFT)
+#define TTBCR2_AS_SHIFT 4
+#define TTBCR2_AS_ENABLE (1 << TTBCR2_AS_SHIFT)
+
#define TTBRn_ASID_SHIFT 48
#define FSR_MULTI (1 << 31)
@@ -773,6 +776,9 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
reg = pgtbl_cfg->arm_lpae_s1_cfg.tcr;
reg2 = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32;
reg2 |= TTBCR2_SEP_UPSTREAM;
+ /* Enable 16 bit ASID if 16 bit VMID is supported */
+ if (smmu->features & ARM_SMMU_FEAT_VMID16)
+ reg |= TTBCR2_AS_ENABLE;
}
if (smmu->version > ARM_SMMU_V1)
writel_relaxed(reg2, cb_base + ARM_SMMU_CB_TTBCR2);
--
1.7.1
^ permalink raw reply related
* [PATCH] arm64: SMMU-v2: Workaround for Cavium ThunderX erratum 28168
From: Geetha sowjanya @ 2016-10-22 4:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1>
From: Tirumalesh Chalamarla <Tirumalesh.Chalamarla@cavium.com>
This patch implements Cavium ThunderX erratum 28168.
PCI requires stores complete in order. Due to erratum #28168
PCI-inbound MSI-X store to the interrupt controller are delivered
to the interrupt controller before older PCI-inbound memory stores
are committed.
Doing a sync on SMMU will make sure all prior transactions are
completed.
Signed-off-by: Tirumalesh Chalamarla <Tirumalesh.Chalamarla@cavium.com>
Signed-off-by: Geetha sowjanya <gakula@caviumnetworks.com>
---
arch/arm64/Kconfig | 11 +++++++++++
drivers/iommu/arm-smmu.c | 38 ++++++++++++++++++++++++++++++++++++++
drivers/irqchip/irq-gic-common.h | 1 +
drivers/irqchip/irq-gic-v3-its.c | 22 ++++++++++++++++++++++
kernel/irq/chip.c | 4 ++++
5 files changed, 76 insertions(+), 0 deletions(-)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 30398db..57f5c9b 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -474,6 +474,17 @@ config CAVIUM_ERRATUM_27456
If unsure, say Y.
+config CAVIUM_ERRATUM_28168
+ bool "Cavium erratum 28168: Make sure ITS and SMMU TLB are in sync"
+ default y
+ help
+ Due to erratum #28168 PCI-inbound MSI-X store to the interrupt
+ controller are delivered to the interrupt controller before older
+ PCI-inbound memory stores are committed. Doing a sync on SMMU
+ will make sure all prior transactions are completed.
+
+ If unsure, say Y.
+
endmenu
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 9740846..20a61c6 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -378,6 +378,7 @@ struct arm_smmu_device {
unsigned int *irqs;
u32 cavium_id_base; /* Specific to Cavium */
+ spinlock_t tlb_lock;
};
enum arm_smmu_context_fmt {
@@ -576,9 +577,39 @@ static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu)
static void arm_smmu_tlb_sync(void *cookie)
{
struct arm_smmu_domain *smmu_domain = cookie;
+ struct arm_smmu_device *smmu = smmu_domain->smmu;
+ unsigned long flags;
+
+ spin_lock_irqsave(&smmu->tlb_lock, flags);
__arm_smmu_tlb_sync(smmu_domain->smmu);
+ spin_unlock_irqrestore(&smmu->tlb_lock, flags)
}
+/*
+ * Cavium ThunderX erratum 28168
+ *
+ * Due to erratum #28168 PCI-inbound MSI-X store to the interrupt
+ * controller are delivered to the interrupt controller before older
+ * PCI-inbound memory stores are committed. Doing a sync on SMMU
+ * will make sure all prior transactions are completed.
+ *
+ */
+void cavium_smmu_tlb_sync(struct device *dev)
+{
+ struct arm_smmu_device *smmu;
+ struct arm_smmu_master_cfg *cfg;
+ unsigned long flags;
+
+ smmu = find_smmu_for_device(dev);
+ if (!smmu)
+ return;
+
+ spin_lock_irqsave(&smmu->tlb_lock, flags);
+ __arm_smmu_tlb_sync(smmu);
+ spin_unlock_irqrestore(&smmu->tlb_lock, flags)
+}
+EXPORT_SYMBOL(cavium_smmu_tlb_sync);
+
static void arm_smmu_tlb_inv_context(void *cookie)
{
struct arm_smmu_domain *smmu_domain = cookie;
@@ -586,6 +617,7 @@ static void arm_smmu_tlb_inv_context(void *cookie)
struct arm_smmu_device *smmu = smmu_domain->smmu;
bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
void __iomem *base;
+ unsigned long flags;
if (stage1) {
base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
@@ -597,7 +629,9 @@ static void arm_smmu_tlb_inv_context(void *cookie)
base + ARM_SMMU_GR0_TLBIVMID);
}
+ spin_lock_irqsave(&smmu->tlb_lock, flags);
__arm_smmu_tlb_sync(smmu);
+ spin_unlock_irqrestore(&smmu->tlb_lock, flags)
}
static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
@@ -1562,6 +1596,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
void __iomem *cb_base;
int i;
+ unsigned long flags;
u32 reg, major;
/* clear global FSR */
@@ -1633,7 +1668,9 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
reg |= sCR0_VMID16EN;
/* Push the button */
+ spin_lock_irqsave(&smmu->tlb_lock, flags)
__arm_smmu_tlb_sync(smmu);
+ spin_unlock_irqrestore(&smmu->tlb_lock, flags)
writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
}
@@ -2001,6 +2038,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
}
}
+ spin_lock_init(&smmu->tlb_lock);
of_iommu_set_ops(dev->of_node, &arm_smmu_ops);
platform_set_drvdata(pdev, smmu);
arm_smmu_device_reset(smmu);
diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h
index 205e5fd..0228ba0 100644
--- a/drivers/irqchip/irq-gic-common.h
+++ b/drivers/irqchip/irq-gic-common.h
@@ -38,4 +38,5 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
void gic_set_kvm_info(const struct gic_kvm_info *info);
+void cavium_smmu_tlb_sync(void *iommu);
#endif /* _IRQ_GIC_COMMON_H */
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 003495d..88e9958 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -112,6 +112,7 @@ struct its_device {
struct its_node *its;
struct event_lpi_map event_map;
void *itt;
+ struct device *dev;
u32 nr_ites;
u32 device_id;
};
@@ -664,10 +665,29 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
iommu_dma_map_msi_msg(d->irq, msg);
}
+/**
+ * Due to erratum in ThunderX,
+ * we need to make sure SMMU is in sync with ITS translations.
+ **/
+static void its_ack_irq(struct irq_data *d)
+{
+ struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+ struct pci_dev *pdev;
+
+ if (!dev_is_pci(its_dev->dev))
+ return;
+
+ pdev = to_pci_dev(its_dev->dev);
+ if (pdev->vendor != 0x177d)
+ cavium_smmu_tlb_sync(its_dev->dev);
+
+}
+
static struct irq_chip its_irq_chip = {
.name = "ITS",
.irq_mask = its_mask_irq,
.irq_unmask = its_unmask_irq,
+ .irq_ack = its_ack_irq,
.irq_eoi = irq_chip_eoi_parent,
.irq_set_affinity = its_set_affinity,
.irq_compose_msi_msg = its_irq_compose_msi_msg,
@@ -1422,6 +1442,8 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
if (!its_dev)
return -ENOMEM;
+ its_dev->dev = dev;
+
pr_debug("ITT %d entries, %d bits\n", nvec, ilog2(nvec));
out:
info->scratchpad[0].ptr = its_dev;
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index be3c34e..6add8da 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -585,6 +585,10 @@ void handle_fasteoi_irq(struct irq_desc *desc)
goto out;
}
+#ifdef CONFIG_CAVIUM_ERRATUM_28168
+ if (chip->irq_ack)
+ chip->irq_ack(&desc->irq_data);
+#endif
kstat_incr_irqs_this_cpu(desc);
if (desc->istate & IRQS_ONESHOT)
mask_irq(desc);
--
1.7.1
^ permalink raw reply related
* [PATCH] ARM: dts: rockchip: add i2c-bus subnode to edp
From: ayaka @ 2016-10-22 3:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1681294.eoXpQL8f8l@phil>
On 10/21/2016 04:25 PM, Heiko Stuebner wrote:
> Am Donnerstag, 20. Oktober 2016, 15:47:56 CEST schrieb Tomeu Vizoso:
>> On 10/20/2016 03:45 PM, Heiko St?bner wrote:
>>> Am Donnerstag, 20. Oktober 2016, 10:07:25 schrieb Tomeu Vizoso:
>>>> Add an empty 'i2c-bus' subnode to the edp node just so that the I2C core
>>>> doesn't attemp to parse the 'ports' subnode as containing i2c devices.
>>>>
>>>> This is to avoid spurious failure messages such as:
>>>>
>>>> i2c i2c-6: of_i2c: modalias failure on /dp at ff970000/ports
>>> On the one hand, the edp really has an i2c bus - with its only client the
>>> EDID listening at 0x50 (and maybe 0x30).
>>>
>>> On the other hand, adding an empty bus to the (implementation independent)
>>> devicetree just to make the Linux i2c subsystem happy sounds heavily like
>>> a
>>> implementation-specific hack, as the edp i2c bus doesn't leak into the
>>> outside world otherwise.
>>>
>>> I guess this empty i2c bus not being part of the binding document points
>>> heavily into the implementation-specific corner :-) .
>>>
>>> My short search on other patches touching this didn't reveal anything but
>>> maybe this was already discussed somewhere and found to be ok?
>> Here it is:
>>
>> http://www.spinics.net/lists/linux-tegra/msg27862.html
> thanks ... I'm still not sure about the placeholder though, aka needing an
> undocumented subnode to make a Linux error message silent.
Sorry, I report the error result, it would work.
And about the problem at this thread beginning, I found I have to use
something like Xserver to access DRM or the panel would not be power on.
The legacy fbdev won't help.
But there is still problem to be solved, so the eDP panel for firefly is
not ready yet.
>
> In the thread you pointed to I also did not see any dt-maintainer involvement
> pointing one way or another, but spinics is often not easy to navigate
> threads, so I may have missed that.
>
>
>>> Another option could be to just make of_i2c_register_device silent if
>>> of_modalias_node returns -ENODEV?
>
> Heiko
>
>>>> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>>>> Cc: Randy Li <randy.li@rock-chips.com>
>>>> Cc: Jon Hunter <jonathanh@nvidia.com>
>>>> ---
>>>>
>>>> arch/arm/boot/dts/rk3288.dtsi | 5 +++++
>>>> 1 file changed, 5 insertions(+)
>>>>
>>>> diff --git a/arch/arm/boot/dts/rk3288.dtsi
>>>> b/arch/arm/boot/dts/rk3288.dtsi
>>>> index 2f814ffeb605..94f4b7eecca2 100644
>>>> --- a/arch/arm/boot/dts/rk3288.dtsi
>>>> +++ b/arch/arm/boot/dts/rk3288.dtsi
>>>> @@ -1075,6 +1075,11 @@
>>>>
>>>> };
>>>>
>>>> };
>>>>
>>>> };
>>>>
>>>> +
>>>> + i2c-bus {
>>>> + #address-cells = <1>;
>>>> + #size-cells = <0>;
>>>> + };
>>>>
>>>> };
>>>>
>>>> hdmi: hdmi at ff980000 {
>
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip
>
^ permalink raw reply
* [PATCH] video: ARM CLCD: fix Vexpress regression
From: Amit Pundir @ 2016-10-22 3:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476945992-5164-1-git-send-email-linus.walleij@linaro.org>
On 20 October 2016 at 14:46, Linus Walleij <linus.walleij@linaro.org> wrote:
> The CLCD does not come up on Versatile Express as it does not
> (currently) have a syscon node for controlling the block apart
> from the CLCD itself. Make sure the .init() function can bail
> out without an error making it probe again.
>
> Reported-by: Amit Pundir <amit.pundir@linaro.org>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> drivers/video/fbdev/amba-clcd-versatile.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/video/fbdev/amba-clcd-versatile.c b/drivers/video/fbdev/amba-clcd-versatile.c
> index 19ad8645d93c..d909b7dda14d 100644
> --- a/drivers/video/fbdev/amba-clcd-versatile.c
> +++ b/drivers/video/fbdev/amba-clcd-versatile.c
> @@ -527,7 +527,8 @@ int versatile_clcd_init_panel(struct clcd_fb *fb,
> &clcd_id);
> if (!np) {
> dev_err(dev, "no Versatile syscon node\n");
> - return -ENODEV;
> + /* Vexpress does not have this */
> + return 0;
> }
> versatile_clcd_type = (enum versatile_clcd)clcd_id->data;
Thanks. Works on my Qemu + Android setup.
Tested-by: Amit Pundir <amit.pundir@linaro.org>
>
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH v2 3/3] ARM: dts: imx6qdl-apalis: Use enable-gpios property for backlight
From: Shawn Guo @ 2016-10-22 3:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2206aa18153f33a2b6763e2bc6c87bf83eadb674.1474260360.git.maitysanchayan@gmail.com>
On Mon, Sep 19, 2016 at 10:41:53AM +0530, Sanchayan Maity wrote:
> Use enable-gpios property of PWM backlight driver for backlight
> control.
>
> Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com>
Applied, thanks.
^ permalink raw reply
* [PATCH v2 2/3] ARM: dts: imx6q-apalis-ixora: Remove use of pwm-leds
From: Shawn Guo @ 2016-10-22 3:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1c9c910104414bdfbad077ccc3baca57974ba8c7.1474260360.git.maitysanchayan@gmail.com>
On Mon, Sep 19, 2016 at 10:41:52AM +0530, Sanchayan Maity wrote:
> Remove use of pwm-leds and use the standard /sys/class/pwm
> interface from PWM subsystem.
>
> Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com>
> Acked-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
Applied, thanks.
^ permalink raw reply
* [PATCH v2 1/3] ARM: dts: imx6qdl-apalis: Do not rely on DDC I2C bus bitbang for HDMI
From: Shawn Guo @ 2016-10-22 3:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2263d508999ada9476268138b2922702eb50131f.1474260360.git.maitysanchayan@gmail.com>
On Mon, Sep 19, 2016 at 10:41:51AM +0530, Sanchayan Maity wrote:
> Remove the use of DDC I2C bus bitbang to support reading of EDID
> and rely on support from internal HDMI I2C master controller instead.
> As a result remove the device tree property ddc-i2c-bus.
>
> Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com>
I think that the dw-hdmi i2c support [1] is a prerequisite of this
patch. I do not see it lands on v4.9-rc1. Or am I missing something?
Shawn
[1] https://patchwork.kernel.org/patch/9296883/
> ---
> Changes since v1:
>
> Change the ranking in i2c aliases
>
> v1: https://lkml.org/lkml/2016/9/14/55
> ---
> arch/arm/boot/dts/imx6q-apalis-ixora.dts | 12 +++---------
> arch/arm/boot/dts/imx6qdl-apalis.dtsi | 25 +++++++++----------------
> 2 files changed, 12 insertions(+), 25 deletions(-)
>
> diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora.dts b/arch/arm/boot/dts/imx6q-apalis-ixora.dts
> index 207b85b..82b81e0 100644
> --- a/arch/arm/boot/dts/imx6q-apalis-ixora.dts
> +++ b/arch/arm/boot/dts/imx6q-apalis-ixora.dts
> @@ -55,10 +55,9 @@
> "fsl,imx6q";
>
> aliases {
> - i2c0 = &i2cddc;
> - i2c1 = &i2c1;
> - i2c2 = &i2c2;
> - i2c3 = &i2c3;
> + i2c0 = &i2c1;
> + i2c1 = &i2c2;
> + i2c2 = &i2c3;
> };
>
> aliases {
> @@ -186,11 +185,6 @@
> };
>
> &hdmi {
> - ddc-i2c-bus = <&i2cddc>;
> - status = "okay";
> -};
> -
> -&i2cddc {
> status = "okay";
> };
>
> diff --git a/arch/arm/boot/dts/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
> index 99e323b..8c67dd8 100644
> --- a/arch/arm/boot/dts/imx6qdl-apalis.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
> @@ -53,18 +53,6 @@
> status = "disabled";
> };
>
> - /* DDC_I2C: I2C2_SDA/SCL on MXM3 205/207 */
> - i2cddc: i2c at 0 {
> - compatible = "i2c-gpio";
> - pinctrl-names = "default";
> - pinctrl-0 = <&pinctrl_i2c_ddc>;
> - gpios = <&gpio3 16 GPIO_ACTIVE_HIGH /* sda */
> - &gpio2 30 GPIO_ACTIVE_HIGH /* scl */
> - >;
> - i2c-gpio,delay-us = <2>; /* ~100 kHz */
> - status = "disabled";
> - };
> -
> reg_1p8v: regulator-1p8v {
> compatible = "regulator-fixed";
> regulator-name = "1P8V";
> @@ -209,6 +197,12 @@
> };
> };
>
> +&hdmi {
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_hdmi_ddc>;
> + status = "disabled";
> +};
> +
> /*
> * GEN1_I2C: I2C1_SDA/SCL on MXM3 209/211 (e.g. RTC on carrier
> * board)
> @@ -633,11 +627,10 @@
> >;
> };
>
> - pinctrl_i2c_ddc: gpioi2cddcgrp {
> + pinctrl_hdmi_ddc: hdmiddcgrp {
> fsl,pins = <
> - /* DDC bitbang */
> - MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x1b0b0
> - MX6QDL_PAD_EIM_D16__GPIO3_IO16 0x1b0b0
> + MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL 0x4001b8b1
> + MX6QDL_PAD_EIM_D16__HDMI_TX_DDC_SDA 0x4001b8b1
> >;
> };
>
> --
> 2.9.3
>
^ permalink raw reply
* [PATCH] ARM: dts: imx6: Add support for Toradex Colibri iMX6 module
From: Shawn Guo @ 2016-10-22 3:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160921112438.8661-1-maitysanchayan@gmail.com>
On Wed, Sep 21, 2016 at 04:54:38PM +0530, Sanchayan Maity wrote:
> Add support for Toradex Colibri iMX6 module.
>
> Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com>
Applied, thanks.
^ permalink raw reply
* [PATCH v3 [fix]] PM / doc: Update device documentation for devices in IRQ safe PM domains
From: Rafael J. Wysocki @ 2016-10-22 0:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477090375-13814-1-git-send-email-lina.iyer@linaro.org>
On Friday, October 21, 2016 03:52:55 PM Lina Iyer wrote:
> Update documentation to reflect the changes made to support IRQ safe PM
> domains.
>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---
> Changes since v3:
> - Moved para to the end of the section
> - Added clause for all IRQ safe devices in a domain
> - Cleanup explanation of nested domains
> ---
> Documentation/power/devices.txt | 11 ++++++++++-
> 1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
> index 8ba6625..9218ce6 100644
> --- a/Documentation/power/devices.txt
> +++ b/Documentation/power/devices.txt
> @@ -607,7 +607,9 @@ individually. Instead, a set of devices sharing a power resource can be put
> into a low-power state together at the same time by turning off the shared
> power resource. Of course, they also need to be put into the full-power state
> together, by turning the shared power resource on. A set of devices with this
> -property is often referred to as a power domain.
> +property is often referred to as a power domain. A power domain may also be
> +nested inside another power domain. The nested domain is referred to as the
> +sub-domain of the parent domain.
>
> Support for power domains is provided through the pm_domain field of struct
> device. This field is a pointer to an object of type struct dev_pm_domain,
> @@ -629,6 +631,13 @@ support for power domains into subsystem-level callbacks, for example by
> modifying the platform bus type. Other platforms need not implement it or take
> it into account in any way.
>
> +Devices and PM domains may be defined as IRQ-safe, if they can be powered
> +on/off even when the IRQs are disabled.
What IRQ-safe means for devices is that their runtime PM callbacks may be
invoked with interrupts disabled on the local CPU. I guess the meaning of
IRQ-safe for PM domains is analogous, but the above isn't precise enough to me.
> An IRQ-safe device in a domain will
> +disallow power management on the domain, unless the domain is also defined as
> +IRQ-safe. In other words, a domain containing all IRQ-safe devices must also
> +be defined as IRQ-safe. Another restriction this framework imposes on the
> +parent domain of an IRQ-safe domain is that the parent domain must also be
> +defined as IRQ-safe.
What about this:
"Devices may be defined as IRQ-safe which indicates to the PM core that their
runtime PM callbacks may be invoked with disabled interrupts (see
Documentation/power/runtime_pm.txt for more information). If an IRQ-safe
device belongs to a PM domain, the runtime PM of the domain will be disallowed,
unless the domain itself is defined as IRQ-safe. However, a PM domain can only
be defined as IRQ-safe if all of the devices in it are IRQ-safe. Moreover, if
an IRQ-safe domain has a parent domain, the runtime PM of the parent is only
allowed if the parent itself is IRQ-safe too with the additional restriction
that all child domains of an IRQ-safe parent must also be IRQ-safe."
Does it actually reflect what the code does?
Thanks,
Rafael
^ permalink raw reply
* [PATCH] ACPI:RASF- Adding support for RASF PCC interfaces.
From: somasundaram.a at hpe.com @ 2016-10-21 23:59 UTC (permalink / raw)
To: linux-arm-kernel
From: A Somasundaram <somasundaram.a@hpe.com>
These files contains pcc interfaces for rasf table, and basic rasf init, as per
ACPI 5.1 & upwards revision. section 5.2.20, chapter 14 Platform communication channel
are references for this implementation.
This module uses pcc interfaces to talk to ACPI HW. This version has PCC interfaces
ready.
The functions to send RASF commands to be used by OSPM is planned for future revision
of the file(rasf_acpi.c).
Signed-off-by:somasundaram.a at hpe.com
---
drivers/acpi/Kconfig | 15 ++
drivers/acpi/Makefile | 1 +
drivers/acpi/processor_driver.c | 6 +-
drivers/acpi/rasf_acpi.c | 330 ++++++++++++++++++++++++++++++++++++++++
include/acpi/rasf_acpi.h | 58 +++++++
5 files changed, 409 insertions(+), 1 deletion(-)
create mode 100644 drivers/acpi/rasf_acpi.c
create mode 100644 include/acpi/rasf_acpi.h
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 445ce28..3a1b24fd 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -238,6 +238,21 @@ config ACPI_CPPC_LIB
If your platform does not support CPPC in firmware,
leave this option disabled.
+config ACPI_RASF_LIB
+ bool
+ depends on ACPI_PROCESSOR
+ select MAILBOX
+ select PCC
+ default y
+ help
+ The files corresponding to this option implements pcc interfaces
+ (platform communication channel) to talk to RASF(RAS Feature table)
+ in the ACPI Complaint hardware platform. The first revision(current one)
+ contains basic init of RASF(extraction of RASF Table, from OS system table)
+ and, pcc interfaces.
+ Subsequent revision will contain OSPM interfaces to send RASF
+ Memory patrol scrub commands to the ACPI hardware.
+
config ACPI_PROCESSOR
tristate "Processor"
depends on X86 || IA64 || ARM64
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 5ae9d85..0bbf0d8 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -81,6 +81,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
obj-$(CONFIG_ACPI_BGRT) += bgrt.o
obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi.o
+obj-$(CONFIG_ACPI_RASF_LIB) += rasf_acpi.o
obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o
# processor has its own "processor." module_param namespace
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index 0553aee..c7aea1a 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -32,7 +32,7 @@
#include <linux/cpuidle.h>
#include <linux/slab.h>
#include <linux/acpi.h>
-
+#include<acpi/rasf_acpi.h>
#include <acpi/processor.h>
#include "internal.h"
@@ -66,6 +66,8 @@ static struct device_driver acpi_processor_driver = {
.remove = acpi_processor_stop,
};
+extern RASF_STATUS rasf_acpi_init(void );
+
static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
{
struct acpi_device *device = data;
@@ -257,6 +259,8 @@ static int __acpi_processor_start(struct acpi_device *device)
status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
acpi_processor_notify, device);
+ rasf_acpi_init();
+ pr_info("rasf init called \n");
if (ACPI_SUCCESS(status))
return 0;
diff --git a/drivers/acpi/rasf_acpi.c b/drivers/acpi/rasf_acpi.c
new file mode 100644
index 0000000..1d378cf
--- /dev/null
+++ b/drivers/acpi/rasf_acpi.c
@@ -0,0 +1,330 @@
+/*
+ * (C) Copyright 2014, 2015 Hewlett-Packard Enterprises.
+ * A.Somasundaram, email: somasundaram.a at hpe.com
+ * This file contains
+ * RASF - ACPI 6.1 Specification, section 5.2.20
+ * PCC(Platform Communications Channel) - ACPI 6.1 Specification , chapter 14
+ * This file contains PCC(Platform communication channel) interfaces, and basic RASF Init, which extracts the RASF table and
+ * Registers the PCC channel for communicating with the ACPI compliant platform that contains RASF command support in hardware
+ *
+ *Next revision of this file will contain functions for sending RASF commands for memory patrol scrubbing. This version contains
+ * core framework of PCC communication and RASF Init.
+ *
+ */
+
+#define pr_fmt(fmt) "ACPI RASF: " fmt
+#include<linux/export.h>
+#include<acpi/rasf_acpi.h>
+#include <linux/delay.h>
+#include <linux/ktime.h>
+#include<acpi/acpixf.h>
+
+#ifdef NEXT_REV
+/*
+ * Lock to provide mutually exclusive access to pcc channel, this is for next version.
+ * when functions for RASF command send/recv are implemented.
+ */
+static DEFINE_SPINLOCK(rasf_lock);
+#endif
+
+
+/* Data structure for pcc communication and rasf table */
+
+static struct mbox_chan *pcc_channel;
+static void __iomem *pcc_comm_addr;
+static u64 comm_base_addr;
+static int pcc_subspace_idx = -1;
+static bool pcc_channel_acquired;
+static ktime_t deadline;
+static unsigned int pcc_mpar, pcc_mrtt;
+static struct acpi_table_rasf *pRasfTable = NULL;
+RASF_STATUS rasf_acpi_init(void );
+
+#ifdef NEXT_REV
+/* pcc mapped address + header size + offset within PCC subspace
+ * This will be useful in next revision, when functions for RASF Command send/recv are implemented.
+ */
+#define RASF_VADDR(offs) (pcc_comm_addr + 0x8 + (offs))
+#endif
+
+/*
+ * Arbitrary Retries for pcc commands.
+ */
+#define NUM_RETRIES 600
+
+/*
+ *This function checks the pcc channel availability
+ *
+ *
+ */
+static int rasf_check_pcc_chan(void)
+{
+ int ret = -EIO;
+
+ struct acpi_rasf_shared_memory __iomem *generic_comm_base = pcc_comm_addr;
+ ktime_t next_deadline = ktime_add(ktime_get(), deadline);
+
+ while (!ktime_after(ktime_get(), next_deadline)) {
+ /*
+ * As per ACPI spec, the PCC space wil be initialized by
+ * platform and should have set the command completion bit when
+ * PCC can be used by OSPM
+ */
+ if (readw_relaxed(&generic_comm_base->status) & RASF_PCC_CMD_COMPLETE) {
+ ret = 0;
+ break;
+ }
+ /*
+ * Reducing the bus traffic in case this loop takes longer than
+ * a few retries.
+ */
+ udelay(3);
+ }
+
+ return ret;
+}
+
+static int rasf_send_pcc_cmd(u16 cmd)
+{
+ int ret = -EIO;
+
+ struct acpi_rasf_shared_memory *generic_comm_base =
+ (struct acpi_rasf_shared_memory *) pcc_comm_addr;
+ static ktime_t last_cmd_cmpl_time, last_mpar_reset;
+ static int mpar_count;
+ unsigned int time_delta;
+
+ /*
+ * For CMD_WRITE we know for a fact the caller should have checked
+ * the channel before writing to PCC space
+ */
+ if (cmd == RASF_CMD_READ) {
+ ret = rasf_check_pcc_chan();
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * Handle the Minimum Request Turnaround Time(MRTT)
+ * "The minimum amount of time that OSPM must wait after the completion
+ * of a command before issuing the next command, in microseconds"
+ */
+ if (pcc_mrtt) {
+ time_delta = ktime_us_delta(ktime_get(), last_cmd_cmpl_time);
+ if (pcc_mrtt > time_delta)
+ udelay(pcc_mrtt - time_delta);
+ }
+
+ /*
+ * Handle the non-zero Maximum Periodic Access Rate(MPAR)
+ * "The maximum number of periodic requests that the subspace channel can
+ * support, reported in commands per minute. 0 indicates no limitation."
+ *
+ * This parameter should be ideally zero or large enough so that it can
+ * handle maximum number of requests that all the cores in the system can
+ * collectively generate. If it is not, we will follow the spec and just
+ * not send the request to the platform after hitting the MPAR limit in
+ * any 60s window
+ */
+ if (pcc_mpar) {
+ if (mpar_count == 0) {
+ time_delta = ktime_ms_delta(ktime_get(), last_mpar_reset);
+ if (time_delta < 60 * MSEC_PER_SEC) {
+ pr_debug("PCC cmd not sent due to MPAR limit");
+ return -EIO;
+ }
+ last_mpar_reset = ktime_get();
+ mpar_count = pcc_mpar;
+ }
+ mpar_count--;
+ }
+
+ /* Write to the shared comm region. */
+ writew_relaxed(cmd, &generic_comm_base->command);
+
+ /* Flip CMD COMPLETE bit */
+ writew_relaxed(0, &generic_comm_base->status);
+
+ /* Ring doorbell */
+ ret = mbox_send_message(pcc_channel, &cmd);
+ if (ret < 0) {
+ pr_err("Err sending PCC mbox message. cmd:%d, ret:%d\n",
+ cmd, ret);
+ return ret;
+ }
+
+ /*
+ * For READs we need to ensure the cmd completed to ensure
+ * the ensuing read()s can proceed. For WRITEs we dont care
+ * because the actual write()s are done before coming here
+ * and the next READ or WRITE will check if the channel
+ * is busy/free@the entry of this call.
+ *
+ * If Minimum Request Turnaround Time is non-zero, we need
+ * to record the completion time of both READ and WRITE
+ * command for proper handling of MRTT, so we need to check
+ * for pcc_mrtt in addition to CMD_READ
+ */
+ if (cmd == RASF_CMD_READ || pcc_mrtt) {
+ ret = rasf_check_pcc_chan();
+ if (pcc_mrtt)
+ last_cmd_cmpl_time = ktime_get();
+ }
+
+ mbox_client_txdone(pcc_channel, ret);
+ return ret;
+}
+
+static void rasf_chan_tx_done(struct mbox_client *cl, void *msg, int ret)
+{
+ if (ret < 0)
+ pr_debug("TX did not complete: CMD sent:%x, ret:%d\n",
+ *(u16 *)msg, ret);
+ else
+ pr_debug("TX completed. CMD sent:%x, ret:%d\n",
+ *(u16 *)msg, ret);
+}
+
+struct mbox_client rasf_mbox_cl = {
+ .tx_done = rasf_chan_tx_done,
+ .knows_txdone = true,
+};
+
+
+
+static int rasf_register_pcc_channel(int pcc_subspace_idx)
+{
+ struct acpi_pcct_hw_reduced *rasf_ss;
+ unsigned int len;
+ u64 usecs_lat;
+
+ if (pcc_subspace_idx >= 0) {
+ pcc_channel = pcc_mbox_request_channel(&rasf_mbox_cl,
+ pcc_subspace_idx);
+
+ if (IS_ERR(pcc_channel)) {
+ pr_err("Failed to find PCC communication channel\n");
+ return -ENODEV;
+ }
+
+ /*
+ * The PCC mailbox controller driver should
+ * have parsed the PCCT (global table of all
+ * PCC channels) and stored pointers to the
+ * subspace communication region in con_priv.
+ */
+ rasf_ss = pcc_channel->con_priv;
+
+ if (!rasf_ss) {
+ pr_err("No PCC subspace found for CPPC\n");
+ return -ENODEV;
+ }
+
+ /*
+ * This is the shared communication region
+ * for the OS and Platform to communicate over.
+ */
+ comm_base_addr = rasf_ss->base_address;
+ len = rasf_ss->length;
+
+ /*
+ * rasf_ss->latency is just a Nominal value. In reality
+ * the remote processor could be much slower to reply.
+ * So add an arbitrary amount of wait on top of Nominal.
+ */
+ usecs_lat = NUM_RETRIES * rasf_ss->latency;
+ deadline = ns_to_ktime(usecs_lat * NSEC_PER_USEC);
+ pcc_mrtt = rasf_ss->min_turnaround_time;
+ pcc_mpar = rasf_ss->max_access_rate;
+
+ pcc_comm_addr = acpi_os_ioremap(comm_base_addr, len);
+ if (!pcc_comm_addr) {
+ pr_err("Failed to ioremap PCC comm region mem\n");
+ return -ENOMEM;
+ }
+
+ /* Set flag so that we dont come here for each CPU. */
+ pcc_channel_acquired = true;
+ }
+
+ return 0;
+}
+
+#ifdef NEXT_REV
+
+/* The next revision of this file will contain the implementation of the following functions
+ *
+ *These functions are used for processing/sending RASF Commands.
+ *
+ */
+/*
+ * The below functions are exposed to OSPM, to query and, initiate memory range patrol.
+ *
+ *
+ */
+bool DoPatrolScrub(....)
+{
+}
+
+bool IsPatrolScrubExposedtoSw(...)
+{
+/* send command, for read */
+
+}
+
+bool GetPatrolParams(...)
+{
+}
+
+bool SetPatrolParams(...)
+{
+/* start patrol
+ stop patrol
+*/
+}
+#endif
+
+RASF_STATUS rasf_acpi_init(void )
+{
+ struct acpi_table_header *pAcpiTable = NULL;
+ acpi_size irasf_size = 0;
+ acpi_status status = AE_OK;
+
+
+ status = acpi_get_table_with_size("RASF", 0, &pAcpiTable, &irasf_size);
+
+ if (ACPI_FAILURE(status))
+ {
+
+ pr_err("rasf driver failed to initialize, get table failed\n");
+
+ pr_info("RASF Init failed \n");
+ return(RASF_FAILURE);
+ }
+
+ pRasfTable = kmalloc(sizeof(struct acpi_table_header), GFP_KERNEL);
+
+
+ if(NULL == pRasfTable)
+ {
+ pr_err("ptr to RasfTable, kmalloc failed \n");
+
+ pr_info("RASF Init failed \n");
+ /* error debug print */
+ return(RASF_FAILURE);
+ }
+ memcpy(pRasfTable, pAcpiTable, irasf_size);
+
+/* extract the pcc subspace channel id from the table */
+ pRasfTable = (struct acpi_table_rasf *)pAcpiTable;
+ memcpy(&pcc_subspace_idx, &pRasfTable->channel_id,12);
+ rasf_register_pcc_channel(pcc_subspace_idx);
+ pr_info("RASF Init Success \n");
+ return(RASF_SUCCESS);
+
+
+}
+EXPORT_SYMBOL_GPL(rasf_acpi_init);
+
+
+
diff --git a/include/acpi/rasf_acpi.h b/include/acpi/rasf_acpi.h
new file mode 100644
index 0000000..2f28ad3
--- /dev/null
+++ b/include/acpi/rasf_acpi.h
@@ -0,0 +1,58 @@
+/*
+ * RASF(feature for patrol scrubbing of memory ranges , if exposed to software)
+ * RASF Diagnostic driver header file
+ *
+ * (C) Copyright 2014, 2015 Hewlett-Packard Enterprises
+ * Author: A.Somasundaram (somasundaram.a at hpe.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#ifndef _RASF_ACPI_H
+#define _RASF_ACPI_H
+
+#include <linux/acpi.h>
+#include <linux/mailbox_controller.h>
+#include <linux/mailbox_client.h>
+#include <linux/types.h>
+
+typedef int RASF_STATUS;
+
+#define RASF_NUM_ENT 21
+#define RASF_REV 2
+
+#define RASF_PCC_CMD_COMPLETE 1
+
+/* CPPC specific PCC commands. */
+#define RASF_CMD_READ 0
+#define RASF_CMD_WRITE 1
+
+#define RASF_FAILURE 0
+#define RASF_SUCCESS 1
+
+/* Each register has the folowing format. */
+struct rasf_reg {
+ u8 descriptor;
+ u16 length;
+ u8 space_id;
+ u8 bit_width;
+ u8 bit_offset;
+ u8 access_width;
+ u64 __iomem address;
+} __packed;
+
+struct rasf_register_resource {
+ acpi_object_type type;
+ union {
+ struct rasf_reg reg;
+ u64 int_value;
+ } rasf_entry;
+};
+/* Methods to interact with the PCC mailbox controller. */
+extern struct mbox_chan *
+ pcc_mbox_request_channel(struct mbox_client *, unsigned int);
+
+#endif /* _CPPC_ACPI_H*/
--
1.9.1
^ permalink raw reply related
* [PATCH v3 4/4] arm64: dts: msm8996: Add SMP2P and APCS nodes
From: Sarangdhar Joshi @ 2016-10-21 23:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477091959-19580-1-git-send-email-spjoshi@codeaurora.org>
Add SMP2P and APCS DT nodes required for Qualcomm ADSP
Peripheral Image Loader.
Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Sarangdhar Joshi <spjoshi@codeaurora.org>
---
arch/arm64/boot/dts/qcom/msm8996.dtsi | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 60d2d20c..9e960c1 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -175,6 +175,30 @@
method = "smc";
};
+ adsp-smp2p {
+ compatible = "qcom,smp2p";
+ qcom,smem = <443>, <429>;
+
+ interrupts = <0 158 IRQ_TYPE_EDGE_RISING>;
+
+ qcom,ipc = <&apcs 16 10>;
+
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <2>;
+
+ adsp_smp2p_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+ #qcom,state-cells = <1>;
+ };
+
+ adsp_smp2p_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
smem {
compatible = "qcom,smem";
memory-region = <&smem_mem>;
@@ -203,6 +227,11 @@
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
};
+ apcs: syscon at 9820000 {
+ compatible = "syscon";
+ reg = <0x9820000 0x1000>;
+ };
+
gcc: clock-controller at 300000 {
compatible = "qcom,gcc-msm8996";
#clock-cells = <1>;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related
* [PATCH v3 3/4] arm64: dts: msm8996: Add SMEM DT nodes
From: Sarangdhar Joshi @ 2016-10-21 23:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477091959-19580-1-git-send-email-spjoshi@codeaurora.org>
From: Bjorn Andersson <bjorn.andersson@linaro.org>
Add SMEM and TCSR DT nodes on MSM8996.
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Sarangdhar Joshi <spjoshi@codeaurora.org>
---
arch/arm64/boot/dts/qcom/msm8996.dtsi | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 949b096..60d2d20c 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -164,17 +164,34 @@
};
+ tcsr_mutex: hwlock {
+ compatible = "qcom,tcsr-mutex";
+ syscon = <&tcsr_mutex_regs 0 0x1000>;
+ #hwlock-cells = <1>;
+ };
+
psci {
compatible = "arm,psci-1.0";
method = "smc";
};
+ smem {
+ compatible = "qcom,smem";
+ memory-region = <&smem_mem>;
+ hwlocks = <&tcsr_mutex 3>;
+ };
+
soc: soc {
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0 0 0xffffffff>;
compatible = "simple-bus";
+ tcsr_mutex_regs: syscon at 740000 {
+ compatible = "syscon";
+ reg = <0x740000 0x20000>;
+ };
+
intc: interrupt-controller at 9bc0000 {
compatible = "arm,gic-v3";
#interrupt-cells = <3>;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related
* [PATCH v3 2/4] arm64: dts: msm8996: Add reserve-memory nodes
From: Sarangdhar Joshi @ 2016-10-21 23:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477091959-19580-1-git-send-email-spjoshi@codeaurora.org>
Add reserve-memory nodes required for Qualcomm
Peripheral Image Loaders
Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Sarangdhar Joshi <spjoshi@codeaurora.org>
---
arch/arm64/boot/dts/qcom/msm8996.dtsi | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index 36216ae..949b096 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -36,6 +36,31 @@
#size-cells = <2>;
ranges;
+ mba_region: mba at 91500000 {
+ reg = <0x0 0x91500000 0x0 0x200000>;
+ no-map;
+ };
+
+ slpi_region: slpi at 90b00000 {
+ reg = <0x0 0x90b00000 0xa00000>;
+ no-map;
+ };
+
+ venus_region: venus at 90400000 {
+ reg = <0x0 0x90400000 0x0 0x700000>;
+ no-map;
+ };
+
+ adsp_region: adsp at 8ea00000 {
+ reg = <0x0 0x8ea00000 0x0 0x1a00000>;
+ no-map;
+ };
+
+ mpss_region: mpss at 88800000 {
+ reg = <0x0 0x88800000 0x0 0x6200000>;
+ no-map;
+ };
+
smem_mem: smem-mem at 86000000 {
reg = <0x0 0x86000000 0x0 0x200000>;
no-map;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related
* [PATCH v3 1/4] arm64: dts: msm8996: Add SMEM reserve-memory node
From: Sarangdhar Joshi @ 2016-10-21 23:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477091959-19580-1-git-send-email-spjoshi@codeaurora.org>
Add DT node to carveout memory for shared memory region.
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Sarangdhar Joshi <spjoshi@codeaurora.org>
---
arch/arm64/boot/dts/qcom/msm8996.dtsi | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index d6da223..36216ae 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -31,6 +31,17 @@
reg = <0 0 0 0>;
};
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ smem_mem: smem-mem at 86000000 {
+ reg = <0x0 0x86000000 0x0 0x200000>;
+ no-map;
+ };
+ };
+
cpus {
#address-cells = <2>;
#size-cells = <0>;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related
* [PATCH v3 0/4] MSM8996 DT Support for ADSP PIL
From: Sarangdhar Joshi @ 2016-10-21 23:19 UTC (permalink / raw)
To: linux-arm-kernel
Add various device tree nodes to lay the groundwork for
Qualcomm ADSP Peripheral Image Loader.
Sorry, I didn't send any cover letter for v1.
Changes since v2:
- Remove empty lines from smem DT node (Stephen)
Changes since v1:
- Move hwlock DT node under root (/) (Bjorn and Andy)
- Rename smp2p-adsp to adsp-smp2p (Bjorn)
- Remove interrupt-parent property from node (Bjorn)
Bjorn Andersson (1):
arm64: dts: msm8996: Add SMEM DT nodes
Sarangdhar Joshi (3):
arm64: dts: msm8996: Add SMEM reserve-memory node
arm64: dts: msm8996: Add reserve-memory nodes
arm64: dts: msm8996: Add SMP2P and APCS nodes
arch/arm64/boot/dts/qcom/msm8996.dtsi | 82 +++++++++++++++++++++++++++++++++++
1 file changed, 82 insertions(+)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH v4 4/9] clk: sunxi-ng: Add minimums for all the relevant structures and clocks
From: André Przywara @ 2016-10-21 22:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a96b56fb7bda849e087b63a04ff76d1396c44d72.1476196031.git-series.maxime.ripard@free-electrons.com>
Salut,
On 11/10/16 15:28, Maxime Ripard wrote:
> Modify the current clocks we have to be able to specify the minimum for
> each clocks we support, just like we support the max.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
> drivers/clk/sunxi-ng/ccu_mult.c | 7 ++++++-
> drivers/clk/sunxi-ng/ccu_nk.c | 12 ++++++++----
> drivers/clk/sunxi-ng/ccu_nkm.c | 18 ++++++++++++------
> drivers/clk/sunxi-ng/ccu_nkmp.c | 16 ++++++++++++----
> drivers/clk/sunxi-ng/ccu_nm.c | 12 ++++++++----
> 5 files changed, 46 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/clk/sunxi-ng/ccu_mult.c b/drivers/clk/sunxi-ng/ccu_mult.c
> index 32a1964439a2..6a02ffee5386 100644
> --- a/drivers/clk/sunxi-ng/ccu_mult.c
> +++ b/drivers/clk/sunxi-ng/ccu_mult.c
> @@ -14,7 +14,7 @@
> #include "ccu_mult.h"
>
> struct _ccu_mult {
> - unsigned long mult, max;
> + unsigned long mult, min, max;
> };
>
> static void ccu_mult_find_best(unsigned long parent, unsigned long rate,
> @@ -23,6 +23,9 @@ static void ccu_mult_find_best(unsigned long parent, unsigned long rate,
> int _mult;
>
> _mult = rate / parent;
> + if (_mult < mult->min)
> + _mult = mult->min;
> +
> if (_mult > mult->max)
> _mult = mult->max;
>
> @@ -37,6 +40,7 @@ static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux,
> struct ccu_mult *cm = data;
> struct _ccu_mult _cm;
>
> + _cm.min = 1;
> _cm.max = 1 << cm->mult.width;
> ccu_mult_find_best(parent_rate, rate, &_cm);
>
> @@ -101,6 +105,7 @@ static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate,
> ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1,
> &parent_rate);
>
> + _cm.min = 1;
> _cm.max = 1 << cm->mult.width;
> ccu_mult_find_best(parent_rate, rate, &_cm);
>
> diff --git a/drivers/clk/sunxi-ng/ccu_nk.c b/drivers/clk/sunxi-ng/ccu_nk.c
> index e7e2e75618ef..a42d870ba0ef 100644
> --- a/drivers/clk/sunxi-ng/ccu_nk.c
> +++ b/drivers/clk/sunxi-ng/ccu_nk.c
> @@ -14,8 +14,8 @@
> #include "ccu_nk.h"
>
> struct _ccu_nk {
> - unsigned long n, max_n;
> - unsigned long k, max_k;
> + unsigned long n, min_n, max_n;
> + unsigned long k, min_k, max_k;
> };
>
> static void ccu_nk_find_best(unsigned long parent, unsigned long rate,
> @@ -25,8 +25,8 @@ static void ccu_nk_find_best(unsigned long parent, unsigned long rate,
> unsigned int best_k = 0, best_n = 0;
> unsigned int _k, _n;
>
> - for (_k = 1; _k <= nk->max_k; _k++) {
> - for (_n = 1; _n <= nk->max_n; _n++) {
> + for (_k = nk->min_k; _k <= nk->max_k; _k++) {
> + for (_n = nk->min_n; _n <= nk->max_n; _n++) {
> unsigned long tmp_rate = parent * _n * _k;
>
> if (tmp_rate > rate)
> @@ -97,7 +97,9 @@ static long ccu_nk_round_rate(struct clk_hw *hw, unsigned long rate,
> if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
> rate *= nk->fixed_post_div;
>
> + _nk.min_n = 1;
> _nk.max_n = 1 << nk->n.width;
> + _nk.min_k = 1;
> _nk.max_k = 1 << nk->k.width;
>
> ccu_nk_find_best(*parent_rate, rate, &_nk);
> @@ -120,7 +122,9 @@ static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate,
> if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
> rate = rate * nk->fixed_post_div;
>
> + _nk.min_n = 1;
> _nk.max_n = 1 << nk->n.width;
> + _nk.min_k = 1;
> _nk.max_k = 1 << nk->k.width;
>
> ccu_nk_find_best(parent_rate, rate, &_nk);
> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
> index 0b08d000eb38..b2a5fccf2f8c 100644
> --- a/drivers/clk/sunxi-ng/ccu_nkm.c
> +++ b/drivers/clk/sunxi-ng/ccu_nkm.c
> @@ -14,9 +14,9 @@
> #include "ccu_nkm.h"
>
> struct _ccu_nkm {
> - unsigned long n, max_n;
> - unsigned long k, max_k;
> - unsigned long m, max_m;
> + unsigned long n, min_n, max_n;
> + unsigned long k, min_k, max_k;
> + unsigned long m, min_m, max_m;
> };
>
> static void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
> @@ -26,9 +26,9 @@ static void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
> unsigned long best_n = 0, best_k = 0, best_m = 0;
> unsigned long _n, _k, _m;
>
> - for (_k = 1; _k <= nkm->max_k; _k++) {
> - for (_n = 1; _n <= nkm->max_n; _n++) {
> - for (_m = 1; _n <= nkm->max_m; _m++) {
> + for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
> + for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
> + for (_m = nkm->min_m; _n <= nkm->max_m; _m++) {
should be _m in the condition
> unsigned long tmp_rate;
>
> tmp_rate = parent * _n * _k / _m;
> @@ -100,8 +100,11 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
> struct ccu_nkm *nkm = data;
> struct _ccu_nkm _nkm;
>
> + _nkm.min_n = 1;
> _nkm.max_n = 1 << nkm->n.width;
> + _nkm.min_k = 1;
> _nkm.max_k = 1 << nkm->k.width;
> + _nkm.min_m = 1;
> _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
>
> ccu_nkm_find_best(parent_rate, rate, &_nkm);
> @@ -126,8 +129,11 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
> unsigned long flags;
> u32 reg;
>
> + _nkm.min_n = 1;
> _nkm.max_n = 1 << nkm->n.width;
> + _nkm.min_k = 1;
> _nkm.max_k = 1 << nkm->k.width;
> + _nkm.min_m = 1;
> _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
>
> ccu_nkm_find_best(parent_rate, rate, &_nkm);
> diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c
> index 4b457d8cce11..2c1398192e48 100644
> --- a/drivers/clk/sunxi-ng/ccu_nkmp.c
> +++ b/drivers/clk/sunxi-ng/ccu_nkmp.c
> @@ -27,10 +27,10 @@ static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
> unsigned long best_n = 0, best_k = 0, best_m = 0, best_p = 0;
> unsigned long _n, _k, _m, _p;
>
> - for (_k = 1; _k <= nkmp->max_k; _k++) {
> - for (_n = 1; _n <= nkm->max_n; _n++) {
> - for (_m = 1; _n <= nkm->max_m; _m++) {
> - for (_p = 1; _p <= nkmp->max_p; _p <<= 1) {
> + for (_k = nkmp->min_k; _k <= nkmp->max_k; _k++) {
> + for (_n = nkmp->min_n; _n <= nkmp->max_n; _n++) {
> + for (_m = nkmp->min_m; _n <= nkmp->max_m; _m++) {
Same here: _m <= ...
> + for (_p = nkmp->min_p; _p <= nkmp->max_p; _p <<= 1) {
> unsigned long tmp_rate;
>
> tmp_rate = parent * _n * _k / (_m * _p);
> @@ -107,9 +107,13 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
> struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
> struct _ccu_nkmp _nkmp;
>
> + _nkmp.min_n = 1;
> _nkmp.max_n = 1 << nkmp->n.width;
> + _nkmp.min_k = 1;
> _nkmp.max_k = 1 << nkmp->k.width;
> + _nkmp.min_m = 1;
> _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
> + _nkmp.min_p = 1;
> _nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1);
>
> ccu_nkmp_find_best(*parent_rate, rate, &_nkmp);
> @@ -125,9 +129,13 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
> unsigned long flags;
> u32 reg;
>
> + _nkmp.min_n = 1;
> _nkmp.max_n = 1 << nkmp->n.width;
> + _nkmp.min_k = 1;
> _nkmp.max_k = 1 << nkmp->k.width;
> + _nkmp.min_m = 1;
> _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
> + _nkmp.min_p = 1;
> _nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1);
>
> ccu_nkmp_find_best(parent_rate, rate, &_nkmp);
> diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
> index c6d652289320..2a190bc032a9 100644
> --- a/drivers/clk/sunxi-ng/ccu_nm.c
> +++ b/drivers/clk/sunxi-ng/ccu_nm.c
> @@ -15,8 +15,8 @@
> #include "ccu_nm.h"
>
> struct _ccu_nm {
> - unsigned long n, max_n;
> - unsigned long m, max_m;
> + unsigned long n, min_n, max_n;
> + unsigned long m, min_m, max_m;
> };
>
> static void ccu_nm_find_best(unsigned long parent, unsigned long rate,
> @@ -26,8 +26,8 @@ static void ccu_nm_find_best(unsigned long parent, unsigned long rate,
> unsigned long best_n = 0, best_m = 0;
> unsigned long _n, _m;
>
> - for (_n = 1; _n <= nm->max_n; _n++) {
> - for (_m = 1; _n <= nm->max_m; _m++) {
> + for (_n = nm->min_n; _n <= nm->max_n; _n++) {
> + for (_m = nm->min_m; _n <= nm->max_m; _m++) {
And here: _m <= ...
Interestingly those typos were already in the code before.
Lets hope I don't dream of m's and k's tonight.
Cheers,
Andre.
> unsigned long tmp_rate = parent * _n / _m;
>
> if (tmp_rate > rate)
> @@ -93,7 +93,9 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
> struct ccu_nm *nm = hw_to_ccu_nm(hw);
> struct _ccu_nm _nm;
>
> + _nm.min_n = 1;
> _nm.max_n = 1 << nm->n.width;
> + _nm.min_m = 1;
> _nm.max_m = nm->m.max ?: 1 << nm->m.width;
>
> ccu_nm_find_best(*parent_rate, rate, &_nm);
> @@ -114,7 +116,9 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
> else
> ccu_frac_helper_disable(&nm->common, &nm->frac);
>
> + _nm.min_n = 1;
> _nm.max_n = 1 << nm->n.width;
> + _nm.min_m = 1;
> _nm.max_m = nm->m.max ?: 1 << nm->m.width;
>
> ccu_nm_find_best(parent_rate, rate, &_nm);
>
^ permalink raw reply
* [PATCH v3 [fix]] PM / doc: Update device documentation for devices in IRQ safe PM domains
From: Lina Iyer @ 2016-10-21 22:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161021152313.GC72940@linaro.org>
Update documentation to reflect the changes made to support IRQ safe PM
domains.
Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
Changes since v3:
- Moved para to the end of the section
- Added clause for all IRQ safe devices in a domain
- Cleanup explanation of nested domains
---
Documentation/power/devices.txt | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index 8ba6625..9218ce6 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -607,7 +607,9 @@ individually. Instead, a set of devices sharing a power resource can be put
into a low-power state together at the same time by turning off the shared
power resource. Of course, they also need to be put into the full-power state
together, by turning the shared power resource on. A set of devices with this
-property is often referred to as a power domain.
+property is often referred to as a power domain. A power domain may also be
+nested inside another power domain. The nested domain is referred to as the
+sub-domain of the parent domain.
Support for power domains is provided through the pm_domain field of struct
device. This field is a pointer to an object of type struct dev_pm_domain,
@@ -629,6 +631,13 @@ support for power domains into subsystem-level callbacks, for example by
modifying the platform bus type. Other platforms need not implement it or take
it into account in any way.
+Devices and PM domains may be defined as IRQ-safe, if they can be powered
+on/off even when the IRQs are disabled. An IRQ-safe device in a domain will
+disallow power management on the domain, unless the domain is also defined as
+IRQ-safe. In other words, a domain containing all IRQ-safe devices must also
+be defined as IRQ-safe. Another restriction this framework imposes on the
+parent domain of an IRQ-safe domain is that the parent domain must also be
+defined as IRQ-safe.
Device Low Power (suspend) States
---------------------------------
--
2.7.4
^ permalink raw reply related
* [PATCH 1/2] pinctrl: pm8994: add pad voltage regulator defines
From: Andy Gross @ 2016-10-21 22:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdZYYawHAOyu09vVxkTFQdrPmHsX28C7sjrWQ57MzfR4JQ@mail.gmail.com>
On Sun, Sep 18, 2016 at 01:38:30PM +0200, Linus Walleij wrote:
> On Fri, Sep 16, 2016 at 7:41 PM, Srinivas Kandagatla
> <srinivas.kandagatla@linaro.org> wrote:
>
> > This patch adds defines for internal voltage regulators used
> > to switch voltage levels on gpio/mpp pads.
> >
> > Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
>
> Acked-by: Linus Walleij <linus.walleij@linaro.org>
>
> Andy can merge this with the rest of the stuff to the Qualcomm SoC tree.
Yup. Picked it up. Thanks!
Andy
^ permalink raw reply
* [PATCH v3 3/6] pwm: imx: support output polarity inversion
From: Lukasz Majewski @ 2016-10-21 21:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1b72dcbc9a021e6fa3aef62f63bbf93f@agner.ch>
Hi Stefan,
> On 2016-10-20 01:30, Lukasz Majewski wrote:
> > Hi Stefan,
> >
> >> Hi Stefan,
> >>
> >> > On 2016-10-12 15:15, Lukasz Majewski wrote:
> >> > > Hi Stefan,
> >> > >
> >> > >> On 2016-10-07 08:11, Bhuvanchandra DV wrote:
> >> > >> > From: Lothar Wassmann <LW@KARO-electronics.de>
> >> > >> >
> >> > >> > The i.MX pwm unit on i.MX27 and newer SoCs provides a
> >> > >> > configurable output polarity. This patch adds support to
> >> > >> > utilize this feature where available.
> >> > >> >
> >> > >> > Signed-off-by: Lothar Wa?mann <LW@KARO-electronics.de>
> >> > >> > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> >> > >> > Signed-off-by: Bhuvanchandra DV
> >> > >> > <bhuvanchandra.dv@toradex.com> Acked-by: Shawn Guo
> >> > >> > <shawn.guo@linaro.org> Reviewed-by: Sascha Hauer
> >> > >> > <s.hauer@pengutronix.de> ---
> >> > >> > Documentation/devicetree/bindings/pwm/imx-pwm.txt | 6 +--
> >> > >> > drivers/pwm/pwm-imx.c | 51
> >> > >> > +++++++++++++++++++++-- 2 files changed, 51 insertions(+), 6
> >> > >> > deletions(-)
> >> > >> >
> >> > >> > diff --git
> >> > >> > a/Documentation/devicetree/bindings/pwm/imx-pwm.txt
> >> > >> > b/Documentation/devicetree/bindings/pwm/imx-pwm.txt index
> >> > >> > e00c2e9..c61bdf8 100644 ---
> >> > >> > a/Documentation/devicetree/bindings/pwm/imx-pwm.txt +++
> >> > >> > b/Documentation/devicetree/bindings/pwm/imx-pwm.txt @@ -6,8
> >> > >> > +6,8 @@ Required properties:
> >> > >> > - "fsl,imx1-pwm" for PWM compatible with the one
> >> > >> > integrated on i.MX1
> >> > >> > - "fsl,imx27-pwm" for PWM compatible with the one
> >> > >> > integrated on i.MX27
> >> > >> > - reg: physical base address and length of the controller's
> >> > >> > registers -- #pwm-cells: should be 2. See pwm.txt in this
> >> > >> > directory for a description of
> >> > >> > - the cells format.
> >> > >> > +- #pwm-cells: 2 for i.MX1 and 3 for i.MX27 and newer SoCs.
> >> > >> > See pwm.txt
> >> > >> > + in this directory for a description of the cells format.
> >> > >> > - clocks : Clock specifiers for both ipg and per clocks.
> >> > >> > - clock-names : Clock names should include both "ipg" and
> >> > >> > "per" See the clock consumer binding,
> >> > >> > @@ -17,7 +17,7 @@ See the clock consumer binding,
> >> > >> > Example:
> >> > >> >
> >> > >> > pwm1: pwm at 53fb4000 {
> >> > >> > - #pwm-cells = <2>;
> >> > >> > + #pwm-cells = <3>;
> >> > >> > compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
> >> > >> > reg = <0x53fb4000 0x4000>;
> >> > >> > clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
> >> > >> > diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
> >> > >> > index d600fd5..c37d223 100644
> >> > >> > --- a/drivers/pwm/pwm-imx.c
> >> > >> > +++ b/drivers/pwm/pwm-imx.c
> >> > >> > @@ -38,6 +38,7 @@
> >> > >> > #define MX3_PWMCR_DOZEEN (1 << 24)
> >> > >> > #define MX3_PWMCR_WAITEN (1 << 23)
> >> > >> > #define MX3_PWMCR_DBGEN (1 << 22)
> >> > >> > +#define MX3_PWMCR_POUTC (1 << 18)
> >> > >> > #define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
> >> > >> > #define MX3_PWMCR_CLKSRC_IPG (1 << 16)
> >> > >> > #define MX3_PWMCR_SWR (1 << 3)
> >> > >> > @@ -180,6 +181,9 @@ static int imx_pwm_config_v2(struct
> >> > >> > pwm_chip *chip, if (enable)
> >> > >> > cr |= MX3_PWMCR_EN;
> >> > >> >
> >> > >> > + if (pwm->args.polarity == PWM_POLARITY_INVERSED)
> >> > >> > + cr |= MX3_PWMCR_POUTC;
> >> > >> > +
> >> > >>
> >> > >> This seems wrong to me, the config callback is meant for
> >> > >> period/duty cycle only.
> >
> > Unfortunately, it also resets the PWM IP block and setups it again
> > (by writing to PWMCR register). In that function we setup for
> > example MX3_PWMCR_DOZEEN
> > and MX3_PWMCR_DBGEN. Why cannot we setup polarity as well?
> >
> >
> > I've double checked the backlight and pwm code flow.
> >
> > Please find following snippet:
> >
> > [ 0.135545] ######### imx_pwm_probe
> > [ 0.135581] PWM supports output inversion
> > [ 0.136864] ######### pwm_backlight_probe
> > [ 0.136913] backlight supply power not found, using dummy
> > regulator [ 0.136984] ######### imx_pwm_set_polarity 1
> > [ 0.136995] imx_pwm_set_polarity: polarity set to inverted cr:
> > 0x40000 0xf08f8000
> > [ 0.137005] #########0 imx_pwm_config_v2 cr: 0x40000
> > [ 0.137683] #########1 imx_pwm_config_v2 cr: 0x0 0xf08f8000
> > [ 0.137693] #########2 imx_pwm_config_v2 cr: 0x1c20050
> > [ 0.137702] #########3 imx_pwm_config_v2 cr: 0x1c20050 0xf08f8000
> > [ 0.137711] @@@@@@@@@@ pwm_apply_state
Maybe a bit more logs:
[ 0.135451] ######### imx_pwm_probe
[ 0.135488] PWM supports output inversion
[ 0.136777] ######### pwm_backlight_probe
[ 0.136826] backlight supply power not found, using dummy regulator
[ 0.136893] ********* pwm_apply_state state->enabled: 0
[ 0.136902] ######### imx_pwm_set_polarity 1
[ 0.136913] imx_pwm_set_polarity: polarity set to inverted cr: 0x40000 0xf08f8000
[ 0.136923] #########0 imx_pwm_config_v2 cr: 0x40000
[ 0.137692] #########1 imx_pwm_config_v2 cr: 0x0 0xf08f8000
[ 0.137701] #########2 imx_pwm_config_v2 cr: 0x1c20050
[ 0.137710] #########3 imx_pwm_config_v2 cr: 0x1c20050 0xf08f8000
[ 0.137720] @@@@@@@@@@ pwm_apply_state
[ 0.137856] ********* pwm_apply_state state->enabled: 0
[ 0.137869] #########0 imx_pwm_config_v2 cr: 0x1c20050
[ 0.138904] #########1 imx_pwm_config_v2 cr: 0x0 0xf08f8000
[ 0.138913] #########2 imx_pwm_config_v2 cr: 0x1c20050
[ 0.138921] #########3 imx_pwm_config_v2 cr: 0x1c20050 0xf08f8000
[ 0.138928] @@@@@@@@@@ pwm_apply_state
[ 0.138940] ********* pwm_apply_state state->enabled: 1
^^^^^^^^^^^^^^^^^^ this is called from
pwm_backlight_power_on() from pwm_bl probe function
The problem here is not the lack of ->apply() callback, but the requirement to
perform software reset on the pwm_v2 fifo when the pwm_v2 is NOT enabled (state->enabled: 0).
As fair as I can see the pwm_state has following members: period, duty cycle, polarity and enabled.
I'm fine to implement ->apply() callback, which would change above values.
However, there is a problem with ->config() (imx_pwm_config_v2 @ pwm-imx.c) and imx pwm_v2 software
FIFO reset.
We can set polarity in any other kernel subsystem, which uses PWM (backlight in this example) and
then this setting would disappear when we call pwm_apply_state with state->enabled = 0 (as presented
in the log). This imposes setting polarity at ->config when we enable the PWM (as this patch does).
> >
> > Here the pwm_backlight_probe calls set_polarity callback available
> > in pwm - the polarity is set (the 0x40000 value).
> >
> > The above operation is performed in pwm_apply_state (@
> > drivers/pwm/core.c). In the same function, latter we call the
> > pwm->chip->ops->config(), which is the pointer to config_v2.
> > Since the PWM is not yet enabled, this function performs SW reset
> > and PWM inversion setting is cleared.
>
> That function should not do that.
I do agree that it shouldn't. Correct me if I'm wrong, but it seems like an
PWM HW requirement to perform the reset.
>It was probably already problematic
> in the old times, it is definitely now with the atomic PWM stuff.
The "atomic"[*] code (with ->apply() provided) will not solve this issue.
>
> >
> > Possible solutions:
> >
> > 1. Leave the original patch from Bhuvanchandra as it was (I'm for
> > this option)
>
> That really seems like a hack to me, and makes transition to the
> atomic PWM API more complex.
Could you be more specific here?
As I mentioned before, the problem is not with the lack of
"atomic" API.
For me the problem is with other subsystems (like pwm backlight)
which do require polarity inversion to work properly.
>
> If we can't make it happen properly in the current state of affairs,
We can set polarity properly with this patch. The only thing which needs fixing
and another revision of the patch) is the removal of condition:
- if (polarity == pwm->args.polarity)
- return 0;
at imx_pwm_set_polarity() function.
> we probably should first move to the atomic API.
>
> It really should not be that hard, since we already do almost
> everything in one function (imx_pwm_config_v2). We probably can
> almost just assign that function to the new apply function pointer
> and read information from the new state struct.
We do need to configure polarity according to DT value during the pwm
config_v2 configuration after PWM IP software reset.
>
> There are examples for instance here:
> https://patchwork.kernel.org/patch/7228221/
The atomicity[*]:
- It seems to me that this "atomicity" is just embracing all the ->enable, ->disable
and ->set_polarity in one -> apply callback. Is this just conceptual clean up or is
there any other reason for it (I'm just curious) ?
Best regards,
?ukasz Majewski
>
> --
> Stefan
>
> >
> > 2. Enable early PWM (in core, or in bl driver) so the config_v2 is
> > not calling SW reset on the PWM. (but this solutions seems _really_
> > bad to me)
> >
> > 3. Perform defer probe of pwm backlight driver (pwm_bl.c) until the
> > pwm is fully configured (it might be a bit tricky).
> >
> >
> > Best regards,
> > ?ukasz Majewski
> >
> >> > >
> >> > > If it is meant only for that, then the polarity should be
> >> > > removed from it.
> >> > >
> >> > > However after very quick testing, at least on my setup, it
> >> > > turns out that removing this lines causes polarity to _not_
> >> > > being set (and the polarity is not inverted).
> >> > >
> >> > > I will investigate this further on my setup and hopefully sent
> >> > > proper patch.
> >> > >
> >> > >> The set_polarity callback should get called in case a
> >> > >> different polarity is requested.
> >> > >
> >> > > On my setup the pwm2 is set from DT and pwm_backlight_probe()
> >> > > calls pwm_apply_args(), so everything should work. However, as
> >> > > I mentioned above there still is some problem with inversion
> >> > > setting.
> >> > >
> >> > >>
> >> > >>
> >> > >> > writel(cr, imx->mmio_base + MX3_PWMCR);
> >> > >> >
> >> > >> > return 0;
> >> > >> > @@ -240,27 +244,62 @@ static void imx_pwm_disable(struct
> >> > >> > pwm_chip *chip, struct pwm_device *pwm)
> >> > >> > clk_disable_unprepare(imx->clk_per);
> >> > >> > }
> >> > >> >
> >> > >> > -static struct pwm_ops imx_pwm_ops = {
> >> > >> > +static int imx_pwm_set_polarity(struct pwm_chip *chip,
> >> > >> > struct pwm_device *pwm,
> >> > >> > + enum pwm_polarity polarity)
> >> > >> > +{
> >> > >> > + struct imx_chip *imx = to_imx_chip(chip);
> >> > >> > + u32 val;
> >> > >> > +
> >> > >> > + if (polarity == pwm->args.polarity)
> >> > >> > + return 0;
> >> > >>
> >> > >> I don't think that this is right. Today, pwm_apply_args (in
> >> > >> include/linux/pwm.h) copies the polarity from args to
> >> > >> state.polarity, which is then passed as polarity argument to
> >> > >> this function. So this will always return 0 afaict.
> >> > >
> >> > > Yes, I've overlooked it (that the state is copied).
> >> > >
> >> > > It can be dropped.
> >> >
> >> > Did you do the above test with that line dropped?
> >>
> >> Yes. The above code has been also removed.
> >>
> >> Best regards,
> >> ?ukasz Majewski
> >>
> >> >
> >> > >
> >> > >>
> >> > >> I would just drop that.
> >> > >>
> >> > >> There is probably one little problem in the current state of
> >> > >> affairs: If the bootloader makes use of a PWM channel with
> >> > >> inverted state, then the kernel would not know about that and
> >> > >> currently assume a wrong initial state... I guess at one
> >> > >> point in time we should implement the state retrieval
> >> > >> callback and move to the new atomic PWM API, which would mean
> >> > >> to implement apply callback.
> >> > >
> >> > > Are there any patches on the horizon?
> >> > >
> >> >
> >> > Not that I know of...
> >> >
> >> > --
> >> > Stefan
> >> >
> >> > >>
> >> > >> --
> >> > >> Stefan
> >> > >>
> >> > >>
> >> > >> > +
> >> > >> > + val = readl(imx->mmio_base + MX3_PWMCR);
> >> > >> > +
> >> > >> > + if (polarity == PWM_POLARITY_INVERSED)
> >> > >> > + val |= MX3_PWMCR_POUTC;
> >> > >> > + else
> >> > >> > + val &= ~MX3_PWMCR_POUTC;
> >> > >> > +
> >> > >> > + writel(val, imx->mmio_base + MX3_PWMCR);
> >> > >> > +
> >> > >> > + dev_dbg(imx->chip.dev, "%s: polarity set to %s\n",
> >> > >> > __func__,
> >> > >> > + polarity == PWM_POLARITY_INVERSED ?
> >> > >> > "inverted" : "normal"); +
> >> > >> > + return 0;
> >> > >> > +}
> >> > >> > +
> >> > >> > +static struct pwm_ops imx_pwm_ops_v1 = {
> >> > >> > .enable = imx_pwm_enable,
> >> > >> > .disable = imx_pwm_disable,
> >> > >> > .config = imx_pwm_config,
> >> > >> > .owner = THIS_MODULE,
> >> > >> > };
> >> > >> >
> >> > >> > +static struct pwm_ops imx_pwm_ops_v2 = {
> >> > >> > + .enable = imx_pwm_enable,
> >> > >> > + .disable = imx_pwm_disable,
> >> > >> > + .set_polarity = imx_pwm_set_polarity,
> >> > >> > + .config = imx_pwm_config,
> >> > >> > + .owner = THIS_MODULE,
> >> > >> > +};
> >> > >> > +
> >> > >> > struct imx_pwm_data {
> >> > >> > int (*config)(struct pwm_chip *chip,
> >> > >> > struct pwm_device *pwm, int duty_ns, int
> >> > >> > period_ns); void (*set_enable)(struct pwm_chip *chip, bool
> >> > >> > enable);
> >> > >> > + struct pwm_ops *pwm_ops;
> >> > >> > };
> >> > >> >
> >> > >> > static struct imx_pwm_data imx_pwm_data_v1 = {
> >> > >> > .config = imx_pwm_config_v1,
> >> > >> > .set_enable = imx_pwm_set_enable_v1,
> >> > >> > + .pwm_ops = &imx_pwm_ops_v1,
> >> > >> > };
> >> > >> >
> >> > >> > static struct imx_pwm_data imx_pwm_data_v2 = {
> >> > >> > .config = imx_pwm_config_v2,
> >> > >> > .set_enable = imx_pwm_set_enable_v2,
> >> > >> > + .pwm_ops = &imx_pwm_ops_v2,
> >> > >> > };
> >> > >> >
> >> > >> > static const struct of_device_id imx_pwm_dt_ids[] = {
> >> > >> > @@ -282,6 +321,8 @@ static int imx_pwm_probe(struct
> >> > >> > platform_device *pdev) if (!of_id)
> >> > >> > return -ENODEV;
> >> > >> >
> >> > >> > + data = of_id->data;
> >> > >> > +
> >> > >> > imx = devm_kzalloc(&pdev->dev, sizeof(*imx),
> >> > >> > GFP_KERNEL); if (imx == NULL)
> >> > >> > return -ENOMEM;
> >> > >> > @@ -300,18 +341,22 @@ static int imx_pwm_probe(struct
> >> > >> > platform_device *pdev) return PTR_ERR(imx->clk_ipg);
> >> > >> > }
> >> > >> >
> >> > >> > - imx->chip.ops = &imx_pwm_ops;
> >> > >> > + imx->chip.ops = data->pwm_ops;
> >> > >> > imx->chip.dev = &pdev->dev;
> >> > >> > imx->chip.base = -1;
> >> > >> > imx->chip.npwm = 1;
> >> > >> > imx->chip.can_sleep = true;
> >> > >> > + if (data->pwm_ops->set_polarity) {
> >> > >> > + dev_dbg(&pdev->dev, "PWM supports output
> >> > >> > inversion\n");
> >> > >> > + imx->chip.of_xlate =
> >> > >> > of_pwm_xlate_with_flags;
> >> > >> > + imx->chip.of_pwm_n_cells = 3;
> >> > >> > + }
> >> > >> >
> >> > >> > r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >> > >> > imx->mmio_base = devm_ioremap_resource(&pdev->dev,
> >> > >> > r); if (IS_ERR(imx->mmio_base))
> >> > >> > return PTR_ERR(imx->mmio_base);
> >> > >> >
> >> > >> > - data = of_id->data;
> >> > >> > imx->config = data->config;
> >> > >> > imx->set_enable = data->set_enable;
> >> > >>
> >> > >
> >> > > Best regards,
> >> > >
> >> > > ?ukasz Majewski
> >>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161021/7c7c9f4d/attachment-0001.sig>
^ 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