* [PATCH 3/3] arm: dts: mt2701: Add reset-cells
From: Matthias Brugger @ 2017-12-14 11:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171201120708.30129-3-matthias.bgg@gmail.com>
On 12/01/2017 01:07 PM, Matthias Brugger wrote:
> The hifsys and ethsys needs the definition of the reset-cells
> property. Fix this.
>
> Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
> arch/arm/boot/dts/mt2701.dtsi | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
> index 965ddfbc9953..05557fce0f1d 100644
> --- a/arch/arm/boot/dts/mt2701.dtsi
> +++ b/arch/arm/boot/dts/mt2701.dtsi
> @@ -604,6 +604,7 @@
> compatible = "mediatek,mt2701-hifsys", "syscon";
> reg = <0 0x1a000000 0 0x1000>;
> #clock-cells = <1>;
> + #reset-cells = <1>;
> };
>
> usb0: usb at 1a1c0000 {
> @@ -688,6 +689,7 @@
> compatible = "mediatek,mt2701-ethsys", "syscon";
> reg = <0 0x1b000000 0 0x1000>;
> #clock-cells = <1>;
> + #reset-cells = <1>;
> };
>
> eth: ethernet at 1b100000 {
>
2 and 3 pushed to v4.15-next/dts32
Thanks!
^ permalink raw reply
* [PATCH v2 3/3] arm: dts: mt7623: fix card detection issue on bananapi-r2
From: Matthias Brugger @ 2017-12-14 11:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <e71b755467ce9a1f8bf78e2b6cd2e1b63e8338cd.1512628593.git.sean.wang@mediatek.com>
On 12/07/2017 07:43 AM, sean.wang at mediatek.com wrote:
> From: Sean Wang <sean.wang@mediatek.com>
>
> Fix that bananapi-r2 booting from SD-card would fail since incorrect
> polarity is applied to the previous setup with GPIO_ACTIVE_HIGH.
>
> Cc: stable at vger.kernel.org
> Fixes: 0eed8d097612 ("arm: dts: mt7623: Add SD-card and EMMC to bananapi-r2")
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> Tested-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---
> arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
> index 688a863..7bf5aa2 100644
> --- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
> +++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
> @@ -204,7 +204,7 @@
> bus-width = <4>;
> max-frequency = <50000000>;
> cap-sd-highspeed;
> - cd-gpios = <&pio 261 0>;
> + cd-gpios = <&pio 261 GPIO_ACTIVE_LOW>;
> vmmc-supply = <&mt6323_vmch_reg>;
> vqmmc-supply = <&mt6323_vio18_reg>;
> };
>
2 and 3 pushed to v4.15-next/dts32
Thanks!
^ permalink raw reply
* [PATCH 1/2] thermal: mtk: Cleanup unused defines
From: Matthias Brugger @ 2017-12-14 11:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171201104321.8410-1-matthias.bgg@gmail.com>
On 12/01/2017 11:43 AM, Matthias Brugger wrote:
> The mtk_thermal has some defiens which are never used within the driver.
> This patch delets them.
>
> Signed-off-by: Matthias Brugger <mbrugger@suse.com>
> ---
> drivers/thermal/mtk_thermal.c | 9 +--------
> 1 file changed, 1 insertion(+), 8 deletions(-)
>
> diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
> index 1e61c09153c9..c75661a3801a 100644
> --- a/drivers/thermal/mtk_thermal.c
> +++ b/drivers/thermal/mtk_thermal.c
> @@ -32,15 +32,10 @@
> #include <linux/types.h>
>
> /* AUXADC Registers */
> -#define AUXADC_CON0_V 0x000
> -#define AUXADC_CON1_V 0x004
> #define AUXADC_CON1_SET_V 0x008
> #define AUXADC_CON1_CLR_V 0x00c
> #define AUXADC_CON2_V 0x010
> #define AUXADC_DATA(channel) (0x14 + (channel) * 4)
> -#define AUXADC_MISC_V 0x094
> -
> -#define AUXADC_CON1_CHANNEL(x) BIT(x)
>
> #define APMIXED_SYS_TS_CON1 0x604
>
> @@ -158,8 +153,6 @@
> /* The number of sensing points per bank */
> #define MT2712_NUM_SENSORS_PER_ZONE 4
>
> -#define THERMAL_NAME "mtk-thermal"
> -
> struct mtk_thermal;
>
> struct thermal_bank_cfg {
> @@ -765,7 +758,7 @@ static struct platform_driver mtk_thermal_driver = {
> .probe = mtk_thermal_probe,
> .remove = mtk_thermal_remove,
> .driver = {
> - .name = THERMAL_NAME,
> + .name = "mtk-thermal",
> .of_match_table = mtk_thermal_of_match,
> },
> };
>
Kind ping.
^ permalink raw reply
* [PATCH v3 09/11] thermal: armada: Wait sensors validity before exiting the init callback
From: Gregory CLEMENT @ 2017-12-14 11:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171214103011.24713-10-miquel.raynal@free-electrons.com>
Hi Miquel,
On jeu., d?c. 14 2017, Miquel Raynal <miquel.raynal@free-electrons.com> wrote:
> The thermal core will check for sensors validity right after the
> initialization callback has returned. As the initialization routine make
> a reset, the sensors are not ready immediately and the core spawns an
> error in the dmesg. Avoid this annoying situation by polling on the
> validity bit before exiting from these routines. This also avoid the use
> of blind sleeps.
You only modified the armada 380 and ap806 init function. Does it means
that this feature is not supported on the other variant?
Gregory
>
> Suggested-by: David Sniatkiwicz <davidsn@marvell.com>
> Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
> ---
> drivers/thermal/armada_thermal.c | 23 ++++++++++++++++++++---
> 1 file changed, 20 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
> index be141ca53e83..1c4122f7377c 100644
> --- a/drivers/thermal/armada_thermal.c
> +++ b/drivers/thermal/armada_thermal.c
> @@ -23,6 +23,7 @@
> #include <linux/platform_device.h>
> #include <linux/of_device.h>
> #include <linux/thermal.h>
> +#include <linux/iopoll.h>
>
> /* Thermal Manager Control and Status Register */
> #define PMU_TDC0_SW_RST_MASK (0x1 << 1)
> @@ -59,6 +60,9 @@
> #define CONTROL1_EXT_TSEN_SW_RESET BIT(7)
> #define CONTROL1_EXT_TSEN_HW_RESETn BIT(8)
>
> +#define STATUS_POLL_PERIOD_US 1000
> +#define STATUS_POLL_TIMEOUT_US 100000
> +
> struct armada_thermal_data;
>
> /* Marvell EBU Thermal Sensor Dev Structure */
> @@ -154,6 +158,16 @@ static void armada375_init_sensor(struct platform_device *pdev,
> msleep(50);
> }
>
> +static void armada_wait_sensor_validity(struct armada_thermal_priv *priv)
> +{
> + u32 reg;
> +
> + readl_relaxed_poll_timeout(priv->status, reg,
> + reg & priv->data->is_valid_bit,
> + STATUS_POLL_PERIOD_US,
> + STATUS_POLL_TIMEOUT_US);
> +}
> +
> static void armada380_init_sensor(struct platform_device *pdev,
> struct armada_thermal_priv *priv)
> {
> @@ -163,7 +177,6 @@ static void armada380_init_sensor(struct platform_device *pdev,
> reg |= CONTROL1_EXT_TSEN_HW_RESETn;
> reg &= ~CONTROL1_EXT_TSEN_SW_RESET;
> writel(reg, priv->control1);
> - msleep(10);
>
> /* Set Tsen Tc Trim to correct default value (errata #132698) */
> if (priv->control0) {
> @@ -171,8 +184,10 @@ static void armada380_init_sensor(struct platform_device *pdev,
> reg &= ~CONTROL0_TSEN_TC_TRIM_MASK;
> reg |= CONTROL0_TSEN_TC_TRIM_VAL;
> writel(reg, priv->control0);
> - msleep(10);
> }
> +
> + /* Wait the sensors to be valid or the core will warn the user */
> + armada_wait_sensor_validity(priv);
> }
>
> static void armada_ap806_init_sensor(struct platform_device *pdev,
> @@ -190,7 +205,9 @@ static void armada_ap806_init_sensor(struct platform_device *pdev,
> reg &= ~CONTROL0_TSEN_RESET;
> reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE;
> writel(reg, priv->control0);
> - msleep(10);
> +
> + /* Wait the sensors to be valid or the core will warn the user */
> + armada_wait_sensor_validity(priv);
> }
>
> static bool armada_is_valid(struct armada_thermal_priv *priv)
> --
> 2.11.0
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH 02/10] arm64: limit PA size to supported range
From: Suzuki K Poulose @ 2017-12-14 11:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513184845-8711-3-git-send-email-kristina.martsenko@arm.com>
On 13/12/17 17:07, Kristina Martsenko wrote:
> We currently copy the physical address size from
> ID_AA64MMFR0_EL1.PARange directly into TCR.(I)PS. This will not work for
> 4k and 16k granule kernels on systems that support 52-bit physical
> addresses, since 52-bit addresses are only permitted with the 64k
> granule.
>
> To fix this, fall back to 48 bits when configuring the PA size when the
> kernel does not support 52-bit PAs. When it does, fall back to 52, to
> avoid similar problems in the future if the PA size is ever increased
> above 52.
>
> Signed-off-by: Kristina Martsenko <kristina.martsenko@arm.com>
> ---
> arch/arm64/include/asm/assembler.h | 13 +++++++++++++
> arch/arm64/include/asm/sysreg.h | 8 ++++++++
> arch/arm64/kvm/hyp-init.S | 6 ++----
> arch/arm64/kvm/hyp/s2-setup.c | 2 ++
> arch/arm64/mm/proc.S | 6 ++----
> 5 files changed, 27 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
> index aef72d886677..6cddf12a0250 100644
> --- a/arch/arm64/include/asm/assembler.h
> +++ b/arch/arm64/include/asm/assembler.h
> @@ -351,6 +351,19 @@ alternative_endif
> .endm
>
> /*
> + * tcr_set_pa_size - set TCR.(I)PS to the highest supported
> + * ID_AA64MMFR0_EL1.PARange value
> + */
> + .macro tcr_set_pa_size, tcr, pos, tmp0, tmp1
> + mrs \tmp0, ID_AA64MMFR0_EL1
> + ubfx \tmp0, \tmp0, #ID_AA64MMFR0_PARANGE_SHIFT, #3
> + mov \tmp1, #ID_AA64MMFR0_PARANGE_MAX
> + cmp \tmp0, \tmp1
> + csel \tmp0, \tmp1, \tmp0, hi
> + bfi \tcr, \tmp0, \pos, #3
> + .endm
> +
> +/*
> * Macro to perform a data cache maintenance for the interval
> * [kaddr, kaddr + size)
> *
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index 08cc88574659..ec144f480b39 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -471,6 +471,14 @@
> #define ID_AA64MMFR0_TGRAN64_SUPPORTED 0x0
> #define ID_AA64MMFR0_TGRAN16_NI 0x0
> #define ID_AA64MMFR0_TGRAN16_SUPPORTED 0x1
> +#define ID_AA64MMFR0_PARANGE_48 0x5
> +#define ID_AA64MMFR0_PARANGE_52 0x6
> +
> +#ifdef CONFIG_ARM64_PA_BITS_52
> +#define ID_AA64MMFR0_PARANGE_MAX ID_AA64MMFR0_PARANGE_52
> +#else
> +#define ID_AA64MMFR0_PARANGE_MAX ID_AA64MMFR0_PARANGE_48
> +#endif
>
> /* id_aa64mmfr1 */
> #define ID_AA64MMFR1_PAN_SHIFT 20
> diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
> index 3f9615582377..f731a48bd9f1 100644
> --- a/arch/arm64/kvm/hyp-init.S
> +++ b/arch/arm64/kvm/hyp-init.S
> @@ -90,11 +90,9 @@ __do_hyp_init:
> bfi x4, x5, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH
> #endif
> /*
> - * Read the PARange bits from ID_AA64MMFR0_EL1 and set the PS bits in
> - * TCR_EL2.
> + * Set the PS bits in TCR_EL2.
> */
> - mrs x5, ID_AA64MMFR0_EL1
> - bfi x4, x5, #16, #3
> + tcr_set_pa_size x4, #16, x5, x6
>
> msr tcr_el2, x4
>
> diff --git a/arch/arm64/kvm/hyp/s2-setup.c b/arch/arm64/kvm/hyp/s2-setup.c
> index a81f5e10fc8c..603e1ee83e89 100644
> --- a/arch/arm64/kvm/hyp/s2-setup.c
> +++ b/arch/arm64/kvm/hyp/s2-setup.c
> @@ -32,6 +32,8 @@ u32 __hyp_text __init_stage2_translation(void)
> * PS is only 3. Fortunately, bit 19 is RES0 in VTCR_EL2...
> */
> parange = read_sysreg(id_aa64mmfr0_el1) & 7;
> + if (parange > ID_AA64MMFR0_PARANGE_MAX)
> + parange = ID_AA64MMFR0_PARANGE_MAX;
> val |= parange << 16;
>
> /* Compute the actual PARange... */
> diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
> index 95233dfc4c39..c10c6c180961 100644
> --- a/arch/arm64/mm/proc.S
> +++ b/arch/arm64/mm/proc.S
> @@ -228,11 +228,9 @@ ENTRY(__cpu_setup)
> tcr_set_idmap_t0sz x10, x9
>
> /*
> - * Read the PARange bits from ID_AA64MMFR0_EL1 and set the IPS bits in
> - * TCR_EL1.
> + * Set the IPS bits in TCR_EL1.
> */
> - mrs x9, ID_AA64MMFR0_EL1
> - bfi x10, x9, #32, #3
> + tcr_set_pa_size x10, #32, x5, x6
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
^ permalink raw reply
* [PATCH 1/2] thermal: mtk: Cleanup unused defines
From: Daniel Lezcano @ 2017-12-14 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171201104321.8410-1-matthias.bgg@gmail.com>
On 01/12/2017 11:43, Matthias Brugger wrote:
> The mtk_thermal has some defiens which are never used within the driver.
> This patch delets them.
>
> Signed-off-by: Matthias Brugger <mbrugger@suse.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
--
<http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
^ permalink raw reply
* [PATCH v3 09/11] thermal: armada: Wait sensors validity before exiting the init callback
From: Miquel RAYNAL @ 2017-12-14 11:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87ind9o8o0.fsf@free-electrons.com>
On Thu, 14 Dec 2017 12:23:11 +0100
Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:
> Hi Miquel,
>
> On jeu., d?c. 14 2017, Miquel Raynal
> <miquel.raynal@free-electrons.com> wrote:
>
> > The thermal core will check for sensors validity right after the
> > initialization callback has returned. As the initialization routine
> > make a reset, the sensors are not ready immediately and the core
> > spawns an error in the dmesg. Avoid this annoying situation by
> > polling on the validity bit before exiting from these routines.
> > This also avoid the use of blind sleeps.
>
> You only modified the armada 380 and ap806 init function. Does it
> means that this feature is not supported on the other variant?
I can't tell for other boards, It does not seem they actually need it
so I did not hacked their init callback. Should I? IMOH, if there is
not problem, there is no fix to add neither.
Miqu?l
^ permalink raw reply
* [PATCH v3 07/11] thermal: armada: Update Kconfig and module description
From: Gregory CLEMENT @ 2017-12-14 11:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171214121706.529f9652@xps13>
Hi Miquel,
On jeu., d?c. 14 2017, Miquel RAYNAL <miquel.raynal@free-electrons.com> wrote:
> Hi Gregory,
>
> On Thu, 14 Dec 2017 12:13:51 +0100
> Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:
>
>> Hi Miquel,
>>
>> On jeu., d?c. 14 2017, Miquel Raynal
>> <miquel.raynal@free-electrons.com> wrote:
>>
>> > Update Armada thermal driver Kconfig entry as well as the driver's
>> > MODULE_DESCRIPTION content, now that 64-bit SoCs are also supported,
>> > eg. Armada 7K and Armada 8K.
>> >
>> > Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
>> > ---
>> > drivers/thermal/Kconfig | 4 ++--
>> > drivers/thermal/armada_thermal.c | 2 +-
>> > 2 files changed, 3 insertions(+), 3 deletions(-)
>> >
>> > diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
>> > index 315ae2926e20..44cad046f272 100644
>> > --- a/drivers/thermal/Kconfig
>> > +++ b/drivers/thermal/Kconfig
>> > @@ -301,13 +301,13 @@ config DB8500_THERMAL
>> > thermal zone if trip points reached.
>> >
>> > config ARMADA_THERMAL
>> > - tristate "Armada 370/XP thermal management"
>> > + tristate "Armada 370/XP/7K/8K thermal management"
>> if you want to be exhaustive you should also add Armada 375 and 38x.
>
> That is right, both are missing from the description, but wouldn't it
> be better to just state "Armada SoCs" instead of patching that file
> everythime a new SoC reuses this IP?
Unfortunately Armada SoCs is more that just these SoC!
Have a look on Documentation/arm/Marvell/README to see how the Marvell
marketing guys had been creative :)
Some kirkwood are called Armada 300 and Armada 310.
The Dove is also called Armada 510.
Some PXA are called Armada too such as Armada 168 or Armada 610.
And finally the Berlin also use Aramda as code name: Armada 1000 or
Aramda 1500
Gregory
>
> Thanks,
> Miqu?l
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH v3 06/11] thermal: armada: Add support for Armada CP110
From: Miquel RAYNAL @ 2017-12-14 11:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87tvwto96y.fsf@free-electrons.com>
On Thu, 14 Dec 2017 12:11:49 +0100
Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:
> Hi Miquel,
>
> On jeu., d?c. 14 2017, Miquel Raynal
> <miquel.raynal@free-electrons.com> wrote:
>
> > From: Baruch Siach <baruch@tkos.co.il>
> >
> > The CP110 component is integrated in the Armada 8k and 7k lines of
> > processors.
> >
> > Signed-off-by: Baruch Siach <baruch@tkos.co.il>
> > [<miquel.raynal@free-electrons.com>: renamed the register
> > pointers]
>
> Actually you did more thant this see below
>
>
> > Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
> > ---
> > drivers/thermal/armada_thermal.c | 30
> > ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6
> > deletions(-)
> >
> > diff --git a/drivers/thermal/armada_thermal.c
> > b/drivers/thermal/armada_thermal.c index 279d01937bb8..f5c911524656
> > 100644 --- a/drivers/thermal/armada_thermal.c
> > +++ b/drivers/thermal/armada_thermal.c
> > @@ -37,7 +37,6 @@
> > #define A375_UNIT_CONTROL_MASK 0x7
> > #define A375_READOUT_INVERT BIT(15)
> > #define A375_HW_RESETn BIT(8)
> > -#define A380_HW_RESET BIT(8)
> >
> > /* Legacy bindings */
> > #define LEGACY_CONTROL_MEM_LEN 0x4
> > @@ -52,6 +51,10 @@
> > #define CONTROL0_TSEN_RESET BIT(1)
> > #define CONTROL0_TSEN_ENABLE BIT(2)
> >
> > +/* EXT_TSEN refers to the external temperature sensors, out of the
> > AP */ +#define CONTROL1_EXT_TSEN_SW_RESET BIT(7)
> > +#define CONTROL1_EXT_TSEN_HW_RESETn BIT(8)
> You added or rename these values
>
> > +
> > struct armada_thermal_data;
> >
> > /* Marvell EBU Thermal Sensor Dev Structure */
> > @@ -153,11 +156,10 @@ static void armada380_init_sensor(struct
> > platform_device *pdev, u32 reg = readl_relaxed(priv->control1);
> >
> > /* Reset hardware once */
> > - if (!(reg & A380_HW_RESET)) {
> > - reg |= A380_HW_RESET;
> > - writel(reg, priv->control1);
> > - msleep(10);
> > - }
> > + reg |= CONTROL1_EXT_TSEN_HW_RESETn;
> > + reg &= ~CONTROL1_EXT_TSEN_SW_RESET;
> > + writel(reg, priv->control1);
>
> And here you modified the behavior of this function.
> Did you checked that it is valid for Armada 38x?
There is nothing about it the documentation and anyway this register
can be accessed later, so writing it is harmless ayway.
>
> Given the comment we had, I thought we should not do anything if
> CONTROL1_EXT_TSEN_HW_RESETn was not set.
That is the opposite, if it is not set (ie. reset is active), you have
to set it (reset is then disabled).
>
> By the way, if the new sequence is valid, this comment should be
> removed or at least updated.
That's right, I will in v4.
Thanks for reviewing,
Miqu?l
^ permalink raw reply
* [PATCH v3 07/11] thermal: armada: Update Kconfig and module description
From: Miquel RAYNAL @ 2017-12-14 11:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87efnxo8cf.fsf@free-electrons.com>
Hi Gregory,
On Thu, 14 Dec 2017 12:30:08 +0100
Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:
> Hi Miquel,
>
> On jeu., d?c. 14 2017, Miquel RAYNAL
> <miquel.raynal@free-electrons.com> wrote:
>
> > Hi Gregory,
> >
> > On Thu, 14 Dec 2017 12:13:51 +0100
> > Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:
> >
> >> Hi Miquel,
> >>
> >> On jeu., d?c. 14 2017, Miquel Raynal
> >> <miquel.raynal@free-electrons.com> wrote:
> >>
> >> > Update Armada thermal driver Kconfig entry as well as the
> >> > driver's MODULE_DESCRIPTION content, now that 64-bit SoCs are
> >> > also supported, eg. Armada 7K and Armada 8K.
> >> >
> >> > Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
> >> > ---
> >> > drivers/thermal/Kconfig | 4 ++--
> >> > drivers/thermal/armada_thermal.c | 2 +-
> >> > 2 files changed, 3 insertions(+), 3 deletions(-)
> >> >
> >> > diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> >> > index 315ae2926e20..44cad046f272 100644
> >> > --- a/drivers/thermal/Kconfig
> >> > +++ b/drivers/thermal/Kconfig
> >> > @@ -301,13 +301,13 @@ config DB8500_THERMAL
> >> > thermal zone if trip points reached.
> >> >
> >> > config ARMADA_THERMAL
> >> > - tristate "Armada 370/XP thermal management"
> >> > + tristate "Armada 370/XP/7K/8K thermal management"
> >> if you want to be exhaustive you should also add Armada 375 and
> >> 38x.
> >
> > That is right, both are missing from the description, but wouldn't
> > it be better to just state "Armada SoCs" instead of patching that
> > file everythime a new SoC reuses this IP?
>
> Unfortunately Armada SoCs is more that just these SoC!
>
> Have a look on Documentation/arm/Marvell/README to see how the Marvell
> marketing guys had been creative :)
>
> Some kirkwood are called Armada 300 and Armada 310.
> The Dove is also called Armada 510.
> Some PXA are called Armada too such as Armada 168 or Armada 610.
> And finally the Berlin also use Aramda as code name: Armada 1000 or
> Aramda 1500
Ehr...
Ok, I'll stick to "Armada 37x/38x/XP/7K/8K SoCs".
Miqu?l
^ permalink raw reply
* [PATCH v3 06/11] thermal: armada: Add support for Armada CP110
From: Gregory CLEMENT @ 2017-12-14 11:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171214123301.1729df4f@xps13>
Hi Miquel,
On jeu., d?c. 14 2017, Miquel RAYNAL <miquel.raynal@free-electrons.com> wrote:
> On Thu, 14 Dec 2017 12:11:49 +0100
> Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:
>
>> Hi Miquel,
>>
>> On jeu., d?c. 14 2017, Miquel Raynal
>> <miquel.raynal@free-electrons.com> wrote:
>>
>> > From: Baruch Siach <baruch@tkos.co.il>
>> >
>> > The CP110 component is integrated in the Armada 8k and 7k lines of
>> > processors.
>> >
>> > Signed-off-by: Baruch Siach <baruch@tkos.co.il>
>> > [<miquel.raynal@free-electrons.com>: renamed the register
>> > pointers]
>>
>> Actually you did more thant this see below
>>
>>
>> > Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
>> > ---
>> > drivers/thermal/armada_thermal.c | 30
>> > ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6
>> > deletions(-)
>> >
>> > diff --git a/drivers/thermal/armada_thermal.c
>> > b/drivers/thermal/armada_thermal.c index 279d01937bb8..f5c911524656
>> > 100644 --- a/drivers/thermal/armada_thermal.c
>> > +++ b/drivers/thermal/armada_thermal.c
>> > @@ -37,7 +37,6 @@
>> > #define A375_UNIT_CONTROL_MASK 0x7
>> > #define A375_READOUT_INVERT BIT(15)
>> > #define A375_HW_RESETn BIT(8)
>> > -#define A380_HW_RESET BIT(8)
>> >
>> > /* Legacy bindings */
>> > #define LEGACY_CONTROL_MEM_LEN 0x4
>> > @@ -52,6 +51,10 @@
>> > #define CONTROL0_TSEN_RESET BIT(1)
>> > #define CONTROL0_TSEN_ENABLE BIT(2)
>> >
>> > +/* EXT_TSEN refers to the external temperature sensors, out of the
>> > AP */ +#define CONTROL1_EXT_TSEN_SW_RESET BIT(7)
>> > +#define CONTROL1_EXT_TSEN_HW_RESETn BIT(8)
>> You added or rename these values
>>
>> > +
>> > struct armada_thermal_data;
>> >
>> > /* Marvell EBU Thermal Sensor Dev Structure */
>> > @@ -153,11 +156,10 @@ static void armada380_init_sensor(struct
>> > platform_device *pdev, u32 reg = readl_relaxed(priv->control1);
>> >
>> > /* Reset hardware once */
>> > - if (!(reg & A380_HW_RESET)) {
>> > - reg |= A380_HW_RESET;
>> > - writel(reg, priv->control1);
>> > - msleep(10);
>> > - }
>> > + reg |= CONTROL1_EXT_TSEN_HW_RESETn;
>> > + reg &= ~CONTROL1_EXT_TSEN_SW_RESET;
>> > + writel(reg, priv->control1);
>>
>> And here you modified the behavior of this function.
>> Did you checked that it is valid for Armada 38x?
>
> There is nothing about it the documentation and anyway this register
> can be accessed later, so writing it is harmless ayway.
>
>>
>> Given the comment we had, I thought we should not do anything if
>> CONTROL1_EXT_TSEN_HW_RESETn was not set.
>
> That is the opposite, if it is not set (ie. reset is active), you have
> to set it (reset is then disabled).
Actually I was concerned by the "once" for me it means "only one time",
but maybe it just meant it was useless to reset it again but not
harmful.
Gregory
>
>>
>> By the way, if the new sequence is valid, this comment should be
>> removed or at least updated.
>
> That's right, I will in v4.
>
> Thanks for reviewing,
> Miqu?l
>
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH v11 1/3] ACPI/IORT: Add msi address regions reservation helper
From: Lorenzo Pieralisi @ 2017-12-14 11:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213115830.61872-2-shameerali.kolothum.thodi@huawei.com>
On Wed, Dec 13, 2017 at 11:58:28AM +0000, Shameer Kolothum wrote:
> On some platforms msi parent address regions have to be excluded from
> normal IOVA allocation in that they are detected and decoded in a HW
> specific way by system components and so they cannot be considered normal
> IOVA address space.
>
> Add a helper function that retrieves ITS address regions - the msi
> parent - through IORT device <-> ITS mappings and reserves it so that
> these regions will not be translated by IOMMU and will be excluded from
> IOVA allocations. The function checks for the smmu model number and
> only applies the msi reservation if the platform requires it.
>
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> ---
> drivers/acpi/arm64/iort.c | 112 +++++++++++++++++++++++++++++++++++++--
> drivers/irqchip/irq-gic-v3-its.c | 3 +-
> include/linux/acpi_iort.h | 7 ++-
> 3 files changed, 117 insertions(+), 5 deletions(-)
You need this additional hunk to make it compile on !CONFIG_IOMMU_API:
-- >8 --
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 3e0ce652c3e8..e2f7bddf5522 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -762,25 +762,6 @@ static int __maybe_unused __get_pci_rid(struct pci_dev *pdev, u16 alias,
return 0;
}
-static __maybe_unused struct acpi_iort_node *iort_get_msi_resv_iommu(
- struct device *dev)
-{
- struct acpi_iort_node *iommu;
- struct iommu_fwspec *fwspec = dev->iommu_fwspec;
-
- iommu = iort_get_iort_node(fwspec->iommu_fwnode);
-
- if (iommu && (iommu->type == ACPI_IORT_NODE_SMMU_V3)) {
- struct acpi_iort_smmu_v3 *smmu;
-
- smmu = (struct acpi_iort_smmu_v3 *)iommu->node_data;
- if (smmu->model == ACPI_IORT_SMMU_V3_HISILICON_HI161X)
- return iommu;
- }
-
- return NULL;
-}
-
static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
struct fwnode_handle *fwnode,
const struct iommu_ops *ops)
@@ -807,6 +788,24 @@ static inline bool iort_iommu_driver_enabled(u8 type)
}
#ifdef CONFIG_IOMMU_API
+static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
+{
+ struct acpi_iort_node *iommu;
+ struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+
+ iommu = iort_get_iort_node(fwspec->iommu_fwnode);
+
+ if (iommu && (iommu->type == ACPI_IORT_NODE_SMMU_V3)) {
+ struct acpi_iort_smmu_v3 *smmu;
+
+ smmu = (struct acpi_iort_smmu_v3 *)iommu->node_data;
+ if (smmu->model == ACPI_IORT_SMMU_V3_HISILICON_HI161X)
+ return iommu;
+ }
+
+ return NULL;
+}
+
static inline const struct iommu_ops *iort_fwspec_iommu_ops(
struct iommu_fwspec *fwspec)
{
^ permalink raw reply related
* [PATCH v2 11/36] KVM: arm64: Introduce VHE-specific kvm_vcpu_run
From: Christoffer Dall @ 2017-12-14 12:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <863fc9b1-c188-a212-4c72-55cbe1cdbf14@arm.com>
On Mon, Dec 11, 2017 at 09:53:13AM +0000, Marc Zyngier wrote:
> On 07/12/17 17:06, Christoffer Dall wrote:
> > So far this is just a copy of the legacy non-VHE switch function, where
> > we only change the existing calls to has_vhe() in both the original and
> > new functions.
>
> I'm not sure I correctly parse the above. Do you want to say that you
> use has_vhe() to select the right world switch back-end? Or did you mean
> to drop some of the has_vhe() calls in the non-VHE case?
>
That's a leftover from a previous patch version. How about the
following instead?
So far this is just a copy of the legacy non-VHE switch function, but we
will start reworking these functions in separate directions to work on
VHE and non-VHE in the most optimal way in later patches.
Thanks,
-Christoffer
> >
> > Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> > ---
> >
> > Notes:
> > Changes since v1:
> > - Rename kvm_vcpu_run to kvm_vcpu_run_vhe and rename __kvm_vcpu_run to
> > __kvm_vcpu_run_nvhe
> > - Removed stray whitespace line
> >
> > arch/arm/include/asm/kvm_asm.h | 5 +++-
> > arch/arm/kvm/hyp/switch.c | 2 +-
> > arch/arm64/include/asm/kvm_asm.h | 4 ++-
> > arch/arm64/kvm/hyp/switch.c | 58 +++++++++++++++++++++++++++++++++++++++-
> > virt/kvm/arm/arm.c | 5 +++-
> > 5 files changed, 69 insertions(+), 5 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
> > index 36dd2962a42d..4ac717276543 100644
> > --- a/arch/arm/include/asm/kvm_asm.h
> > +++ b/arch/arm/include/asm/kvm_asm.h
> > @@ -70,7 +70,10 @@ extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
> >
> > extern void __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high);
> >
> > -extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
> > +/* no VHE on 32-bit :( */
> > +static inline int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) { return 0; }
> > +
> > +extern int __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu);
> >
> > extern void __init_stage2_translation(void);
> >
> > diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c
> > index c3b9799e2e13..7b2bd25e3b10 100644
> > --- a/arch/arm/kvm/hyp/switch.c
> > +++ b/arch/arm/kvm/hyp/switch.c
> > @@ -153,7 +153,7 @@ static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
> > return true;
> > }
> >
> > -int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
> > +int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
> > {
> > struct kvm_cpu_context *host_ctxt;
> > struct kvm_cpu_context *guest_ctxt;
> > diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
> > index 33e0edc6f8be..adaf1db12271 100644
> > --- a/arch/arm64/include/asm/kvm_asm.h
> > +++ b/arch/arm64/include/asm/kvm_asm.h
> > @@ -58,7 +58,9 @@ extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
> >
> > extern void __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high);
> >
> > -extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
> > +extern int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu);
> > +
> > +extern int __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu);
> >
> > extern u64 __vgic_v3_get_ich_vtr_el2(void);
> > extern u64 __vgic_v3_read_vmcr(void);
> > diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> > index 845e3bece399..8f32f8dcab65 100644
> > --- a/arch/arm64/kvm/hyp/switch.c
> > +++ b/arch/arm64/kvm/hyp/switch.c
> > @@ -342,7 +342,63 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
> > return false;
> > }
> >
> > -int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
> > +/* Switch to the guest for VHE systems running in EL2 */
> > +int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
> > +{
> > + struct kvm_cpu_context *host_ctxt;
> > + struct kvm_cpu_context *guest_ctxt;
> > + u64 exit_code;
> > +
> > + vcpu = kern_hyp_va(vcpu);
> > +
> > + host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
> > + host_ctxt->__hyp_running_vcpu = vcpu;
> > + guest_ctxt = &vcpu->arch.ctxt;
> > +
> > + __sysreg_save_host_state(host_ctxt);
> > +
> > + __activate_traps(vcpu);
> > + __activate_vm(vcpu);
> > +
> > + __vgic_restore_state(vcpu);
> > + __timer_enable_traps(vcpu);
> > +
> > + /*
> > + * We must restore the 32-bit state before the sysregs, thanks
> > + * to erratum #852523 (Cortex-A57) or #853709 (Cortex-A72).
> > + */
> > + __sysreg32_restore_state(vcpu);
> > + __sysreg_restore_guest_state(guest_ctxt);
> > + __debug_switch_to_guest(vcpu);
> > +
> > + do {
> > + /* Jump in the fire! */
> > + exit_code = __guest_enter(vcpu, host_ctxt);
> > +
> > + /* And we're baaack! */
> > + } while (fixup_guest_exit(vcpu, &exit_code));
> > +
> > + __sysreg_save_guest_state(guest_ctxt);
> > + __sysreg32_save_state(vcpu);
> > + __timer_disable_traps(vcpu);
> > + __vgic_save_state(vcpu);
> > +
> > + __deactivate_traps(vcpu);
> > + __deactivate_vm(vcpu);
> > +
> > + __sysreg_restore_host_state(host_ctxt);
> > +
> > + /*
> > + * This must come after restoring the host sysregs, since a non-VHE
> > + * system may enable SPE here and make use of the TTBRs.
> > + */
> > + __debug_switch_to_host(vcpu);
> > +
> > + return exit_code;
> > +}
> > +
> > +/* Switch to the guest for legacy non-VHE systems */
> > +int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
> > {
> > struct kvm_cpu_context *host_ctxt;
> > struct kvm_cpu_context *guest_ctxt;
> > diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
> > index 3e10343374a1..104ee524c75a 100644
> > --- a/virt/kvm/arm/arm.c
> > +++ b/virt/kvm/arm/arm.c
> > @@ -712,7 +712,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
> > trace_kvm_entry(*vcpu_pc(vcpu));
> > guest_enter_irqoff();
> >
> > - ret = kvm_call_hyp(__kvm_vcpu_run, vcpu);
> > + if (has_vhe())
> > + ret = kvm_vcpu_run_vhe(vcpu);
> > + else
> > + ret = kvm_call_hyp(__kvm_vcpu_run_nvhe, vcpu);
> >
> > vcpu->mode = OUTSIDE_GUEST_MODE;
> > vcpu->stat.exits++;
> >
>
> Otherwise looks good to me.
>
> M.
> --
> Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v2 11/36] KVM: arm64: Introduce VHE-specific kvm_vcpu_run
From: Marc Zyngier @ 2017-12-14 12:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171214121223.GS910@cbox>
On 14/12/17 12:12, Christoffer Dall wrote:
> On Mon, Dec 11, 2017 at 09:53:13AM +0000, Marc Zyngier wrote:
>> On 07/12/17 17:06, Christoffer Dall wrote:
>>> So far this is just a copy of the legacy non-VHE switch function, where
>>> we only change the existing calls to has_vhe() in both the original and
>>> new functions.
>>
>> I'm not sure I correctly parse the above. Do you want to say that you
>> use has_vhe() to select the right world switch back-end? Or did you mean
>> to drop some of the has_vhe() calls in the non-VHE case?
>>
>
> That's a leftover from a previous patch version. How about the
> following instead?
>
> So far this is just a copy of the legacy non-VHE switch function, but we
> will start reworking these functions in separate directions to work on
> VHE and non-VHE in the most optimal way in later patches.
This makes more sense.With that change:
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v11 1/3] ACPI/IORT: Add msi address regions reservation helper
From: Shameerali Kolothum Thodi @ 2017-12-14 12:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171214114759.GA27117@e107981-ln.cambridge.arm.com>
Hi Lorenzo,
> -----Original Message-----
> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
> Sent: Thursday, December 14, 2017 11:48 AM
> To: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> Cc: robin.murphy at arm.com; marc.zyngier at arm.com; will.deacon at arm.com;
> joro at 8bytes.org; John Garry <john.garry@huawei.com>; xuwei (O)
> <xuwei5@hisilicon.com>; Guohanjun (Hanjun Guo) <guohanjun@huawei.com>;
> iommu at lists.linux-foundation.org; linux-arm-kernel at lists.infradead.org; linux-
> acpi at vger.kernel.org; devicetree at vger.kernel.org; Linuxarm
> <linuxarm@huawei.com>
> Subject: Re: [PATCH v11 1/3] ACPI/IORT: Add msi address regions reservation
> helper
>
> On Wed, Dec 13, 2017 at 11:58:28AM +0000, Shameer Kolothum wrote:
> > On some platforms msi parent address regions have to be excluded from
> > normal IOVA allocation in that they are detected and decoded in a HW
> > specific way by system components and so they cannot be considered normal
> > IOVA address space.
> >
> > Add a helper function that retrieves ITS address regions - the msi
> > parent - through IORT device <-> ITS mappings and reserves it so that
> > these regions will not be translated by IOMMU and will be excluded from
> > IOVA allocations. The function checks for the smmu model number and
> > only applies the msi reservation if the platform requires it.
> >
> > Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> > ---
> > drivers/acpi/arm64/iort.c | 112
> +++++++++++++++++++++++++++++++++++++--
> > drivers/irqchip/irq-gic-v3-its.c | 3 +-
> > include/linux/acpi_iort.h | 7 ++-
> > 3 files changed, 117 insertions(+), 5 deletions(-)
>
> You need this additional hunk to make it compile on !CONFIG_IOMMU_API:
Oops..Sorry, missed that. If you are happy with the rest, I will make the below
change and sent out the v12(hopefully final).
Please let me know.
Thanks,
Shameer
>
> -- >8 --
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 3e0ce652c3e8..e2f7bddf5522 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -762,25 +762,6 @@ static int __maybe_unused __get_pci_rid(struct
> pci_dev *pdev, u16 alias,
> return 0;
> }
>
> -static __maybe_unused struct acpi_iort_node *iort_get_msi_resv_iommu(
> - struct device *dev)
> -{
> - struct acpi_iort_node *iommu;
> - struct iommu_fwspec *fwspec = dev->iommu_fwspec;
> -
> - iommu = iort_get_iort_node(fwspec->iommu_fwnode);
> -
> - if (iommu && (iommu->type == ACPI_IORT_NODE_SMMU_V3)) {
> - struct acpi_iort_smmu_v3 *smmu;
> -
> - smmu = (struct acpi_iort_smmu_v3 *)iommu->node_data;
> - if (smmu->model ==
> ACPI_IORT_SMMU_V3_HISILICON_HI161X)
> - return iommu;
> - }
> -
> - return NULL;
> -}
> -
> static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
> struct fwnode_handle *fwnode,
> const struct iommu_ops *ops)
> @@ -807,6 +788,24 @@ static inline bool iort_iommu_driver_enabled(u8 type)
> }
>
> #ifdef CONFIG_IOMMU_API
> +static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
> +{
> + struct acpi_iort_node *iommu;
> + struct iommu_fwspec *fwspec = dev->iommu_fwspec;
> +
> + iommu = iort_get_iort_node(fwspec->iommu_fwnode);
> +
> + if (iommu && (iommu->type == ACPI_IORT_NODE_SMMU_V3)) {
> + struct acpi_iort_smmu_v3 *smmu;
> +
> + smmu = (struct acpi_iort_smmu_v3 *)iommu->node_data;
> + if (smmu->model ==
> ACPI_IORT_SMMU_V3_HISILICON_HI161X)
> + return iommu;
> + }
> +
> + return NULL;
> +}
> +
> static inline const struct iommu_ops *iort_fwspec_iommu_ops(
> struct iommu_fwspec *fwspec)
> {
^ permalink raw reply
* [PATCH v2 05/19] arm64: alternatives: Add dynamic patching feature
From: Marc Zyngier @ 2017-12-14 12:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213175330.qlqay7ev7s6zra2n@armageddon.cambridge.arm.com>
On 13/12/17 17:53, Catalin Marinas wrote:
> On Mon, Dec 11, 2017 at 02:49:23PM +0000, Marc Zyngier wrote:
>> We've so far relied on a patching infrastructure that only gave us
>> a single alternative, without any way to finely control what gets
>> patched. For a single feature, this is an all or nothing thing.
>>
>> It would be interesting to have a more fine grained way of patching
>> the kernel though, where we could dynamically tune the code that gets
>> injected.
>>
>> In order to achive this, let's introduce a new form of alternative
>> that is associated with a callback. This callback gets the instruction
>> sequence number and the old instruction as a parameter, and returns
>> the new instruction. This callback is always called, as the patching
>> decision is now done at runtime (not patching is equivalent to returning
>> the same instruction).
>>
>> Patching with a callback is declared with the new ALTERNATIVE_CB
>> and alternative_cb directives:
>>
>> asm volatile(ALTERNATIVE_CB("mov %0, #0\n", callback)
>> : "r" (v));
>> or
>> alternative_cb callback
>> mov x0, #0
>> alternative_else_nop_endif
>
> Could we have a new "alternative_cb_endif" instead of
> alternative_else_no_endif? IIUC, the nops generated in the
> .altinstr_replacement section wouldn't be used, so I think it makes the
> code clearer that there is no other alternative instruction set, just an
> update in-place of the given instruction.
Yes, good call.
>
>> diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h
>> index 395befde7595..ce612e10a2c9 100644
>> --- a/arch/arm64/include/asm/alternative.h
>> +++ b/arch/arm64/include/asm/alternative.h
> [...]
>> -.macro altinstruction_entry orig_offset alt_offset feature orig_len alt_len
>> +.macro altinstruction_entry orig_offset, alt_offset, feature, orig_len, alt_len, cb = 0
>> .align ALTINSTR_ALIGN
>> .word \orig_offset - .
>> + .if \cb == 0
>> .word \alt_offset - .
>> + .else
>> + .word \cb - .
>> + .endif
>> .hword \feature
>> .byte \orig_len
>> .byte \alt_len
>> .endm
>>
>> -.macro alternative_insn insn1, insn2, cap, enable = 1
>> +.macro alternative_insn insn1, insn2, cap, enable = 1, cb = 0
>> .if \enable
>> 661: \insn1
>> 662: .pushsection .altinstructions, "a"
>> - altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f
>> + altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f, \cb
>> .popsection
>> .pushsection .altinstr_replacement, "ax"
>> 663: \insn2
>
> So here we could skip .pushsection .altinstr_replacement if cb. We could
> even pass \cb directly to altinstruction_entry instead of 663f so that
> we keep altinstruction_entry unmodified.
>
>> @@ -109,10 +119,10 @@ void apply_alternatives(void *start, size_t length);
>> /*
>> * Begin an alternative code sequence.
>> */
>> -.macro alternative_if_not cap
>> +.macro alternative_if_not cap, cb = 0
>> .set .Lasm_alt_mode, 0
>> .pushsection .altinstructions, "a"
>> - altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f
>> + altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f, \cb
>> .popsection
>> 661:
>> .endm
>> @@ -120,13 +130,17 @@ void apply_alternatives(void *start, size_t length);
>> .macro alternative_if cap
>> .set .Lasm_alt_mode, 1
>> .pushsection .altinstructions, "a"
>> - altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f
>> + altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f, 0
>> .popsection
>> .pushsection .altinstr_replacement, "ax"
>> .align 2 /* So GAS knows label 661 is suitably aligned */
>> 661:
>> .endm
>
> and here we wouldn't need this hunk for alternative_if.
All good remarks. I've reworked that and the changes are a lot more
manageable now. Thanks for the suggestion.
>
>> --- a/arch/arm64/kernel/alternative.c
>> +++ b/arch/arm64/kernel/alternative.c
>> @@ -110,12 +110,15 @@ static void __apply_alternatives(void *alt_region, bool use_linear_alias)
>> struct alt_instr *alt;
>> struct alt_region *region = alt_region;
>> __le32 *origptr, *replptr, *updptr;
>> + alternative_cb_t alt_cb;
>>
>> for (alt = region->begin; alt < region->end; alt++) {
>> u32 insn;
>> int i, nr_inst;
>>
>> - if (!cpus_have_cap(alt->cpufeature))
>> + /* Use ARM64_NCAPS as an unconditional patch */
>> + if (alt->cpufeature != ARM64_NCAPS &&
>
> Nitpick (personal preference): alt->cpufeature < ARM64_NCAPS.
>
>> + !cpus_have_cap(alt->cpufeature))
>> continue;
>>
>> BUG_ON(alt->alt_len != alt->orig_len);
>> @@ -124,11 +127,18 @@ static void __apply_alternatives(void *alt_region, bool use_linear_alias)
>>
>> origptr = ALT_ORIG_PTR(alt);
>> replptr = ALT_REPL_PTR(alt);
>> + alt_cb = ALT_REPL_PTR(alt);
>> updptr = use_linear_alias ? lm_alias(origptr) : origptr;
>> nr_inst = alt->alt_len / sizeof(insn);
>>
>> for (i = 0; i < nr_inst; i++) {
>> - insn = get_alt_insn(alt, origptr + i, replptr + i);
>> + if (alt->cpufeature == ARM64_NCAPS) {
>> + insn = le32_to_cpu(updptr[i]);
>> + insn = alt_cb(alt, i, insn);
>
> I wonder whether we'd need the origptr + i as well at some point (e.g.
> to generate some relative relocations).
The callback takes the alt_instr structure as a parameter. All we need
is to expose the ALT_ORIG_PTR macro for the callback to resolve this as
an absolute address.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v3 06/11] thermal: armada: Add support for Armada CP110
From: Miquel RAYNAL @ 2017-12-14 12:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87a7ylo803.fsf@free-electrons.com>
On Thu, 14 Dec 2017 12:37:32 +0100
Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:
> Hi Miquel,
>
> On jeu., d?c. 14 2017, Miquel RAYNAL
> <miquel.raynal@free-electrons.com> wrote:
>
> > On Thu, 14 Dec 2017 12:11:49 +0100
> > Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:
> >
> >> Hi Miquel,
> >>
> >> On jeu., d?c. 14 2017, Miquel Raynal
> >> <miquel.raynal@free-electrons.com> wrote:
> >>
> >> > From: Baruch Siach <baruch@tkos.co.il>
> >> >
> >> > The CP110 component is integrated in the Armada 8k and 7k lines
> >> > of processors.
> >> >
> >> > Signed-off-by: Baruch Siach <baruch@tkos.co.il>
> >> > [<miquel.raynal@free-electrons.com>: renamed the register
> >> > pointers]
> >>
> >> Actually you did more thant this see below
> >>
> >>
> >> > Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
> >> > ---
> >> > drivers/thermal/armada_thermal.c | 30
> >> > ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+),
> >> > 6 deletions(-)
> >> >
> >> > diff --git a/drivers/thermal/armada_thermal.c
> >> > b/drivers/thermal/armada_thermal.c index
> >> > 279d01937bb8..f5c911524656 100644 ---
> >> > a/drivers/thermal/armada_thermal.c +++
> >> > b/drivers/thermal/armada_thermal.c @@ -37,7 +37,6 @@
> >> > #define A375_UNIT_CONTROL_MASK 0x7
> >> > #define A375_READOUT_INVERT BIT(15)
> >> > #define A375_HW_RESETn BIT(8)
> >> > -#define A380_HW_RESET BIT(8)
> >> >
> >> > /* Legacy bindings */
> >> > #define LEGACY_CONTROL_MEM_LEN 0x4
> >> > @@ -52,6 +51,10 @@
> >> > #define CONTROL0_TSEN_RESET BIT(1)
> >> > #define CONTROL0_TSEN_ENABLE BIT(2)
> >> >
> >> > +/* EXT_TSEN refers to the external temperature sensors, out of
> >> > the AP */ +#define CONTROL1_EXT_TSEN_SW_RESET BIT(7)
> >> > +#define CONTROL1_EXT_TSEN_HW_RESETn BIT(8)
> >> You added or rename these values
> >>
> >> > +
> >> > struct armada_thermal_data;
> >> >
> >> > /* Marvell EBU Thermal Sensor Dev Structure */
> >> > @@ -153,11 +156,10 @@ static void armada380_init_sensor(struct
> >> > platform_device *pdev, u32 reg = readl_relaxed(priv->control1);
> >> >
> >> > /* Reset hardware once */
> >> > - if (!(reg & A380_HW_RESET)) {
> >> > - reg |= A380_HW_RESET;
> >> > - writel(reg, priv->control1);
> >> > - msleep(10);
> >> > - }
> >> > + reg |= CONTROL1_EXT_TSEN_HW_RESETn;
> >> > + reg &= ~CONTROL1_EXT_TSEN_SW_RESET;
> >> > + writel(reg, priv->control1);
> >>
> >> And here you modified the behavior of this function.
> >> Did you checked that it is valid for Armada 38x?
> >
> > There is nothing about it the documentation and anyway this register
> > can be accessed later, so writing it is harmless ayway.
> >
> >>
> >> Given the comment we had, I thought we should not do anything if
> >> CONTROL1_EXT_TSEN_HW_RESETn was not set.
> >
> > That is the opposite, if it is not set (ie. reset is active), you
> > have to set it (reset is then disabled).
>
> Actually I was concerned by the "once" for me it means "only one
> time", but maybe it just meant it was useless to reset it again but
> not harmful.
This:
reg |= CONTROL1_EXT_TSEN_HW_RESETn;
does not reset the IP, instead it cancels the reset, if one is
happening. So no, doing it unconditionally is not harmful.
Miqu?l
>
> Gregory
>
> >
> >>
> >> By the way, if the new sequence is valid, this comment should be
> >> removed or at least updated.
> >
> > That's right, I will in v4.
> >
> > Thanks for reviewing,
> > Miqu?l
> >
> >
>
--
Miquel Raynal, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH v2 14/36] KVM: arm64: Remove noop calls to timer save/restore from VHE switch
From: Christoffer Dall @ 2017-12-14 12:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <76009e9a-0518-6b0c-c1f4-9fc5ce6a1138@arm.com>
On Mon, Dec 11, 2017 at 10:02:58AM +0000, Marc Zyngier wrote:
> On 07/12/17 17:06, Christoffer Dall wrote:
> > The VHE switch function calls __timer_enable_traps and
> > __timer_disable_traps which don't do anything on VHE systems.
> > Therefore, simply remove these calls from the VHE switch function and
> > make the functions non-conditional as they are now only called from the
> > non-VHE switch path.
> >
> > Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> > ---
> > arch/arm64/kvm/hyp/switch.c | 2 --
> > virt/kvm/arm/hyp/timer-sr.c | 36 ++++++++++++++----------------------
> > 2 files changed, 14 insertions(+), 24 deletions(-)
> >
> > diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> > index e783e2371b7c..09aafa0470f7 100644
> > --- a/arch/arm64/kvm/hyp/switch.c
> > +++ b/arch/arm64/kvm/hyp/switch.c
> > @@ -358,7 +358,6 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
> > __activate_vm(vcpu->kvm);
> >
> > __vgic_restore_state(vcpu);
> > - __timer_enable_traps(vcpu);
> >
> > /*
> > * We must restore the 32-bit state before the sysregs, thanks
> > @@ -377,7 +376,6 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
> >
> > __sysreg_save_guest_state(guest_ctxt);
> > __sysreg32_save_state(vcpu);
> > - __timer_disable_traps(vcpu);
> > __vgic_save_state(vcpu);
> >
> > __deactivate_traps(vcpu);
> > diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c
> > index f24404b3c8df..752b37f9133c 100644
> > --- a/virt/kvm/arm/hyp/timer-sr.c
> > +++ b/virt/kvm/arm/hyp/timer-sr.c
> > @@ -29,32 +29,24 @@ void __hyp_text __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high)
> >
> > void __hyp_text __timer_disable_traps(struct kvm_vcpu *vcpu)
> > {
> > - /*
> > - * We don't need to do this for VHE since the host kernel runs in EL2
> > - * with HCR_EL2.TGE ==1, which makes those bits have no impact.
> > - */
> > - if (!has_vhe()) {
> > - u64 val;
> > + u64 val;
> >
> > - /* Allow physical timer/counter access for the host */
> > - val = read_sysreg(cnthctl_el2);
> > - val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
> > - write_sysreg(val, cnthctl_el2);
> > - }
> > + /* Allow physical timer/counter access for the host */
> > + val = read_sysreg(cnthctl_el2);
> > + val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
> > + write_sysreg(val, cnthctl_el2);
> > }
> >
> > void __hyp_text __timer_enable_traps(struct kvm_vcpu *vcpu)
> > {
> > - if (!has_vhe()) {
> > - u64 val;
> > + u64 val;
> >
> > - /*
> > - * Disallow physical timer access for the guest
> > - * Physical counter access is allowed
> > - */
> > - val = read_sysreg(cnthctl_el2);
> > - val &= ~CNTHCTL_EL1PCEN;
> > - val |= CNTHCTL_EL1PCTEN;
> > - write_sysreg(val, cnthctl_el2);
> > - }
> > + /*
> > + * Disallow physical timer access for the guest
> > + * Physical counter access is allowed
> > + */
> > + val = read_sysreg(cnthctl_el2);
> > + val &= ~CNTHCTL_EL1PCEN;
> > + val |= CNTHCTL_EL1PCTEN;
> > + write_sysreg(val, cnthctl_el2);
> > }
> >
>
> Since we're not testing for !VHE anymore, can you add a small comment
> saying that these two function are for the benefit of !VHE only and
> shouldn't be called on VHE?
Yes, absolutely:
diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c
index 752b37f9133c..77754a62eb0c 100644
--- a/virt/kvm/arm/hyp/timer-sr.c
+++ b/virt/kvm/arm/hyp/timer-sr.c
@@ -27,6 +27,10 @@ void __hyp_text __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high)
write_sysreg(cntvoff, cntvoff_el2);
}
+/*
+ * Should only be called on non-VHE systems.
+ * VHE systems use EL2 timers and configure EL1 timers in kvm_timer_init_vhe().
+ */
void __hyp_text __timer_disable_traps(struct kvm_vcpu *vcpu)
{
u64 val;
@@ -37,6 +41,10 @@ void __hyp_text __timer_disable_traps(struct kvm_vcpu *vcpu)
write_sysreg(val, cnthctl_el2);
}
+/*
+ * Should only be called on non-VHE systems.
+ * VHE systems use EL2 timers and configure EL1 timers in kvm_timer_init_vhe().
+ */
void __hyp_text __timer_enable_traps(struct kvm_vcpu *vcpu)
{
u64 val;
>
> Otherwise,
>
> Acked-by: Marc Zyngier <marc.zyngier@arm.com>
>
Thanks,
-Christoffer
^ permalink raw reply related
* [PATCH v11 1/3] ACPI/IORT: Add msi address regions reservation helper
From: Lorenzo Pieralisi @ 2017-12-14 12:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5FC3163CFD30C246ABAA99954A238FA838628CDD@FRAEML521-MBX.china.huawei.com>
On Thu, Dec 14, 2017 at 12:17:50PM +0000, Shameerali Kolothum Thodi wrote:
> Hi Lorenzo,
>
> > -----Original Message-----
> > From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
> > Sent: Thursday, December 14, 2017 11:48 AM
> > To: Shameerali Kolothum Thodi <shameerali.kolothum.thodi@huawei.com>
> > Cc: robin.murphy at arm.com; marc.zyngier at arm.com; will.deacon at arm.com;
> > joro at 8bytes.org; John Garry <john.garry@huawei.com>; xuwei (O)
> > <xuwei5@hisilicon.com>; Guohanjun (Hanjun Guo) <guohanjun@huawei.com>;
> > iommu at lists.linux-foundation.org; linux-arm-kernel at lists.infradead.org; linux-
> > acpi at vger.kernel.org; devicetree at vger.kernel.org; Linuxarm
> > <linuxarm@huawei.com>
> > Subject: Re: [PATCH v11 1/3] ACPI/IORT: Add msi address regions reservation
> > helper
> >
> > On Wed, Dec 13, 2017 at 11:58:28AM +0000, Shameer Kolothum wrote:
> > > On some platforms msi parent address regions have to be excluded from
> > > normal IOVA allocation in that they are detected and decoded in a HW
> > > specific way by system components and so they cannot be considered normal
> > > IOVA address space.
> > >
> > > Add a helper function that retrieves ITS address regions - the msi
> > > parent - through IORT device <-> ITS mappings and reserves it so that
> > > these regions will not be translated by IOMMU and will be excluded from
> > > IOVA allocations. The function checks for the smmu model number and
> > > only applies the msi reservation if the platform requires it.
> > >
> > > Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> > > ---
> > > drivers/acpi/arm64/iort.c | 112
> > +++++++++++++++++++++++++++++++++++++--
> > > drivers/irqchip/irq-gic-v3-its.c | 3 +-
> > > include/linux/acpi_iort.h | 7 ++-
> > > 3 files changed, 117 insertions(+), 5 deletions(-)
> >
> > You need this additional hunk to make it compile on !CONFIG_IOMMU_API:
>
> Oops..Sorry, missed that. If you are happy with the rest, I will make the below
> change and sent out the v12(hopefully final).
I am ok with it, yes.
Thanks,
Lorenzo
> Please let me know.
>
> Thanks,
> Shameer
>
> >
> > -- >8 --
> > diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> > index 3e0ce652c3e8..e2f7bddf5522 100644
> > --- a/drivers/acpi/arm64/iort.c
> > +++ b/drivers/acpi/arm64/iort.c
> > @@ -762,25 +762,6 @@ static int __maybe_unused __get_pci_rid(struct
> > pci_dev *pdev, u16 alias,
> > return 0;
> > }
> >
> > -static __maybe_unused struct acpi_iort_node *iort_get_msi_resv_iommu(
> > - struct device *dev)
> > -{
> > - struct acpi_iort_node *iommu;
> > - struct iommu_fwspec *fwspec = dev->iommu_fwspec;
> > -
> > - iommu = iort_get_iort_node(fwspec->iommu_fwnode);
> > -
> > - if (iommu && (iommu->type == ACPI_IORT_NODE_SMMU_V3)) {
> > - struct acpi_iort_smmu_v3 *smmu;
> > -
> > - smmu = (struct acpi_iort_smmu_v3 *)iommu->node_data;
> > - if (smmu->model ==
> > ACPI_IORT_SMMU_V3_HISILICON_HI161X)
> > - return iommu;
> > - }
> > -
> > - return NULL;
> > -}
> > -
> > static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
> > struct fwnode_handle *fwnode,
> > const struct iommu_ops *ops)
> > @@ -807,6 +788,24 @@ static inline bool iort_iommu_driver_enabled(u8 type)
> > }
> >
> > #ifdef CONFIG_IOMMU_API
> > +static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
> > +{
> > + struct acpi_iort_node *iommu;
> > + struct iommu_fwspec *fwspec = dev->iommu_fwspec;
> > +
> > + iommu = iort_get_iort_node(fwspec->iommu_fwnode);
> > +
> > + if (iommu && (iommu->type == ACPI_IORT_NODE_SMMU_V3)) {
> > + struct acpi_iort_smmu_v3 *smmu;
> > +
> > + smmu = (struct acpi_iort_smmu_v3 *)iommu->node_data;
> > + if (smmu->model ==
> > ACPI_IORT_SMMU_V3_HISILICON_HI161X)
> > + return iommu;
> > + }
> > +
> > + return NULL;
> > +}
> > +
> > static inline const struct iommu_ops *iort_fwspec_iommu_ops(
> > struct iommu_fwspec *fwspec)
> > {
^ permalink raw reply
* [PATCH v2 15/36] KVM: arm64: Move userspace system registers into separate function
From: Christoffer Dall @ 2017-12-14 12:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a965d4ae-2bbf-5f57-61c4-aee38ae74991@arm.com>
On Mon, Dec 11, 2017 at 10:14:23AM +0000, Marc Zyngier wrote:
> On 07/12/17 17:06, Christoffer Dall wrote:
> > There's a semantic difference between the EL1 registers that control
> > operation of a kernel running in EL1 and EL1 registers that only control
> > userspace execution in EL0. Since we can defer saving/restoring the
> > latter, move them into their own function.
> >
> > We also take this chance to rename the function saving/restoring the
> > remaining system register to make it clear this function deals with
> > the EL1 system registers.
> >
> > No functional change.
> >
> > Reviewed-by: Andrew Jones <drjones@redhat.com>
> > Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> > ---
> >
> > Notes:
> > Changes since v1:
> > - Added comment about sp_el0 to common save sysreg save/restore functions
> >
> > arch/arm64/kvm/hyp/sysreg-sr.c | 44 +++++++++++++++++++++++++++++++-----------
> > 1 file changed, 33 insertions(+), 11 deletions(-)
> >
> > diff --git a/arch/arm64/kvm/hyp/sysreg-sr.c b/arch/arm64/kvm/hyp/sysreg-sr.c
> > index 68a7d164e5e1..bbfb4d01af88 100644
> > --- a/arch/arm64/kvm/hyp/sysreg-sr.c
> > +++ b/arch/arm64/kvm/hyp/sysreg-sr.c
> > @@ -33,15 +33,24 @@ static void __hyp_text __sysreg_do_nothing(struct kvm_cpu_context *ctxt) { }
> > */
> >
> > static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt)
> > +{
> > + ctxt->sys_regs[MDSCR_EL1] = read_sysreg(mdscr_el1);
> > +
> > + /*
> > + * The host arm64 Linux uses sp_el0 to point to 'current' and it must
> > + * therefore be saved/restored on every entry/exit to/from the guest.
> > + */
> > + ctxt->gp_regs.regs.sp = read_sysreg(sp_el0);
> > +}
> > +
> > +static void __hyp_text __sysreg_save_user_state(struct kvm_cpu_context *ctxt)
> > {
> > ctxt->sys_regs[ACTLR_EL1] = read_sysreg(actlr_el1);
>
> What is the rational for keeping ACTLR_EL1 as part of the user state?
>
The rationale was that I missed the note you pointed me to below, and
therefore I figured that ACTLR_EL1 couldn't affect the host kernel,
because it runs in EL2, but could affect host userspace, which is
incorrect. So I was basically just being overlay cautious.
> > ctxt->sys_regs[TPIDR_EL0] = read_sysreg(tpidr_el0);
> > ctxt->sys_regs[TPIDRRO_EL0] = read_sysreg(tpidrro_el0);
> > - ctxt->sys_regs[MDSCR_EL1] = read_sysreg(mdscr_el1);
> > - ctxt->gp_regs.regs.sp = read_sysreg(sp_el0);
> > }
> >
> > -static void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt)
> > +static void __hyp_text __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
> > {
> > ctxt->sys_regs[MPIDR_EL1] = read_sysreg(vmpidr_el2);
> > ctxt->sys_regs[CSSELR_EL1] = read_sysreg(csselr_el1);
> > @@ -70,31 +79,42 @@ static void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt)
> > }
> >
> > static hyp_alternate_select(__sysreg_call_save_host_state,
> > - __sysreg_save_state, __sysreg_do_nothing,
> > + __sysreg_save_el1_state, __sysreg_do_nothing,
> > ARM64_HAS_VIRT_HOST_EXTN);
> >
> > void __hyp_text __sysreg_save_host_state(struct kvm_cpu_context *ctxt)
> > {
> > __sysreg_call_save_host_state()(ctxt);
> > __sysreg_save_common_state(ctxt);
> > + __sysreg_save_user_state(ctxt);
> > }
> >
> > void __hyp_text __sysreg_save_guest_state(struct kvm_cpu_context *ctxt)
> > {
> > - __sysreg_save_state(ctxt);
> > + __sysreg_save_el1_state(ctxt);
> > __sysreg_save_common_state(ctxt);
> > + __sysreg_save_user_state(ctxt);
> > }
> >
> > static void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt)
> > {
> > - write_sysreg(ctxt->sys_regs[ACTLR_EL1], actlr_el1);
> > - write_sysreg(ctxt->sys_regs[TPIDR_EL0], tpidr_el0);
> > - write_sysreg(ctxt->sys_regs[TPIDRRO_EL0], tpidrro_el0);
> > write_sysreg(ctxt->sys_regs[MDSCR_EL1], mdscr_el1);
> > +
> > + /*
> > + * The host arm64 Linux uses sp_el0 to point to 'current' and it must
> > + * therefore be saved/restored on every entry/exit to/from the guest.
> > + */
> > write_sysreg(ctxt->gp_regs.regs.sp, sp_el0);
> > }
> >
> > -static void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt)
> > +static void __hyp_text __sysreg_restore_user_state(struct kvm_cpu_context *ctxt)
> > +{
> > + write_sysreg(ctxt->sys_regs[ACTLR_EL1], actlr_el1);
>
> Same here.
>
> > + write_sysreg(ctxt->sys_regs[TPIDR_EL0], tpidr_el0);
> > + write_sysreg(ctxt->sys_regs[TPIDRRO_EL0], tpidrro_el0);
> > +}
> > +
> > +static void __hyp_text __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt)
> > {
> > write_sysreg(ctxt->sys_regs[MPIDR_EL1], vmpidr_el2);
> > write_sysreg(ctxt->sys_regs[CSSELR_EL1], csselr_el1);
> > @@ -123,19 +143,21 @@ static void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt)
> > }
> >
> > static hyp_alternate_select(__sysreg_call_restore_host_state,
> > - __sysreg_restore_state, __sysreg_do_nothing,
> > + __sysreg_restore_el1_state, __sysreg_do_nothing,
> > ARM64_HAS_VIRT_HOST_EXTN);
> >
> > void __hyp_text __sysreg_restore_host_state(struct kvm_cpu_context *ctxt)
> > {
> > __sysreg_call_restore_host_state()(ctxt);
> > __sysreg_restore_common_state(ctxt);
> > + __sysreg_restore_user_state(ctxt);
> > }
> >
> > void __hyp_text __sysreg_restore_guest_state(struct kvm_cpu_context *ctxt)
> > {
> > - __sysreg_restore_state(ctxt);
> > + __sysreg_restore_el1_state(ctxt);
> > __sysreg_restore_common_state(ctxt);
> > + __sysreg_restore_user_state(ctxt);
> > }
> >
> > static void __hyp_text __fpsimd32_save_state(struct kvm_cpu_context *ctxt)
> >
>
> I think we should move ACTLR_EL1 to the EL1 state, allowing it to be
> lazily switched. See the note in D10.2.1 that recommends a VHE enabled
> system to have ACTLR_EL1 as a guest-only register.
Thanks for this pointer. I will adjust the code as you suggest.
-Christoffer
^ permalink raw reply
* [PATCH 00/12] mmc: sdhci-omap: Add UHS/HS200 mode support
From: Kishon Vijay Abraham I @ 2017-12-14 13:09 UTC (permalink / raw)
To: linux-arm-kernel
Add UHS/HS200 mode support in sdhci-omap. The programming sequence
for voltage switching, tuning is followed from AM572x TRM
http://www.ti.com/lit/ug/spruhz6i/spruhz6i.pdf
(Similar to all AM57x/DRA7x SoCs). The patch series also implements
workaround for errata published in
http://www.ti.com/lit/er/sprz429k/sprz429k.pdf.
While most of this series is specific to sdhci-omap, it also
patches sdhci to use software timer when the requested timeout
is greater than hardware capablility. This re-uses the SW data timer
already implemented in sdhci while disabling the HW timeout (so that
spurious timeout is not observed). The patch for sdhci.c is based on
an earlier patch that was done specific to omap_hsmmc.c
(https://patchwork.kernel.org/patch/9791449/)
It also includes a pdata-quirk patch since both pdata-quirks and
sdhci-omap uses struct sdhci_omap_platform_data.
The dt patches enabling UHS/HS200 will be follow this patch series.
This series is created on
git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git next
Kishon Vijay Abraham I (12):
mmc: sdhci-omap: Update 'power_mode' outside sdhci_omap_init_74_clocks
mmc: sdhci-omap: Add card_busy host ops
mmc: sdhci-omap: Add custom set_uhs_signaling sdhci_host ops
mmc: sdhci-omap: Add tuning support
mmc: sdhci-omap: Workaround for Errata i802
mmc: sdhci_omap: Add support to set IODELAY values
mmc: sdhci_omap: Fix sdhci-omap quirks
mmc: sdhci-omap: Add support to override f_max and iodelay from pdata
mmc: sdhci: Use software timer when timeout greater than hardware
capablility
dt-bindings: sdhci-omap: Add K2G specific binding
mmc: sdhci-omap: Add support for MMC/SD controller in k2g SoC
ARM: OMAP2+: Use sdhci-omap specific pdata-quirks for MMC/SD on DRA74x
EVM
.../devicetree/bindings/mmc/sdhci-omap.txt | 2 +
arch/arm/mach-omap2/pdata-quirks.c | 34 +-
drivers/mmc/host/sdhci-omap.c | 446 ++++++++++++++++++++-
drivers/mmc/host/sdhci.c | 41 +-
drivers/mmc/host/sdhci.h | 11 +
include/linux/platform_data/sdhci-omap.h | 35 ++
6 files changed, 544 insertions(+), 25 deletions(-)
create mode 100644 include/linux/platform_data/sdhci-omap.h
--
2.11.0
^ permalink raw reply
* [PATCH 01/12] mmc: sdhci-omap: Update 'power_mode' outside sdhci_omap_init_74_clocks
From: Kishon Vijay Abraham I @ 2017-12-14 13:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171214130941.26666-1-kishon@ti.com>
Updating 'power_mode' in sdhci_omap_init_74_clocks results in
'power_mode' never updated to MMC_POWER_OFF during card
removal. This results in initialization sequence not sent to the
card during re-insertion.
Fix it here by adding sdhci_omap_set_power_mode to update power_mode.
This function can also be used later to perform operations that
are specific to a power mode (e.g, disable tuning during power off).
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
drivers/mmc/host/sdhci-omap.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c
index 628bfe9a3d17..96985786cadf 100644
--- a/drivers/mmc/host/sdhci-omap.c
+++ b/drivers/mmc/host/sdhci-omap.c
@@ -244,6 +244,12 @@ static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc,
return 0;
}
+static void sdhci_omap_set_power_mode(struct sdhci_omap_host *omap_host,
+ u8 power_mode)
+{
+ omap_host->power_mode = power_mode;
+}
+
static void sdhci_omap_set_bus_mode(struct sdhci_omap_host *omap_host,
unsigned int mode)
{
@@ -273,6 +279,7 @@ static void sdhci_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
sdhci_omap_set_bus_mode(omap_host, ios->bus_mode);
sdhci_set_ios(mmc, ios);
+ sdhci_omap_set_power_mode(omap_host, ios->power_mode);
}
static u16 sdhci_omap_calc_divisor(struct sdhci_pltfm_host *host,
@@ -401,8 +408,6 @@ static void sdhci_omap_init_74_clocks(struct sdhci_host *host, u8 power_mode)
sdhci_omap_writel(omap_host, SDHCI_OMAP_STAT, INT_CC_EN);
enable_irq(host->irq);
-
- omap_host->power_mode = power_mode;
}
static struct sdhci_ops sdhci_omap_ops = {
@@ -504,6 +509,7 @@ static int sdhci_omap_probe(struct platform_device *pdev)
omap_host->host = host;
omap_host->base = host->ioaddr;
omap_host->dev = dev;
+ omap_host->power_mode = MMC_POWER_UNDEFINED;
host->ioaddr += offset;
mmc = host->mmc;
--
2.11.0
^ permalink raw reply related
* [PATCH 02/12] mmc: sdhci-omap: Add card_busy host ops
From: Kishon Vijay Abraham I @ 2017-12-14 13:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171214130941.26666-1-kishon@ti.com>
card_busy ops is used by mmc core in
1) mmc_set_uhs_voltage to verify voltage switch
2) __mmc_start_request/mmc_poll_for_busy to check the card busy status
While only DAT0 can be used to check the card busy status (in '2' above),
CMD and DAT[0..3] is used to verify voltage switch (in '1' above).
The voltage switching sequence for AM572x platform is mentioned
in Figure 25-48. eMMC/SD/SDIO Power Switching Procedure of
AM572x Sitara Processors Silicon Revision 2.0, 1.1 TRM
(SPRUHZ6I - October 2014?Revised April 2017 [1]).
Add card_busy host ops in sdhci_omap that checks for both CMD and
DAT[0..3]. card_busy here returns true if one of CMD and DAT[0..3] is
low though during voltage switch sequence all of CMD and DAT[0..3] has
to be low (however haven't observed a case where some DAT lines are low
and some are high).
In the voltage switching sequence, CLKEXTFREE bit in MMCHS_CON
should also be set after switching to 1.8v which is also taken
care in the card_busy ops.
[1] -> http://www.ti.com/lit/ug/spruhz6i/spruhz6i.pdf
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
drivers/mmc/host/sdhci-omap.c | 62 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c
index 96985786cadf..defe4eac020d 100644
--- a/drivers/mmc/host/sdhci-omap.c
+++ b/drivers/mmc/host/sdhci-omap.c
@@ -31,11 +31,20 @@
#define SDHCI_OMAP_CON 0x12c
#define CON_DW8 BIT(5)
#define CON_DMA_MASTER BIT(20)
+#define CON_CLKEXTFREE BIT(16)
+#define CON_PADEN BIT(15)
#define CON_INIT BIT(1)
#define CON_OD BIT(0)
#define SDHCI_OMAP_CMD 0x20c
+#define SDHCI_OMAP_PSTATE 0x0224
+#define PSTATE_CLEV BIT(24)
+#define PSTATE_DLEV_SHIFT 20
+#define PSTATE_DLEV_DAT(x) (1 << (PSTATE_DLEV_SHIFT + (x)))
+#define PSTATE_DLEV (PSTATE_DLEV_DAT(0) | PSTATE_DLEV_DAT(1) | \
+ PSTATE_DLEV_DAT(2) | PSTATE_DLEV_DAT(3))
+
#define SDHCI_OMAP_HCTL 0x228
#define HCTL_SDBP BIT(8)
#define HCTL_SDVS_SHIFT 9
@@ -191,6 +200,58 @@ static void sdhci_omap_conf_bus_power(struct sdhci_omap_host *omap_host,
}
}
+static int sdhci_omap_card_busy(struct mmc_host *mmc)
+{
+ int i;
+ u32 reg, ac12;
+ int ret = true;
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct sdhci_pltfm_host *pltfm_host;
+ struct sdhci_omap_host *omap_host;
+ u32 ier = host->ier;
+
+ pltfm_host = sdhci_priv(host);
+ omap_host = sdhci_pltfm_priv(pltfm_host);
+
+ reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON);
+ ac12 = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12);
+ reg &= ~CON_CLKEXTFREE;
+ if (ac12 & AC12_V1V8_SIGEN)
+ reg |= CON_CLKEXTFREE;
+ reg |= CON_PADEN;
+ sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg);
+
+ disable_irq(host->irq);
+ ier |= SDHCI_INT_CARD_INT;
+ sdhci_writel(host, ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
+
+ for (i = 0; i < 5; i++) {
+ /*
+ * Delay is required for PSTATE to correctly reflect
+ * DLEV/CLEV values after PADEM is set.
+ */
+ usleep_range(100, 200);
+ reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_PSTATE);
+ if ((reg & PSTATE_CLEV) &&
+ ((reg & PSTATE_DLEV) == PSTATE_DLEV)) {
+ ret = false;
+ goto ret;
+ }
+ }
+
+ret:
+ reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON);
+ reg &= ~(CON_CLKEXTFREE | CON_PADEN);
+ sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg);
+
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+ enable_irq(host->irq);
+
+ return ret;
+}
+
static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc,
struct mmc_ios *ios)
{
@@ -562,6 +623,7 @@ static int sdhci_omap_probe(struct platform_device *pdev)
host->mmc_host_ops.start_signal_voltage_switch =
sdhci_omap_start_signal_voltage_switch;
host->mmc_host_ops.set_ios = sdhci_omap_set_ios;
+ host->mmc_host_ops.card_busy = sdhci_omap_card_busy;
sdhci_read_caps(host);
host->caps |= SDHCI_CAN_DO_ADMA2;
--
2.11.0
^ permalink raw reply related
* [PATCH 03/12] mmc: sdhci-omap: Add custom set_uhs_signaling sdhci_host ops
From: Kishon Vijay Abraham I @ 2017-12-14 13:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171214130941.26666-1-kishon@ti.com>
UHS-1 DDR50 and MMC DDR52 mode require DDR bit to be
set in the configuration register (MMCHS_CON). Add
sdhci-omap specific set_uhs_signaling ops to set
this bit. Also while setting the UHSMS bit, clock should be
disabled.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
drivers/mmc/host/sdhci-omap.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c
index defe4eac020d..8f7239e2edc2 100644
--- a/drivers/mmc/host/sdhci-omap.c
+++ b/drivers/mmc/host/sdhci-omap.c
@@ -31,6 +31,7 @@
#define SDHCI_OMAP_CON 0x12c
#define CON_DW8 BIT(5)
#define CON_DMA_MASTER BIT(20)
+#define CON_DDR BIT(19)
#define CON_CLKEXTFREE BIT(16)
#define CON_PADEN BIT(15)
#define CON_INIT BIT(1)
@@ -93,6 +94,9 @@ struct sdhci_omap_host {
u8 power_mode;
};
+static void sdhci_omap_start_clock(struct sdhci_omap_host *omap_host);
+static void sdhci_omap_stop_clock(struct sdhci_omap_host *omap_host);
+
static inline u32 sdhci_omap_readl(struct sdhci_omap_host *host,
unsigned int offset)
{
@@ -471,6 +475,26 @@ static void sdhci_omap_init_74_clocks(struct sdhci_host *host, u8 power_mode)
enable_irq(host->irq);
}
+static void sdhci_omap_set_uhs_signaling(struct sdhci_host *host,
+ unsigned int timing)
+{
+ u32 reg;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host);
+
+ sdhci_omap_stop_clock(omap_host);
+
+ reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON);
+ if (timing == MMC_TIMING_UHS_DDR50 || timing == MMC_TIMING_MMC_DDR52)
+ reg |= CON_DDR;
+ else
+ reg &= ~CON_DDR;
+ sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg);
+
+ sdhci_set_uhs_signaling(host, timing);
+ sdhci_omap_start_clock(omap_host);
+}
+
static struct sdhci_ops sdhci_omap_ops = {
.set_clock = sdhci_omap_set_clock,
.set_power = sdhci_omap_set_power,
@@ -480,7 +504,7 @@ static struct sdhci_ops sdhci_omap_ops = {
.set_bus_width = sdhci_omap_set_bus_width,
.platform_send_init_74_clocks = sdhci_omap_init_74_clocks,
.reset = sdhci_reset,
- .set_uhs_signaling = sdhci_set_uhs_signaling,
+ .set_uhs_signaling = sdhci_omap_set_uhs_signaling,
};
static int sdhci_omap_set_capabilities(struct sdhci_omap_host *omap_host)
--
2.11.0
^ permalink raw reply related
* [PATCH 04/12] mmc: sdhci-omap: Add tuning support
From: Kishon Vijay Abraham I @ 2017-12-14 13:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171214130941.26666-1-kishon@ti.com>
MMC tuning procedure is required to support SD card
UHS1-SDR104 mode and EMMC HS200 mode.
SDR104/HS200 DLL Tuning Procedure for AM572x platform is mentioned
in Figure 25-51. SDR104/HS200 DLL Tuning Procedure of
AM572x Sitara Processors Silicon Revision 2.0, 1.1 TRM
(SPRUHZ6I - October 2014?Revised April 2017 [1]).
The tuning function sdhci_omap_execute_tuning() will only be
called by the MMC/SD core if the corresponding speed modes
are supported by the OMAP silicon which is set in the mmc
host "caps" field.
[1] -> http://www.ti.com/lit/ug/spruhz6i/spruhz6i.pdf
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
drivers/mmc/host/sdhci-omap.c | 130 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 130 insertions(+)
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c
index 8f7239e2edc2..df8a0a472996 100644
--- a/drivers/mmc/host/sdhci-omap.c
+++ b/drivers/mmc/host/sdhci-omap.c
@@ -37,6 +37,13 @@
#define CON_INIT BIT(1)
#define CON_OD BIT(0)
+#define SDHCI_OMAP_DLL 0x0134
+#define DLL_SWT BIT(20)
+#define DLL_FORCE_SR_C_SHIFT 13
+#define DLL_FORCE_SR_C_MASK (0x7f << DLL_FORCE_SR_C_SHIFT)
+#define DLL_FORCE_VALUE BIT(12)
+#define DLL_CALIB BIT(1)
+
#define SDHCI_OMAP_CMD 0x20c
#define SDHCI_OMAP_PSTATE 0x0224
@@ -66,12 +73,16 @@
#define SDHCI_OMAP_AC12 0x23c
#define AC12_V1V8_SIGEN BIT(19)
+#define AC12_SCLK_SEL BIT(23)
#define SDHCI_OMAP_CAPA 0x240
#define CAPA_VS33 BIT(24)
#define CAPA_VS30 BIT(25)
#define CAPA_VS18 BIT(26)
+#define SDHCI_OMAP_CAPA2 0x0244
+#define CAPA2_TSDR50 BIT(13)
+
#define SDHCI_OMAP_TIMEOUT 1 /* 1 msec */
#define SYSCTL_CLKD_MAX 0x3FF
@@ -80,6 +91,8 @@
#define IOV_3V0 3000000 /* 300000 uV */
#define IOV_3V3 3300000 /* 330000 uV */
+#define MAX_PHASE_DELAY 0x7C
+
struct sdhci_omap_data {
u32 offset;
};
@@ -204,6 +217,120 @@ static void sdhci_omap_conf_bus_power(struct sdhci_omap_host *omap_host,
}
}
+static inline void sdhci_omap_set_dll(struct sdhci_omap_host *omap_host,
+ int count)
+{
+ int i;
+ u32 reg;
+
+ reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_DLL);
+ reg |= DLL_FORCE_VALUE;
+ reg &= ~DLL_FORCE_SR_C_MASK;
+ reg |= (count << DLL_FORCE_SR_C_SHIFT);
+ sdhci_omap_writel(omap_host, SDHCI_OMAP_DLL, reg);
+
+ reg |= DLL_CALIB;
+ sdhci_omap_writel(omap_host, SDHCI_OMAP_DLL, reg);
+ for (i = 0; i < 1000; i++) {
+ reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_DLL);
+ if (reg & DLL_CALIB)
+ break;
+ }
+ reg &= ~DLL_CALIB;
+ sdhci_omap_writel(omap_host, SDHCI_OMAP_DLL, reg);
+}
+
+static void sdhci_omap_disable_tuning(struct sdhci_omap_host *omap_host)
+{
+ u32 reg;
+
+ reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12);
+ reg &= ~AC12_SCLK_SEL;
+ sdhci_omap_writel(omap_host, SDHCI_OMAP_AC12, reg);
+
+ reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_DLL);
+ reg &= ~(DLL_FORCE_VALUE | DLL_SWT);
+ sdhci_omap_writel(omap_host, SDHCI_OMAP_DLL, reg);
+}
+
+static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ u32 reg;
+ int ret = 0;
+ u8 cur_match, prev_match = 0;
+ u32 phase_delay = 0;
+ u32 start_window = 0, max_window = 0;
+ u32 length = 0, max_len = 0;
+ struct mmc_ios *ios = &mmc->ios;
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct sdhci_pltfm_host *pltfm_host;
+ struct sdhci_omap_host *omap_host;
+ struct device *dev;
+
+ pltfm_host = sdhci_priv(host);
+ omap_host = sdhci_pltfm_priv(pltfm_host);
+ dev = omap_host->dev;
+
+ /* clock tuning is not needed for upto 52MHz */
+ if (ios->clock <= 52000000)
+ return 0;
+
+ reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA2);
+ if (ios->timing == MMC_TIMING_UHS_SDR50 && !(reg & CAPA2_TSDR50))
+ return 0;
+
+ reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_DLL);
+ reg |= DLL_SWT;
+ sdhci_omap_writel(omap_host, SDHCI_OMAP_DLL, reg);
+
+ while (phase_delay <= MAX_PHASE_DELAY) {
+ sdhci_omap_set_dll(omap_host, phase_delay);
+
+ cur_match = !mmc_send_tuning(mmc, opcode, NULL);
+ if (cur_match) {
+ if (prev_match) {
+ length++;
+ } else {
+ start_window = phase_delay;
+ length = 1;
+ }
+ }
+
+ if (length > max_len) {
+ max_window = start_window;
+ max_len = length;
+ }
+
+ prev_match = cur_match;
+ phase_delay += 4;
+ }
+
+ if (!max_len) {
+ dev_err(dev, "Unable to find match\n");
+ ret = -EIO;
+ goto tuning_error;
+ }
+
+ reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12);
+ if (!(reg & AC12_SCLK_SEL)) {
+ ret = -EIO;
+ goto tuning_error;
+ }
+
+ phase_delay = max_window + 4 * (max_len >> 1);
+ sdhci_omap_set_dll(omap_host, phase_delay);
+
+ goto ret;
+
+tuning_error:
+ dev_err(dev, "Tuning failed\n");
+ sdhci_omap_disable_tuning(omap_host);
+
+ret:
+ sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+ return ret;
+}
+
static int sdhci_omap_card_busy(struct mmc_host *mmc)
{
int i;
@@ -312,6 +439,8 @@ static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc,
static void sdhci_omap_set_power_mode(struct sdhci_omap_host *omap_host,
u8 power_mode)
{
+ if (omap_host->bus_mode == MMC_POWER_OFF)
+ sdhci_omap_disable_tuning(omap_host);
omap_host->power_mode = power_mode;
}
@@ -648,6 +777,7 @@ static int sdhci_omap_probe(struct platform_device *pdev)
sdhci_omap_start_signal_voltage_switch;
host->mmc_host_ops.set_ios = sdhci_omap_set_ios;
host->mmc_host_ops.card_busy = sdhci_omap_card_busy;
+ host->mmc_host_ops.execute_tuning = sdhci_omap_execute_tuning;
sdhci_read_caps(host);
host->caps |= SDHCI_CAN_DO_ADMA2;
--
2.11.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox