* [PATCH] arm64: dts: hisilicon: Add hi3660 cpu capacity-dmips-mhz information
From: Leo Yan @ 2017-12-14 1:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cddaf386-5688-a064-7cb0-1e75485330c4@arm.com>
On Wed, Dec 13, 2017 at 03:16:13PM +0000, Valentin Schneider wrote:
> Hi Leo,
>
>
> On 12/13/2017 02:53 PM, Leo Yan wrote:
> >Hi Valentin,
> >
> >On Wed, Dec 13, 2017 at 02:21:06PM +0000, Valentin Schneider wrote:
> >>The following dt entries are added:
> >> cpus [0-3] (Cortex A53):
> >> - capacity-dmips-mhz = <592>;
> >>
> >> cpus [4-7] (Cortex A73):
> >> - capacity-dmips-mhz = <1024>;
> >>
> >>Those values were obtained by running dhrystone 2.1 on a
> >>HiKey960 with the following procedure:
> >>- Offline all CPUs but CPU0 (A53)
> >>- Set CPU0 frequency to maximum
> >>- Run Dhrystone 2.1 for 20 seconds
> >>
> >>- Offline all CPUs but CPU4 (A73)
> >>- set CPU4 frequency to maximum
> >>- Run Dhrystone 2.1 for 20 seconds
> >>
> >>The results are as follows:
> >>A53: 129633887 loops
> >>A73: 287034147 loops
> >Seems to me the capacity-dmips-mhz should be:
> >
> >CA53: 129633887 / 20 / 1844 = 3515
> >CA73: 287034147 / 20 / 2362 = 6076
> >
> >After normalized to range [0..1024], we could get:
> >
> >CA53: 592
> >CA73: 1024
>
> Yes, that's the "direct approach". I wanted to underline the fact that there
> are two different max frequencies so what I followed would be:
>
> 1) Computing the performance ratio:
> (129633887 / 287034147) * 1024 = 462.47
>
> 2) Scaling that to the same frequency scale:
> 462.47 * (2362/1844) = 592.38
>
> Which gives the same end result (it's the same equation but split in two
> steps). Also it makes it easy to check that the cpu_capacity sysfs entry for
> the A53s gets correctly set (to 462).
Yeah, thanks for clear explanation.
[...]
Thanks,
Leo Yan
^ permalink raw reply
* [PATCH 1/2] cpufreq: mvebu: Free the clock reference in the normal path
From: Viresh Kumar @ 2017-12-14 2:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213172914.6148-2-gregory.clement@free-electrons.com>
On 13-12-17, 18:29, Gregory CLEMENT wrote:
> In case of error the clock reference was freed but not in normal path
> once it was nor more used. This patch fixes it.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> drivers/cpufreq/mvebu-cpufreq.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/cpufreq/mvebu-cpufreq.c b/drivers/cpufreq/mvebu-cpufreq.c
> index ed915ee85dd9..c043aad8e3a0 100644
> --- a/drivers/cpufreq/mvebu-cpufreq.c
> +++ b/drivers/cpufreq/mvebu-cpufreq.c
> @@ -99,6 +99,7 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
> if (ret)
> dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
> __func__, ret);
> + clk_put(clk);
> }
>
> platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* [PATCH 2/2] cpufreq: mvebu: Free opp if registering failed
From: Viresh Kumar @ 2017-12-14 2:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213172914.6148-3-gregory.clement@free-electrons.com>
On 13-12-17, 18:29, Gregory CLEMENT wrote:
> Since the introduction of this driver, the functions to remove the opp
> were added. So stop claiming we can't remove opp and use one of them in
> case of failure.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> drivers/cpufreq/mvebu-cpufreq.c | 15 ++++++++-------
> 1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/cpufreq/mvebu-cpufreq.c b/drivers/cpufreq/mvebu-cpufreq.c
> index c043aad8e3a0..31513bd42705 100644
> --- a/drivers/cpufreq/mvebu-cpufreq.c
> +++ b/drivers/cpufreq/mvebu-cpufreq.c
> @@ -76,12 +76,6 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
> return PTR_ERR(clk);
> }
>
> - /*
> - * In case of a failure of dev_pm_opp_add(), we don't
> - * bother with cleaning up the registered OPP (there's
> - * no function to do so), and simply cancel the
> - * registration of the cpufreq device.
> - */
> ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk), 0);
> if (ret) {
> clk_put(clk);
> @@ -91,7 +85,8 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
> ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk) / 2, 0);
> if (ret) {
> clk_put(clk);
> - return ret;
> + dev_err(cpu_dev, "Failed to register OPPs\n");
> + goto opp_register_failed;
> }
>
> ret = dev_pm_opp_set_sharing_cpus(cpu_dev,
> @@ -104,5 +99,11 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
>
> platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
> return 0;
> +
> +opp_register_failed:
> + /* As registering has failed remove all the opp for all cpus */
> + dev_pm_opp_cpumask_remove_table(cpu_possible_mask);
> +
> + return ret;
> }
> device_initcall(armada_xp_pmsu_cpufreq_init);
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* [PATCH v2] ARM64: dts: meson-axg: add ethernet mac controller
From: Yixun Lan @ 2017-12-14 3:02 UTC (permalink / raw)
To: linux-arm-kernel
Add DT info for the stmmac ethernet MAC which found in
the Amlogic's Meson-AXG SoC, also describe the ethernet
pinctrl & clock information here.
This is tested in the S400 dev board which use a RTL8211F PHY,
and the pins connect to the 'eth_rgmii_y_pins' group.
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Yixun Lan <yixun.lan@amlogic.com>
---
Changes in v2 since [1]:
- rebase to kevin's v4.16/dt64 branch
- add Neil's Reviewed-by
- move clock info to board.dts instead of in soc.dtsi
- drop "meson-axg-dwmac" compatible string, since we didn't use this
we could re-add it later when we really need.
- note: to make ethernet work properly,it depend on clock & pinctrl[2],
to compile the DTS, the patch [3] is required.
the code part will be taken via clock & pinctrl subsystem tree.
[1]
http://lists.infradead.org/pipermail/linux-amlogic/2017-November/005301.html
[2]
http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005735.html
http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005694.html
[3]
http://lists.infradead.org/pipermail/linux-amlogic/2017-December/005738.html
---
arch/arm64/boot/dts/amlogic/meson-axg-s400.dts | 11 ++++++
arch/arm64/boot/dts/amlogic/meson-axg.dtsi | 50 ++++++++++++++++++++++++++
2 files changed, 61 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
index 70eca1f8736a..138de3bc7cc8 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
@@ -20,3 +20,14 @@
&uart_AO {
status = "okay";
};
+
+ðmac {
+ status = "okay";
+ clocks = <&clkc CLKID_ETH>,
+ <&clkc CLKID_FCLK_DIV2>,
+ <&clkc CLKID_MPLL2>;
+ clock-names = "stmmaceth", "clkin0", "clkin1";
+ phy-mode = "rgmii";
+ pinctrl-0 = <ð_rgmii_y_pins>;
+ pinctrl-names = "default";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
index d356ce74ad89..106234fda765 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -7,6 +7,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/axg-clkc.h>
/ {
compatible = "amlogic,meson-axg";
@@ -148,6 +149,15 @@
#address-cells = <0>;
};
+ ethmac: ethernet at ff3f0000 {
+ compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
+ reg = <0x0 0xff3f0000 0x0 0x10000
+ 0x0 0xff634540 0x0 0x8>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "macirq";
+ status = "disabled";
+ };
+
hiubus: bus at ff63c000 {
compatible = "simple-bus";
reg = <0x0 0xff63c000 0x0 0x1c00>;
@@ -194,6 +204,46 @@
#gpio-cells = <2>;
gpio-ranges = <&pinctrl_periphs 0 0 86>;
};
+
+ eth_rgmii_x_pins: eth-x-rgmii {
+ mux {
+ groups = "eth_mdio_x",
+ "eth_mdc_x",
+ "eth_rgmii_rx_clk_x",
+ "eth_rx_dv_x",
+ "eth_rxd0_x",
+ "eth_rxd1_x",
+ "eth_rxd2_rgmii",
+ "eth_rxd3_rgmii",
+ "eth_rgmii_tx_clk",
+ "eth_txen_x",
+ "eth_txd0_x",
+ "eth_txd1_x",
+ "eth_txd2_rgmii",
+ "eth_txd3_rgmii";
+ function = "eth";
+ };
+ };
+
+ eth_rgmii_y_pins: eth-y-rgmii {
+ mux {
+ groups = "eth_mdio_y",
+ "eth_mdc_y",
+ "eth_rgmii_rx_clk_y",
+ "eth_rx_dv_y",
+ "eth_rxd0_y",
+ "eth_rxd1_y",
+ "eth_rxd2_rgmii",
+ "eth_rxd3_rgmii",
+ "eth_rgmii_tx_clk",
+ "eth_txen_y",
+ "eth_txd0_y",
+ "eth_txd1_y",
+ "eth_txd2_rgmii",
+ "eth_txd3_rgmii";
+ function = "eth";
+ };
+ };
};
};
--
2.15.1
^ permalink raw reply related
* [PATCH v3 3/4] cpufreq: Add DVFS support for Armada 37xx
From: Viresh Kumar @ 2017-12-14 3:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213175119.9441-4-gregory.clement@free-electrons.com>
I just searched for tabs and spaces in this patch and here are the observations.
On 13-12-17, 18:51, Gregory CLEMENT wrote:
> +/* Power management in North Bridge register set */
> +#define ARMADA_37XX_NB_L0L1 0x18
There is a single space after #define here, which is good.
> +#define ARMADA_37XX_NB_L2L3 0x1C
> +#define ARMADA_37XX_NB_TBG_DIV_OFF 13
But here and at many places below you have two spaces after #define, which isn't
bad but isn't consistent as well.
> +#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7
> +#define ARMADA_37XX_NB_CLK_SEL_OFF 11
> +#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1
> +#define ARMADA_37XX_NB_CLK_SEL_TBG 0x1
You have used space instead of TAB after ARMADA_37XX_NB_CLK_SEL_TBG here, while
everywhere else we have tabs. Maybe its better to be consistent ?
> +#define ARMADA_37XX_NB_TBG_SEL_OFF 9
> +#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3
> +#define ARMADA_37XX_NB_VDD_SEL_OFF 6
> +#define ARMADA_37XX_NB_VDD_SEL_MASK 0x3
> +#define ARMADA_37XX_NB_CONFIG_SHIFT 16
> +#define ARMADA_37XX_NB_DYN_MOD 0x24
> +#define ARMADA_37XX_NB_CLK_SEL_EN BIT(26)
> +#define ARMADA_37XX_NB_TBG_EN BIT(28)
> +#define ARMADA_37XX_NB_DIV_EN BIT(29)
> +#define ARMADA_37XX_NB_VDD_EN BIT(30)
> +#define ARMADA_37XX_NB_DFS_EN BIT(31)
> +#define ARMADA_37XX_NB_CPU_LOAD 0x30
> +#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3
> +#define ARMADA_37XX_DVFS_LOAD_0 0
> +#define ARMADA_37XX_DVFS_LOAD_1 1
> +#define ARMADA_37XX_DVFS_LOAD_2 2
> +#define ARMADA_37XX_DVFS_LOAD_3 3
> +
> +/*
> + * On Armada 37xx the Power management manages 4 level of CPU load,
> + * each level can be associated with a CPU clock source, a CPU
> + * divider, a VDD level, etc...
> + */
> +#define LOAD_LEVEL_NR 4
> +
> +struct armada_37xx_dvfs {
> + u32 cpu_freq_max;
> + u8 divider[LOAD_LEVEL_NR];
> +};
> +
> +static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
> + {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
> + {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
> + {.cpu_freq_max = 800*1000*1000, .divider = {1, 2, 3, 4} },
> + {.cpu_freq_max = 600*1000*1000, .divider = {2, 4, 5, 6} },
> +};
> +
> +static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) {
> + if (freq == armada_37xx_dvfs[i].cpu_freq_max)
> + return &armada_37xx_dvfs[i];
> + }
> +
> + pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000);
> + return NULL;
> +}
> +
> +/*
> + * Setup the four level managed by the hardware. Once the four level
> + * will be configured then the DVFS will be enabled.
> + */
> +static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
> + struct clk *clk, u8 *divider)
> +{
> + int load_lvl;
> + struct clk *parent;
> +
> + for (load_lvl = 0; load_lvl < LOAD_LEVEL_NR; load_lvl++) {
> + unsigned int reg, mask, val, offset = 0;
double space before "val".
> +
> + if (load_lvl <= ARMADA_37XX_DVFS_LOAD_1)
> + reg = ARMADA_37XX_NB_L0L1;
> + else
> + reg = ARMADA_37XX_NB_L2L3;
> +
> + if (load_lvl == ARMADA_37XX_DVFS_LOAD_0 ||
> + load_lvl == ARMADA_37XX_DVFS_LOAD_2)
double spaces after ==
> + offset += ARMADA_37XX_NB_CONFIG_SHIFT;
> +
> + /* Set cpu clock source, for all the level we use TBG */
> + val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF;
> + mask = (ARMADA_37XX_NB_CLK_SEL_MASK
> + << ARMADA_37XX_NB_CLK_SEL_OFF);
> +
> + /*
> + * Set cpu divider based on the pre-computed array in
> + * order to have balanced step.
> + */
> + val |= divider[load_lvl] << ARMADA_37XX_NB_TBG_DIV_OFF;
> + mask |= (ARMADA_37XX_NB_TBG_DIV_MASK
> + << ARMADA_37XX_NB_TBG_DIV_OFF);
> +
> + /* Set VDD divider which is actually the load level. */
> + val |= load_lvl << ARMADA_37XX_NB_VDD_SEL_OFF;
> + mask |= (ARMADA_37XX_NB_VDD_SEL_MASK
> + << ARMADA_37XX_NB_VDD_SEL_OFF);
> +
> + val <<= offset;
> + mask <<= offset;
> +
> + regmap_update_bits(base, reg, mask, val);
> + }
> +
> + /*
> + * Set cpu clock source, for all the level we keep the same
> + * clock source that the one already configured. For this one
> + * we need to use the clock framework
> + */
> + parent = clk_get_parent(clk);
> + clk_set_parent(clk, parent);
> +}
> +
> +static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base)
> +{
> + unsigned int reg = ARMADA_37XX_NB_DYN_MOD,
> + mask = ARMADA_37XX_NB_DFS_EN;
> +
> + regmap_update_bits(base, reg, mask, 0);
> +}
> +
> +static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base)
> +{
> + unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD,
> + mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
> +
> + /* Start with the highest load (0) */
> + val = ARMADA_37XX_DVFS_LOAD_0;
> + regmap_update_bits(base, reg, mask, val);
> +
> + /* Now enable DVFS for the CPUs */
> + reg = ARMADA_37XX_NB_DYN_MOD;
> + mask = ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN |
> + ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN |
> + ARMADA_37XX_NB_DFS_EN;
> +
> + regmap_update_bits(base, reg, mask, mask);
> +}
> +
> +static int __init armada37xx_cpufreq_driver_init(void)
> +{
> + struct armada_37xx_dvfs *dvfs;
> + struct platform_device *pdev;
> + unsigned int cur_frequency;
> + struct regmap *nb_pm_base;
> + struct device *cpu_dev;
> + int load_lvl, ret;
> + struct clk *clk;
> +
> + nb_pm_base =
> + syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
> +
> + if (IS_ERR(nb_pm_base))
> + return -ENODEV;
> +
> + /* Before doing any configuration on the DVFS first, disable it */
> + armada37xx_cpufreq_disable_dvfs(nb_pm_base);
> +
> + /*
> + * On CPU 0 register the operating points supported (which are
> + * the nominal CPU frequency and full integer divisions of
> + * it).
> + */
> + cpu_dev = get_cpu_device(0);
> + if (!cpu_dev) {
> + dev_err(cpu_dev, "Cannot get CPU\n");
> + return -ENODEV;
> + }
> +
> + clk = clk_get(cpu_dev, 0);
> + if (IS_ERR(clk)) {
> + dev_err(cpu_dev, "Cannot get clock for CPU0\n");
> + return PTR_ERR(clk);
> + }
> +
> + /* Get nominal (current) CPU frequency */
> + cur_frequency = clk_get_rate(clk);
> + if (!cur_frequency) {
> + dev_err(cpu_dev, "Failed to get clock rate for CPU\n");
> + return -EINVAL;
> + }
> +
> + dvfs = armada_37xx_cpu_freq_info_get(cur_frequency);
> + if (!dvfs)
> + return -EINVAL;
> +
> + armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
> +
> + for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR;
> + load_lvl++) {
> + unsigned long freq = cur_frequency / dvfs->divider[load_lvl];
> +
> + ret = dev_pm_opp_add(cpu_dev, freq, 0);
> + if (ret) {
> + /* clean-up the already added opp before leaving */
Double space after /*
> + while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) {
> + freq = cur_frequency / dvfs->divider[load_lvl];
> + dev_pm_opp_remove(cpu_dev, freq);
> + }
> + return ret;
> + }
> + }
> +
> + /* Now that everything is setup, enable the DVFS at hardware level */
> + armada37xx_cpufreq_enable_dvfs(nb_pm_base);
> +
> + pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
> +
> + return PTR_ERR_OR_ZERO(pdev);
> +}
> +/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
> +late_initcall(armada37xx_cpufreq_driver_init);
> +
> +MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
> +MODULE_DESCRIPTION("Armada 37xx cpufreq driver");
> +MODULE_LICENSE("GPL");
I am not objecting to using double spaces at all these locations, its fine. Just
that I wanted to point it out in case it is not intentional.
--
viresh
^ permalink raw reply
* [PATCH 2/2] ARM: dts: sun8i: Add ADC routing
From: Chen-Yu Tsai @ 2017-12-14 3:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213123408.10422-3-mylene.josserand@free-electrons.com>
On Wed, Dec 13, 2017 at 8:34 PM, Myl?ne Josserand
<mylene.josserand@free-electrons.com> wrote:
> Add the ADC route between the analog and the digital parts
> of sun8i A33. Configure the MIC1 to use MBIAS and MIC2 to use HBIAS.
>
> Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
> ---
> arch/arm/boot/dts/sun8i-a33.dtsi | 10 +++++++++-
> 1 file changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi
> index 22660919bd08..1841eecd5993 100644
> --- a/arch/arm/boot/dts/sun8i-a33.dtsi
> +++ b/arch/arm/boot/dts/sun8i-a33.dtsi
> @@ -191,7 +191,15 @@
> simple-audio-card,aux-devs = <&codec_analog>;
> simple-audio-card,routing =
> "Left DAC", "AIF1 Slot 0 Left",
> - "Right DAC", "AIF1 Slot 0 Right";
> + "Right DAC", "AIF1 Slot 0 Right",
> + "AIF1 Slot 0 Left ADC", "Left ADC",
> + "AIF1 Slot 0 Right ADC", "Right ADC",
> + "Left ADC", "ADC",
> + "Right ADC", "ADC",
> + "Mic", "MBIAS",
> + "Headset Mic", "HBIAS",
> + "MIC1", "Mic",
> + "MIC2", "Headset Mic";
These entries are board level routing. They should be done in the
board dts files. Unfortunately device tree does not provide a way
to "append" entries to properties, which means one has to copy all
the preceding entries as well.
Also, you are not adding the "Mic" and "Headset Mic" widgets. A33
uses simple-card, which means these connection/board level widgets
must be added using simple-audio-card,widgets.
ChenYu
> status = "disabled";
>
> simple-audio-card,cpu {
> --
> 2.11.0
>
^ permalink raw reply
* [PATCH 2/3] reset: meson-axg: add compatible string for Meson-AXG SoC
From: Yixun Lan @ 2017-12-14 3:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513180898.9445.3.camel@pengutronix.de>
On 12/14/17 00:01, Philipp Zabel wrote:
> Hi Yixun,
>
> On Wed, 2017-12-13 at 22:07 +0800, Yixun Lan wrote:
>> Hi Philipp
>>
>> On 11/10/2017 04:46 PM, Yixun Lan wrote:
>>> Try to add compatible string explictly to support new Meson-AXG SoC.
>>>
>>> Signed-off-by: Yixun Lan <yixun.lan@amlogic.com>
>>> ---
>>> drivers/reset/reset-meson.c | 2 ++
>>> 1 file changed, 2 insertions(+)
>>>
>>> diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
>>> index c419a3753d00..93cbee1ae8ef 100644
>>> --- a/drivers/reset/reset-meson.c
>>> +++ b/drivers/reset/reset-meson.c
>>> @@ -139,6 +139,8 @@ static const struct of_device_id meson_reset_dt_ids[] = {
>>> .data = &meson_reset_meson8_ops, },
>>> { .compatible = "amlogic,meson-gxbb-reset",
>>> .data = &meson_reset_gx_ops, },
>>> + { .compatible = "amlogic,meson-axg-reset",
>>> + .data = &meson_reset_gx_ops, },
>>> { /* sentinel */ },
>>> };
>>>
>>>
>>
>> it's generally a ping to the status of these two patches[1], are they
>> ready to go? or do you have any comment? or do you want me to send
>> another version with Neil's Reviewed-by added[1]
>
> I forgot to update you on the status. I have put both patches on the
> reset/next branch with Neil's R-b, they are in linux-next:
>
> 0e5721f76252 ("reset: meson-axg: add compatible string for Meson-AXG SoC")
> c16292578ffa ("dt-bindings: reset: Add bindings for the Meson-AXG SoC Reset Controller")
>
> I'll include them with the next pull request.
>
Hi Philipp
great & thanks.
Hi Kevin:
could you take the DT part[1] via your tree, also with Neil's
Reviewed-by added? I've checked, it could apply cleanly to your
v4.16/dt64 branch
many thanks
Yixun
[1]
http://lists.infradead.org/pipermail/linux-amlogic/2017-November/005280.html
^ permalink raw reply
* [PATCH v4 03/15] dt-bindings: display: sun4i-drm: Add LVDS properties
From: Chen-Yu Tsai @ 2017-12-14 3:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <8b7042f5e85cc868ea802deba79a0c53ffbe6564.1512662253.git-series.maxime.ripard@free-electrons.com>
On Thu, Dec 7, 2017 at 11:58 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Some clocks and resets supposed to drive the LVDS logic in the display
> engine have been overlooked when the driver was first introduced.
>
> Add those additional resources to the binding, and we'll deal with the ABI
> stability in the code.
>
> Reviewed-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
^ permalink raw reply
* [PATCH v4 06/15] drm/sun4i: Force the mixer rate at 150MHz
From: Chen-Yu Tsai @ 2017-12-14 3:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <34f2c9d5c9ab48ead94253144a8e829cccfa4653.1512662253.git-series.maxime.ripard@free-electrons.com>
On Thu, Dec 7, 2017 at 11:58 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> It seems like the mixer can only run properly when clocked at 150MHz. In
> order to have something more robust than simply a fire-and-forget
> assigned-clocks-rate, let's put that in the code.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
> drivers/gpu/drm/sun4i/sun8i_mixer.c | 9 +++++++++
> drivers/gpu/drm/sun4i/sun8i_mixer.h | 3 +++
> 2 files changed, 12 insertions(+)
>
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> index 29ceeb016d72..ff235e3228ce 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> @@ -400,6 +400,14 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
> }
> clk_prepare_enable(mixer->mod_clk);
>
> + /*
> + * It seems that we need to enforce that rate for whatever
> + * reason for the mixer to be functional. Make sure it's the
> + * case.
> + */
> + if (mixer->cfg->mod_rate)
> + clk_set_rate(mixer->mod_clk, mixer->cfg->mod_rate);
> +
I think it might be better to set the rate first, then enable the clock.
This is sort of implied by the user manual saying "PLLs other than CPU
do not support DVFS". And it fits better with CLK_SET_RATE_GATE semantics,
if we ever adopt it.
Otherwise,
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> list_add_tail(&mixer->engine.list, &drv->engine_list);
>
> /* Reset the registers */
> @@ -474,6 +482,7 @@ static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
> .ui_num = 1,
> .scaler_mask = 0x3,
> .ccsc = 0,
> + .mod_rate = 150000000,
> };
>
> static const struct of_device_id sun8i_mixer_of_table[] = {
> diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
> index bc58040a88f9..f34e70c42adf 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
> +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
> @@ -121,12 +121,15 @@ struct de2_fmt_info {
> * Set value to 0 if this is first mixer or second mixer with VEP support.
> * Set value to 1 if this is second mixer without VEP support. Other values
> * are invalid.
> + * @mod_rate: module clock rate that needs to be set in order to have
> + * a functional block.
> */
> struct sun8i_mixer_cfg {
> int vi_num;
> int ui_num;
> int scaler_mask;
> int ccsc;
> + unsigned long mod_rate;
> };
>
> struct sun8i_mixer {
> --
> git-series 0.9.1
^ permalink raw reply
* [PATCH v3 08/15] drm/sun4i: Add LVDS support
From: Chen-Yu Tsai @ 2017-12-14 3:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171207122521.frv5zgaay3sgol6f@flea.lan>
On Thu, Dec 7, 2017 at 8:25 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Thu, Dec 07, 2017 at 02:05:47PM +0800, Chen-Yu Tsai wrote:
>> > +static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon,
>> > + const struct drm_encoder *encoder,
>> > + bool enabled)
>> > +{
>> > + if (enabled) {
>> > + u8 val;
>> > +
>> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
>> > + SUN4I_TCON0_LVDS_IF_EN,
>> > + SUN4I_TCON0_LVDS_IF_EN);
>> > +
>> > + regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
>> > + SUN4I_TCON0_LVDS_ANA0_C(2) |
>> > + SUN4I_TCON0_LVDS_ANA0_V(3) |
>> > + SUN4I_TCON0_LVDS_ANA0_PD(2) |
>> > + SUN4I_TCON0_LVDS_ANA0_EN_LDO);
>> > + udelay(2);
>> > +
>> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
>> > + SUN4I_TCON0_LVDS_ANA0_EN_MB,
>> > + SUN4I_TCON0_LVDS_ANA0_EN_MB);
>> > + udelay(2);
>> > +
>> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
>> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVC,
>> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVC);
>> > +
>> > + if (sun4i_tcon_get_pixel_depth(encoder) == 18)
>> > + val = 7;
>> > + else
>> > + val = 0xf;
>> > +
>> > + regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
>> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
>> > + SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val));
>>
>> I suggest changing the prefix of the macros of the analog bits to
>> SUN6I_TCON0_*. The register definitions and sequence do not apply
>> to the A10/A20. Furthermore you should add a comment saying this
>> doesn't apply to the A10/A20. In the future we might want to move
>> this part into a separate function, referenced by a function pointer
>> from the quirks structure.
>
> I'll change the bit field names and add a comment like you suggested.
>
>> > + } else {
>> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
>> > + SUN4I_TCON0_LVDS_IF_EN, 0);
>> > + }
>> > +}
>> > +
>> > void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>> > const struct drm_encoder *encoder,
>> > bool enabled)
>> > {
>> > + bool is_lvds = false;
>> > int channel;
>> >
>> > switch (encoder->encoder_type) {
>> > + case DRM_MODE_ENCODER_LVDS:
>> > + is_lvds = true;
>> > + /* Fallthrough */
>> > case DRM_MODE_ENCODER_NONE:
>> > channel = 0;
>> > break;
>> > @@ -84,10 +171,16 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
>> > return;
>> > }
>> >
>> > + if (is_lvds && !enabled)
>> > + sun4i_tcon_lvds_set_status(tcon, encoder, false);
>> > +
>> > regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
>> > SUN4I_TCON_GCTL_TCON_ENABLE,
>> > enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
>> >
>> > + if (is_lvds && enabled)
>> > + sun4i_tcon_lvds_set_status(tcon, encoder, true);
>> > +
>> > sun4i_tcon_channel_set_status(tcon, channel, enabled);
>> > }
>> >
>> > @@ -170,6 +263,78 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
>> > SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
>> > }
>> >
>> > +static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
>> > + const struct drm_encoder *encoder,
>> > + const struct drm_display_mode *mode)
>> > +{
>> > + unsigned int bp;
>> > + u8 clk_delay;
>> > + u32 reg, val = 0;
>> > +
>> > + tcon->dclk_min_div = 7;
>> > + tcon->dclk_max_div = 7;
>> > + sun4i_tcon0_mode_set_common(tcon, mode);
>> > +
>> > + /* Adjust clock delay */
>> > + clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
>> > + regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
>> > + SUN4I_TCON0_CTL_CLK_DELAY_MASK,
>> > + SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
>> > +
>> > + /*
>> > + * This is called a backporch in the register documentation,
>> > + * but it really is the back porch + hsync
>> > + */
>> > + bp = mode->crtc_htotal - mode->crtc_hsync_start;
>> > + DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
>> > + mode->crtc_htotal, bp);
>> > +
>> > + /* Set horizontal display timings */
>> > + regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
>> > + SUN4I_TCON0_BASIC1_H_TOTAL(mode->htotal) |
>> > + SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
>> > +
>> > + /*
>> > + * This is called a backporch in the register documentation,
>> > + * but it really is the back porch + hsync
>> > + */
>> > + bp = mode->crtc_vtotal - mode->crtc_vsync_start;
>> > + DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
>> > + mode->crtc_vtotal, bp);
>> > +
>> > + /* Set vertical display timings */
>> > + regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
>> > + SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
>> > + SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
>>
>> Can we move the above to a common function?
>
> Until we have DSI support figured out I'd rather not do too much of
> consolidation. We know already a few things are going to change there
> (like the clk_delay), but it's not clear yet how much.
>
>> > + /* Map output pins to channel 0 */
>> > + regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
>> > + SUN4I_TCON_GCTL_IOMAP_MASK,
>> > + SUN4I_TCON_GCTL_IOMAP_TCON0);
>> > +
>> > + /* Enable the output on the pins */
>> > + regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
>>
>> Is this still needed? You are no longer using the TCON LCD pins
>> with LVDS.
>
> We do. It's a separate function of the pins, but it's the same pins.
OK. I assume you've tried it without setting it and it failed?
I just assume that these refer to the TCON LCD output, whereas
LVDS looks like a separate module and function, and shouldn't
need it.
ChenYu
>> > static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
>> > .has_channel_1 = true,
>> > + .has_lvds_pll = true,
>>
>> The A31s does not have MIPI.
>
> I'll change that.
>
> Thanks!
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
^ permalink raw reply
* [PATCH v4 08/15] drm/sun4i: Add LVDS support
From: Chen-Yu Tsai @ 2017-12-14 3:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <b64644e9397ec437ec4d3d16be585b22086cf615.1512662253.git-series.maxime.ripard@free-electrons.com>
On Thu, Dec 7, 2017 at 11:58 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The TCON supports the LVDS interface to output to a panel or a bridge.
> Let's add support for it.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
> drivers/gpu/drm/sun4i/Makefile | 1 +-
> drivers/gpu/drm/sun4i/sun4i_lvds.c | 177 ++++++++++++++++++++++-
> drivers/gpu/drm/sun4i/sun4i_lvds.h | 18 ++-
> drivers/gpu/drm/sun4i/sun4i_tcon.c | 242 +++++++++++++++++++++++++++++-
> drivers/gpu/drm/sun4i/sun4i_tcon.h | 29 ++++-
> 5 files changed, 465 insertions(+), 2 deletions(-)
> create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.c
> create mode 100644 drivers/gpu/drm/sun4i/sun4i_lvds.h
>
[...]
> diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.h b/drivers/gpu/drm/sun4i/sun4i_lvds.h
> new file mode 100644
> index 000000000000..1b8fad4b82c3
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.h
> @@ -0,0 +1,18 @@
> +/*
> + * Copyright (C) 2015 NextThing Co
> + * Copyright (C) 2015-2017 Free Electrons
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + */
SPDX?
> +
> +#ifndef _SUN4I_LVDS_H_
> +#define _SUN4I_LVDS_H_
> +
> +int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon);
> +
> +#endif /* _SUN4I_LVDS_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 46e28ca1f676..777c7348d0cf 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
[...]
> @@ -698,6 +873,54 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
> return ret;
> }
>
> + /*
> + * This can only be made optional since we've had DT nodes
> + * without the LVDS reset properties.
> + *
> + * If the property is missing, just disable LVDS, and print a
> + * warning.
> + */
> + tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds");
> + if (IS_ERR(tcon->lvds_rst)) {
> + dev_err(dev, "Couldn't get our reset line\n");
> + return PTR_ERR(tcon->lvds_rst);
> + } else if (tcon->lvds_rst) {
> + has_lvds_rst = true;
> + reset_control_reset(tcon->lvds_rst);
> + } else {
> + has_lvds_rst = false;
> + }
> +
> + /*
> + * This can only be made optional since we've had DT nodes
> + * without the LVDS reset properties.
> + *
> + * If the property is missing, just disable LVDS, and print a
> + * warning.
> + */
> + if (tcon->quirks->has_lvds_pll) {
Care to change these names to match the DT property as well?
[...]
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
> index bd3ad7684870..23db06cdc461 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
[...]
> @@ -149,6 +173,7 @@ struct sun4i_tcon;
>
> struct sun4i_tcon_quirks {
> bool has_channel_1; /* a33 does not have channel 1 */
> + bool has_lvds_pll; /* Can we mux the LVDS clock to a PLL? */
This could then read "Does LVDS clock have parent other than TCON clock?"
Otherwise,
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Also see my other (late) reply to the previous version.
> bool needs_de_be_mux; /* sun6i needs mux to select backend */
>
> /* callback to handle tcon muxing options */
> @@ -167,6 +192,9 @@ struct sun4i_tcon {
> struct clk *sclk0;
> struct clk *sclk1;
>
> + /* Possible mux for the LVDS clock */
> + struct clk *lvds_pll;
> +
> /* Pixel clock */
> struct clk *dclk;
> u8 dclk_max_div;
> @@ -174,6 +202,7 @@ struct sun4i_tcon {
>
> /* Reset control */
> struct reset_control *lcd_rst;
> + struct reset_control *lvds_rst;
>
> struct drm_panel *panel;
>
> --
> git-series 0.9.1
^ permalink raw reply
* [PATCH v4 13/15] ARM: dts: sun8i: a83t: Add the PWM pin group
From: Chen-Yu Tsai @ 2017-12-14 3:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <b58547cd03f88c65162f362361023b44a4b6fc89.1512662253.git-series.maxime.ripard@free-electrons.com>
On Thu, Dec 7, 2017 at 11:58 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The A83T has a PWM that can be output from the SoC. Let's add a pinctrl
> group for it.
>
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Might as well just squash this with patch 11, and enforce it by default.
ChenYu
^ permalink raw reply
* [PATCH v2 0/3] ARM: sun8i: a83t: Add support for I2S and I2C
From: Chen-Yu Tsai @ 2017-12-14 4:23 UTC (permalink / raw)
To: linux-arm-kernel
Hi everyone,
This is v2 of my A83T I2S and I2C support series.
Changes since v1:
- Dropped ASoC patch that was merged
- Added SoC-specific compatible strings for I2C controllers
- Added Maxime's Acked-by
This series adds support for I2S and I2C on the Allwinner A83T SoC.
The I2S controllers are similar to the ones found on the A31. However
the TX FIFO and interrupt status registers were swapped around. This
seems to be a recurring theme for the audio related hardware blocks.
Patch 1 adds device nodes and default pinmux settings for the I2S
controllers.
Patch 2 adds device nodes and default pinmux settings for the I2C
controllers.
Patch 3 is an example of a PCM5122 codec tied to I2C2 and I2S1 over
the GPIO header of the Banana Pi M3. This patch should not be merged.
Please have a look.
Regards
ChenYu
Chen-Yu Tsai (3):
ARM: dts: sun8i: a83t: Add I2S controller device nodes
ARM: dts: sun8i: a83t: Add I2C device nodes and pinmux settings
[DO NOT MERGE] ARM: dts: sun8i: a83t: bpi-m3: Enable PCM5122 codec
with I2S1
arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts | 33 +++++++++
arch/arm/boot/dts/sun8i-a83t.dtsi | 102 +++++++++++++++++++++++++++
2 files changed, 135 insertions(+)
--
2.15.0
^ permalink raw reply
* [PATCH v2 1/3] ARM: dts: sun8i: a83t: Add I2S controller device nodes
From: Chen-Yu Tsai @ 2017-12-14 4:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171214042350.29469-1-wens@csie.org>
The A83T has 3 I2S controllers. The first is multiplexed with the TDM
controller. The pins are generally connected to the codec side of the
AXP81x PMIC/codec/RTC chip. The second is free for other uses. The
third only supports output, and is connected internally to the HDMI
controller for HDMI audio output.
This patch adds device nodes for the controllers, and a default pinmux
setting for the second controller.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun8i-a83t.dtsi | 47 +++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index a384b766f3dc..354cb4b48f47 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -348,6 +348,12 @@
drive-strength = <40>;
};
+ i2s1_pins: i2s1-pins {
+ /* I2S1 does not have external MCLK pin */
+ pins = "PG10", "PG11", "PG12", "PG13";
+ function = "i2s1";
+ };
+
mmc0_pins: mmc0-pins {
pins = "PF0", "PF1", "PF2",
"PF3", "PF4", "PF5";
@@ -430,6 +436,47 @@
status = "disabled";
};
+ i2s0: i2s at 1c22000 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun8i-a83t-i2s";
+ reg = <0x01c22000 0x400>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S0>, <&ccu CLK_I2S0>;
+ clock-names = "apb", "mod";
+ dmas = <&dma 3>, <&dma 3>;
+ resets = <&ccu RST_BUS_I2S0>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ i2s1: i2s at 1c22400 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun8i-a83t-i2s";
+ reg = <0x01c22400 0x400>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S1>, <&ccu CLK_I2S1>;
+ clock-names = "apb", "mod";
+ dmas = <&dma 4>, <&dma 4>;
+ resets = <&ccu RST_BUS_I2S1>;
+ dma-names = "rx", "tx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s1_pins>;
+ status = "disabled";
+ };
+
+ i2s2: i2s at 1c22800 {
+ #sound-dai-cells = <0>;
+ compatible = "allwinner,sun8i-a83t-i2s";
+ reg = <0x01c22800 0x400>;
+ interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S2>, <&ccu CLK_I2S2>;
+ clock-names = "apb", "mod";
+ dmas = <&dma 27>;
+ resets = <&ccu RST_BUS_I2S2>;
+ dma-names = "tx";
+ status = "disabled";
+ };
+
uart0: serial at 1c28000 {
compatible = "snps,dw-apb-uart";
reg = <0x01c28000 0x400>;
--
2.15.0
^ permalink raw reply related
* [PATCH v2 2/3] ARM: dts: sun8i: a83t: Add I2C device nodes and pinmux settings
From: Chen-Yu Tsai @ 2017-12-14 4:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171214042350.29469-1-wens@csie.org>
The A83T has 3 I2C controllers under the standard bus. There is one
more in the R_ block section. The pin functions for the 3 controllers
are on PH 0~6. I2C2 can also be used on pins PE14 and PE15, but these
pins can also mux the CSI (camera sensor interface) controller's
embedded I2C controller. The latter seems to be preferred in the
reference designs for I2C camera sensor access, freeing I2C2 for other
uses.
This patch adds device nodes for the three standard I2C controllers,
as well as pinmux settings for the PH pins. For I2C0 and I2C1, since
they only have one possible setting, just set them by default.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/boot/dts/sun8i-a83t.dtsi | 55 +++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index 354cb4b48f47..de5119a2a91c 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -348,6 +348,21 @@
drive-strength = <40>;
};
+ i2c0_pins: i2c0-pins {
+ pins = "PH0", "PH1";
+ function = "i2c0";
+ };
+
+ i2c1_pins: i2c1-pins {
+ pins = "PH2", "PH3";
+ function = "i2c1";
+ };
+
+ i2c2_ph_pins: i2c2-ph-pins {
+ pins = "PH4", "PH5";
+ function = "i2c2";
+ };
+
i2s1_pins: i2s1-pins {
/* I2S1 does not have external MCLK pin */
pins = "PG10", "PG11", "PG12", "PG13";
@@ -499,6 +514,46 @@
status = "disabled";
};
+ i2c0: i2c at 1c2ac00 {
+ compatible = "allwinner,sun8i-a83t-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x01c2ac00 0x400>;
+ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C0>;
+ resets = <&ccu RST_BUS_I2C0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c1: i2c at 1c2b000 {
+ compatible = "allwinner,sun8i-a83t-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x01c2b000 0x400>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C1>;
+ resets = <&ccu RST_BUS_I2C1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c2: i2c at 1c2b400 {
+ compatible = "allwinner,sun8i-a83t-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x01c2b400 0x400>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C2>;
+ resets = <&ccu RST_BUS_I2C2>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
emac: ethernet at 1c30000 {
compatible = "allwinner,sun8i-a83t-emac";
syscon = <&syscon>;
--
2.15.0
^ permalink raw reply related
* [PATCH v2 3/3] [DO NOT MERGE] ARM: dts: sun8i: a83t: bpi-m3: Enable PCM5122 codec with I2S1
From: Chen-Yu Tsai @ 2017-12-14 4:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171214042350.29469-1-wens@csie.org>
This patch enables a PiFi DAC+ V2.0, which is a PCM5122-based audio
output DAC add-on board for the Raspberry Pi B+ and later, connected
to the GPIO header of the Bananapi M3 via jumper cables. The power,
ground, and I2C pins are in the same position, but the I2S ones are
not.
The I2C controller used is I2C2, while the I2S controller is I2S1.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts | 33 ++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts b/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts
index 6550bf0e594b..a9a208ebda12 100644
--- a/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts
+++ b/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts
@@ -70,6 +70,23 @@
gpio = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */
};
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "PiFi DAC+ v2.0";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,mclk-fs = <512>;
+ simple-audio-card,frame-master = <&link_cpu>;
+ simple-audio-card,bitclock-master = <&link_cpu>;
+
+ link_cpu: simple-audio-card,cpu {
+ sound-dai = <&i2s1>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&pcm5122>;
+ };
+ };
+
wifi_pwrseq: wifi_pwrseq {
compatible = "mmc-pwrseq-simple";
clocks = <&ac100_rtc 1>;
@@ -100,6 +117,22 @@
status = "okay";
};
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_ph_pins>;
+ status = "okay";
+
+ pcm5122: pcm5122 at 4d {
+ #sound-dai-cells = <0>;
+ compatible = "ti,pcm5122";
+ reg = <0x4d>;
+ };
+};
+
+&i2s1 {
+ status = "okay";
+};
+
&mdio {
rgmii_phy: ethernet-phy at 1 {
compatible = "ethernet-phy-ieee802.3-c22";
--
2.15.0
^ permalink raw reply related
* [PATCH 1/4] cpufreq: ti-cpufreq: Convert to module_platform_driver
From: Viresh Kumar @ 2017-12-14 4:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213203358.20839-2-d-gerlach@ti.com>
On 13-12-17, 14:33, Dave Gerlach wrote:
> ti-cpufreq will be responsible for calling dev_pm_opp_set_regulators on
> platforms that require AVS and ABB regulator support so we must be
> able to defer probe if regulators are not yet available, so change
> ti-cpufreq to be a module_platform_driver to allow for probe defer.
>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
> drivers/cpufreq/ti-cpufreq.c | 23 +++++++++++++++++++++--
> 1 file changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
> index 923317f03b4b..b1c230a1e2aa 100644
> --- a/drivers/cpufreq/ti-cpufreq.c
> +++ b/drivers/cpufreq/ti-cpufreq.c
> @@ -17,6 +17,7 @@
> #include <linux/cpu.h>
> #include <linux/io.h>
> #include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> #include <linux/init.h>
> #include <linux/of.h>
> #include <linux/of_platform.h>
> @@ -195,7 +196,7 @@ static const struct of_device_id ti_cpufreq_of_match[] = {
> {},
> };
>
> -static int ti_cpufreq_init(void)
> +static int ti_cpufreq_probe(struct platform_device *pdev)
> {
> u32 version[VERSION_COUNT];
> struct device_node *np;
> @@ -269,4 +270,22 @@ static int ti_cpufreq_init(void)
>
> return ret;
> }
> -device_initcall(ti_cpufreq_init);
> +
> +static int ti_cpufreq_init(void)
> +{
> + platform_device_register_simple("ti-cpufreq", -1, NULL, 0);
> + return 0;
> +}
> +module_init(ti_cpufreq_init);
> +
> +static struct platform_driver ti_cpufreq_driver = {
> + .probe = ti_cpufreq_probe,
> + .driver = {
> + .name = "ti-cpufreq",
> + },
> +};
> +module_platform_driver(ti_cpufreq_driver);
> +
> +MODULE_DESCRIPTION("TI CPUFreq/OPP hw-supported driver");
> +MODULE_AUTHOR("Dave Gerlach <d-gerlach@ti.com>");
> +MODULE_LICENSE("GPL v2");
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* [PATCH 2/4] cpufreq: ti-cpufreq: Add support for multiple regulators
From: Viresh Kumar @ 2017-12-14 4:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213203358.20839-3-d-gerlach@ti.com>
On 13-12-17, 14:33, Dave Gerlach wrote:
> Some platforms, like those in the DRA7 and AM57 families, require the
> scaling of multiple regulators in order to properly support higher OPPs.
> Let the ti-cpufreq driver determine when this is required and pass the
> appropriate regulator names to the OPP core so that they can be properly
> managed.
>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
> drivers/cpufreq/ti-cpufreq.c | 28 ++++++++++++++++++++++++----
> 1 file changed, 24 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
> index b1c230a1e2aa..a099b7bf74cd 100644
> --- a/drivers/cpufreq/ti-cpufreq.c
> +++ b/drivers/cpufreq/ti-cpufreq.c
> @@ -51,6 +51,7 @@ struct ti_cpufreq_soc_data {
> unsigned long efuse_mask;
> unsigned long efuse_shift;
> unsigned long rev_offset;
> + bool multi_regulator;
> };
>
> struct ti_cpufreq_data {
> @@ -58,6 +59,7 @@ struct ti_cpufreq_data {
> struct device_node *opp_node;
> struct regmap *syscon;
> const struct ti_cpufreq_soc_data *soc_data;
> + struct opp_table *opp_table;
> };
>
> static unsigned long amx3_efuse_xlate(struct ti_cpufreq_data *opp_data,
> @@ -96,6 +98,7 @@ static struct ti_cpufreq_soc_data am3x_soc_data = {
> .efuse_offset = 0x07fc,
> .efuse_mask = 0x1fff,
> .rev_offset = 0x600,
> + .multi_regulator = false,
> };
>
> static struct ti_cpufreq_soc_data am4x_soc_data = {
> @@ -104,6 +107,7 @@ static struct ti_cpufreq_soc_data am4x_soc_data = {
> .efuse_offset = 0x0610,
> .efuse_mask = 0x3f,
> .rev_offset = 0x600,
> + .multi_regulator = false,
> };
>
> static struct ti_cpufreq_soc_data dra7_soc_data = {
> @@ -112,6 +116,7 @@ static struct ti_cpufreq_soc_data dra7_soc_data = {
> .efuse_mask = 0xf80000,
> .efuse_shift = 19,
> .rev_offset = 0x204,
> + .multi_regulator = true,
> };
>
> /**
> @@ -201,7 +206,9 @@ static int ti_cpufreq_probe(struct platform_device *pdev)
> u32 version[VERSION_COUNT];
> struct device_node *np;
> const struct of_device_id *match;
> + struct opp_table *ti_opp_table;
> struct ti_cpufreq_data *opp_data;
> + const char * const reg_names[] = {"vdd", "vbb"};
> int ret;
>
> np = of_find_node_by_path("/");
> @@ -248,16 +255,29 @@ static int ti_cpufreq_probe(struct platform_device *pdev)
> if (ret)
> goto fail_put_node;
>
> - ret = PTR_ERR_OR_ZERO(dev_pm_opp_set_supported_hw(opp_data->cpu_dev,
> - version, VERSION_COUNT));
> - if (ret) {
> + ti_opp_table = dev_pm_opp_set_supported_hw(opp_data->cpu_dev,
> + version, VERSION_COUNT);
> + if (IS_ERR(ti_opp_table)) {
> dev_err(opp_data->cpu_dev,
> "Failed to set supported hardware\n");
> + ret = PTR_ERR(ti_opp_table);
> goto fail_put_node;
> }
>
> - of_node_put(opp_data->opp_node);
> + opp_data->opp_table = ti_opp_table;
> +
> + if (opp_data->soc_data->multi_regulator) {
> + ti_opp_table = dev_pm_opp_set_regulators(opp_data->cpu_dev,
> + reg_names,
> + ARRAY_SIZE(reg_names));
> + if (IS_ERR(ti_opp_table)) {
> + dev_pm_opp_put_supported_hw(opp_data->opp_table);
> + ret = PTR_ERR(ti_opp_table);
> + goto fail_put_node;
> + }
> + }
>
> + of_node_put(opp_data->opp_node);
> register_cpufreq_dt:
> platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* [PATCH 4/4] PM / OPP: Add ti-opp-supply driver
From: Viresh Kumar @ 2017-12-14 4:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213203358.20839-5-d-gerlach@ti.com>
On 13-12-17, 14:33, Dave Gerlach wrote:
> Introduce a ti-opp-supply driver that will use new multiple regulator
> support that is part of the OPP core This is needed on TI platforms like
> DRA7/AM57 in order to control both CPU regulator and Adaptive Body Bias
> (ABB) regulator. These regulators must be scaled in sequence during an
> OPP transition depending on whether or not the frequency is being scaled
> up or down.
>
> This driver also implements AVS Class0 for these parts by looking up the
> required values from registers in the SoC and programming adjusted
> optimal voltage values for each OPP.
>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
> drivers/opp/Makefile | 1 +
> drivers/opp/ti-opp-supply.c | 428 ++++++++++++++++++++++++++++++++++++++++++++
Why is this added as a separate driver and not part of the same ti-cpufreq.c
file?
> 2 files changed, 429 insertions(+)
> create mode 100644 drivers/opp/ti-opp-supply.c
>
> diff --git a/drivers/opp/Makefile b/drivers/opp/Makefile
> index e70ceb406fe9..6ce6aefacc81 100644
> --- a/drivers/opp/Makefile
> +++ b/drivers/opp/Makefile
> @@ -2,3 +2,4 @@ ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
> obj-y += core.o cpu.o
> obj-$(CONFIG_OF) += of.o
> obj-$(CONFIG_DEBUG_FS) += debugfs.o
> +obj-$(CONFIG_ARM_TI_CPUFREQ) += ti-opp-supply.o
> diff --git a/drivers/opp/ti-opp-supply.c b/drivers/opp/ti-opp-supply.c
> new file mode 100644
> index 000000000000..73d795c90b79
> --- /dev/null
> +++ b/drivers/opp/ti-opp-supply.c
> @@ -0,0 +1,428 @@
> +/*
> + * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/
> + * Nishanth Menon <nm@ti.com>
> + * Dave Gerlach <d-gerlach@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
Please use the new SPDX format for licenses.
> + * TI OPP supply driver that provides override into the regulator control
> + * for generic opp core to handle devices with ABB regulator and/or
> + * SmartReflex Class0.
> + */
> +#include <linux/clk.h>
> +#include <linux/cpufreq.h>
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/notifier.h>
> +#include <linux/of_device.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_opp.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/slab.h>
> +
> +/**
> + * struct ti_opp_supply_optimum_voltage_table - optimized voltage table
> + * @reference_uv: reference voltage (usually Nominal voltage)
> + * @optimized_uv: Optimized voltage from efuse
> + */
> +struct ti_opp_supply_optimum_voltage_table {
> + unsigned int reference_uv;
> + unsigned int optimized_uv;
> +};
> +
> +/**
> + * struct ti_opp_supply_data - OMAP specific opp supply data
> + * @vdd_table: Optimized voltage mapping table
> + * @num_vdd_table: number of entries in vdd_table
> + * @vdd_absolute_max_voltage_uv: absolute maximum voltage in UV for the supply
> + */
> +struct ti_opp_supply_data {
> + struct ti_opp_supply_optimum_voltage_table *vdd_table;
> + u32 num_vdd_table;
> + u32 vdd_absolute_max_voltage_uv;
> +};
> +
> +static struct ti_opp_supply_data opp_data;
> +
> +/**
> + * struct ti_opp_supply_of_data - device tree match data
> + * @flags: specific type of opp supply
> + * @efuse_voltage_mask: mask required for efuse register representing voltage
> + * @efuse_voltage_uv: Are the efuse entries in micro-volts? if not, assume
> + * milli-volts.
> + */
> +struct ti_opp_supply_of_data {
> +#define OPPDM_EFUSE_CLASS0_OPTIMIZED_VOLTAGE BIT(1)
> +#define OPPDM_HAS_NO_ABB BIT(2)
> + const u8 flags;
> + const u32 efuse_voltage_mask;
> + const bool efuse_voltage_uv;
> +};
> +
> +/**
> + * _store_optimized_voltages() - store optimized voltages
> + * @dev: ti opp supply device for which we need to store info
> + * @data: data specific to the device
> + *
> + * Picks up efuse based optimized voltages for VDD unique per device and
> + * stores it in internal data structure for use during transition requests.
> + *
> + * Return: If successful, 0, else appropriate error value.
> + */
> +static int _store_optimized_voltages(struct device *dev,
> + struct ti_opp_supply_data *data)
> +{
> + void __iomem *base;
> + struct property *prop;
> + struct resource *res;
> + const __be32 *val;
> + int proplen, i;
> + int ret = 0;
> + struct ti_opp_supply_optimum_voltage_table *table;
> + const struct ti_opp_supply_of_data *of_data = dev_get_drvdata(dev);
> +
> + /* pick up Efuse based voltages */
> + res = platform_get_resource(to_platform_device(dev), IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(dev, "Unable to get IO resource\n");
> + ret = -ENODEV;
> + goto out_map;
> + }
> +
> + base = ioremap_nocache(res->start, resource_size(res));
> + if (!base) {
> + dev_err(dev, "Unable to map Efuse registers\n");
> + ret = -ENOMEM;
> + goto out_map;
> + }
> +
> + /* Fetch efuse-settings. */
> + prop = of_find_property(dev->of_node, "ti,efuse-settings", NULL);
> + if (!prop) {
> + dev_err(dev, "No 'ti,efuse-settings' property found\n");
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + proplen = prop->length / sizeof(int);
> + data->num_vdd_table = proplen / 2;
> + /* Verify for corrupted OPP entries in dt */
> + if (data->num_vdd_table * 2 * sizeof(int) != prop->length) {
> + dev_err(dev, "Invalid 'ti,efuse-settings'\n");
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + ret = of_property_read_u32(dev->of_node, "ti,absolute-max-voltage-uv",
> + &data->vdd_absolute_max_voltage_uv);
> + if (ret) {
> + dev_err(dev, "ti,absolute-max-voltage-uv is missing\n");
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + table = kzalloc(sizeof(*data->vdd_table) *
> + data->num_vdd_table, GFP_KERNEL);
> + if (!table) {
> + ret = -ENOMEM;
> + goto out;
> + }
> + data->vdd_table = table;
> +
> + val = prop->value;
> + for (i = 0; i < data->num_vdd_table; i++, table++) {
> + u32 efuse_offset;
> + u32 tmp;
> +
> + table->reference_uv = be32_to_cpup(val++);
> + efuse_offset = be32_to_cpup(val++);
> +
> + tmp = readl(base + efuse_offset);
> + tmp &= of_data->efuse_voltage_mask;
> + tmp >>= __ffs(of_data->efuse_voltage_mask);
> +
> + table->optimized_uv = of_data->efuse_voltage_uv ? tmp :
> + tmp * 1000;
> +
> + dev_dbg(dev, "[%d] efuse=0x%08x volt_table=%d vset=%d\n",
> + i, efuse_offset, table->reference_uv,
> + table->optimized_uv);
> +
> + /*
> + * Some older samples might not have optimized efuse
> + * Use reference voltage for those - just add debug message
> + * for them.
> + */
> + if (!table->optimized_uv) {
> + dev_dbg(dev, "[%d] efuse=0x%08x volt_table=%d:vset0\n",
> + i, efuse_offset, table->reference_uv);
> + table->optimized_uv = table->reference_uv;
> + }
> + }
> +out:
> + iounmap(base);
> +out_map:
> + return ret;
> +}
> +
> +/**
> + * _free_optimized_voltages() - free resources for optvoltages
> + * @dev: device for which we need to free info
> + * @data: data specific to the device
> + */
> +static void _free_optimized_voltages(struct device *dev,
> + struct ti_opp_supply_data *data)
> +{
> + kfree(data->vdd_table);
> + data->vdd_table = NULL;
> + data->num_vdd_table = 0;
> +}
> +
> +/**
> + * _get_optimal_vdd_voltage() - Finds optimal voltage for the supply
> + * @dev: device for which we need to find info
> + * @data: data specific to the device
> + * @reference_uv: reference voltage (OPP voltage) for which we need value
> + *
> + * Return: if a match is found, return optimized voltage, else return
> + * reference_uv, also return reference_uv if no optimization is needed.
> + */
> +static int _get_optimal_vdd_voltage(struct device *dev,
> + struct ti_opp_supply_data *data,
> + int reference_uv)
> +{
> + int i;
> + struct ti_opp_supply_optimum_voltage_table *table;
> +
> + if (!data->num_vdd_table)
> + return reference_uv;
> +
> + table = data->vdd_table;
> + if (!table)
> + return -EINVAL;
> +
> + /* Find a exact match - this list is usually very small */
> + for (i = 0; i < data->num_vdd_table; i++, table++)
> + if (table->reference_uv == reference_uv)
> + return table->optimized_uv;
> +
> + /* IF things are screwed up, we'd make a mess on console.. ratelimit */
> + dev_err_ratelimited(dev, "%s: Failed optimized voltage match for %d\n",
> + __func__, reference_uv);
> + return reference_uv;
> +}
> +
> +static int _opp_set_voltage(struct device *dev,
> + struct dev_pm_opp_supply *supply,
> + int new_target_uv, struct regulator *reg,
> + char *reg_name)
> +{
> + int ret;
> + unsigned long vdd_uv, uv_max;
> +
> + if (new_target_uv)
> + vdd_uv = new_target_uv;
> + else
> + vdd_uv = supply->u_volt;
> +
> + /*
> + * If we do have an absolute max voltage specified, then we should
> + * use that voltage instead to allow for cases where the voltage rails
> + * are ganged (example if we set the max for an opp as 1.12v, and
> + * the absolute max is 1.5v, for another rail to get 1.25v, it cannot
> + * be achieved if the regulator is constrainted to max of 1.12v, even
> + * if it can function at 1.25v
> + */
> + if (opp_data.vdd_absolute_max_voltage_uv)
> + uv_max = opp_data.vdd_absolute_max_voltage_uv;
> + else
> + uv_max = supply->u_volt_max;
> +
> + if (vdd_uv > uv_max ||
> + vdd_uv < supply->u_volt_min ||
> + supply->u_volt_min > uv_max) {
> + dev_warn(dev,
> + "Invalid range voltages [Min:%lu target:%lu Max:%lu]\n",
> + supply->u_volt_min, vdd_uv, uv_max);
> + return -EINVAL;
> + }
> +
> + dev_dbg(dev, "%s scaling to %luuV[min %luuV max %luuV]\n", reg_name,
> + vdd_uv, supply->u_volt_min,
> + uv_max);
> +
> + ret = regulator_set_voltage_triplet(reg,
> + supply->u_volt_min,
> + vdd_uv,
> + uv_max);
> + if (ret) {
> + dev_err(dev, "%s failed for %luuV[min %luuV max %luuV]\n",
> + reg_name, vdd_uv, supply->u_volt_min,
> + uv_max);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * ti_opp_supply_set_opp() - do the opp supply transition
> + * @data: information on regulators and new and old opps provided by
> + * opp core to use in transition
> + *
> + * Return: If successful, 0, else appropriate error value.
> + */
> +int ti_opp_supply_set_opp(struct dev_pm_set_opp_data *data)
> +{
> + struct dev_pm_opp_supply *old_supply_vdd = &data->old_opp.supplies[0];
> + struct dev_pm_opp_supply *old_supply_vbb = &data->old_opp.supplies[1];
> + struct dev_pm_opp_supply *new_supply_vdd = &data->new_opp.supplies[0];
> + struct dev_pm_opp_supply *new_supply_vbb = &data->new_opp.supplies[1];
> + struct device *dev = data->dev;
> + unsigned long old_freq = data->old_opp.rate, freq = data->new_opp.rate;
> + struct clk *clk = data->clk;
> + struct regulator *vdd_reg = data->regulators[0];
> + struct regulator *vbb_reg = data->regulators[1];
> + int vdd_uv;
> + int ret;
> +
> + vdd_uv = _get_optimal_vdd_voltage(dev, &opp_data,
> + new_supply_vbb->u_volt);
> +
> + /* Scaling up? Scale voltage before frequency */
> + if (freq > old_freq) {
> + ret = _opp_set_voltage(dev, new_supply_vdd, vdd_uv, vdd_reg,
> + "vdd");
> + if (ret)
> + goto restore_voltage;
> +
> + ret = _opp_set_voltage(dev, new_supply_vbb, 0, vbb_reg, "vbb");
> + if (ret)
> + goto restore_voltage;
> + }
> +
> + /* Change frequency */
> + dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n",
> + __func__, old_freq, freq);
> +
> + ret = clk_set_rate(clk, freq);
> + if (ret) {
> + dev_err(dev, "%s: failed to set clock rate: %d\n", __func__,
> + ret);
> + goto restore_voltage;
> + }
> +
> + /* Scaling down? Scale voltage after frequency */
> + if (freq < old_freq) {
> + ret = _opp_set_voltage(dev, new_supply_vbb, 0, vbb_reg, "vbb");
> + if (ret)
> + goto restore_freq;
> +
> + ret = _opp_set_voltage(dev, new_supply_vdd, vdd_uv, vdd_reg,
> + "vdd");
> + if (ret)
> + goto restore_freq;
> + }
> +
> + return 0;
> +
> +restore_freq:
> + ret = clk_set_rate(clk, old_freq);
> + if (ret)
> + dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
> + __func__, old_freq);
> +restore_voltage:
> + /* This shouldn't harm even if the voltages weren't updated earlier */
> + if (old_supply_vdd->u_volt) {
> + ret = _opp_set_voltage(dev, old_supply_vbb, 0, vbb_reg, "vbb");
> + if (ret)
> + return ret;
> +
> + ret = _opp_set_voltage(dev, old_supply_vdd, 0, vdd_reg,
> + "vdd");
> + if (ret)
> + return ret;
> + }
> +
> + return ret;
> +}
> +
> +static const struct ti_opp_supply_of_data omap_generic_of_data = {
> +};
> +
> +static const struct ti_opp_supply_of_data omap_omap5_of_data = {
> + .flags = OPPDM_EFUSE_CLASS0_OPTIMIZED_VOLTAGE,
> + .efuse_voltage_mask = 0xFFF,
> + .efuse_voltage_uv = false,
> +};
> +
> +static const struct ti_opp_supply_of_data omap_omap5core_of_data = {
> + .flags = OPPDM_EFUSE_CLASS0_OPTIMIZED_VOLTAGE | OPPDM_HAS_NO_ABB,
> + .efuse_voltage_mask = 0xFFF,
> + .efuse_voltage_uv = false,
> +};
> +
> +static const struct of_device_id ti_opp_supply_of_match[] = {
> + {.compatible = "ti,omap-opp-supply", .data = &omap_generic_of_data},
> + {.compatible = "ti,omap5-opp-supply", .data = &omap_omap5_of_data},
> + {.compatible = "ti,omap5-core-opp-supply",
> + .data = &omap_omap5core_of_data},
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, ti_opp_supply_of_match);
> +
> +static int ti_opp_supply_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device *cpu_dev = get_cpu_device(0);
> + const struct of_device_id *match;
> + const struct ti_opp_supply_of_data *of_data;
> + int ret = 0;
> +
> + match = of_match_device(ti_opp_supply_of_match, dev);
> + if (!match) {
> + /* We do not expect this to happen */
> + dev_err(dev, "%s: Unable to match device\n", __func__);
> + return -ENODEV;
> + }
> + if (!match->data) {
> + /* Again, unlikely.. but mistakes do happen */
> + dev_err(dev, "%s: Bad data in match\n", __func__);
> + return -EINVAL;
> + }
> + of_data = match->data;
> +
> + dev_set_drvdata(dev, (void *)of_data);
> +
> + /* If we need optimized voltage */
> + if (of_data->flags & OPPDM_EFUSE_CLASS0_OPTIMIZED_VOLTAGE) {
> + ret = _store_optimized_voltages(dev, &opp_data);
> + if (ret)
> + return ret;
> + }
> +
> + ret = PTR_ERR_OR_ZERO(dev_pm_opp_register_set_opp_helper(cpu_dev,
> + ti_opp_supply_set_opp));
> + if (ret)
> + _free_optimized_voltages(dev, &opp_data);
> +
> + return ret;
> +}
> +
> +static struct platform_driver ti_opp_supply_driver = {
> + .probe = ti_opp_supply_probe,
> + .driver = {
> + .name = "ti_opp_supply",
> + .owner = THIS_MODULE,
> + .of_match_table = of_match_ptr(ti_opp_supply_of_match),
> + },
> +};
> +module_platform_driver(ti_opp_supply_driver);
> +
> +MODULE_DESCRIPTION("Texas Instruments OMAP OPP Supply driver");
> +MODULE_AUTHOR("Texas Instruments Inc.");
> +MODULE_LICENSE("GPL v2");
Looks fine otherwise.
--
viresh
^ permalink raw reply
* [PATCH] KVM: arm/arm64: don't set vtimer->cnt_ctl in kvm_arch_timer_handler
From: Jia He @ 2017-12-14 4:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213091803.GQ910@cbox>
Hi Christoffer
I have tried your newer level-mapped-v7 branch, but bug is still there.
There is no special load in both host and guest. The guest (kernel 4.14)
is often hanging when booting
the guest kernel log
[ OK ] Reached target Remote File Systems.
Starting File System Check on /dev/mapper/fedora-root...
[ OK ] Started File System Check on /dev/mapper/fedora-root.
Mounting /sysroot...
[ 2.670764] SGI XFS with ACLs, security attributes, no debug enabled
[ 2.678180] XFS (dm-0): Mounting V5 Filesystem
[ 2.740364] XFS (dm-0): Ending clean mount
[ OK ] Mounted /sysroot.
[ OK ] Reached target Initrd Root File System.
Starting Reload Configuration from the Real Root...
[ 61.288215] INFO: rcu_sched detected stalls on CPUs/tasks:
[ 61.290791] 1-...!: (0 ticks this GP) idle=574/0/0 softirq=5/5 fqs=1
[ 61.293664] (detected by 0, t=6002 jiffies, g=-263, c=-264, q=39760)
[ 61.296480] Task dump for CPU 1:
[ 61.297938] swapper/1 R running task 0 0 1 0x00000020
[ 61.300643] Call trace:
[ 61.301260] __switch_to+0x6c/0x78
[ 61.302095] cpu_number+0x0/0x8
[ 61.302867] rcu_sched kthread starved for 6000 jiffies!
g18446744073709551353 c18446744073709551352 f0x0 RCU_GP_WAIT_FQS(3)
->state=0x402 ->cpu=1
[ 61.305941] rcu_sched I 0 8 2 0x00000020
[ 61.307250] Call trace:
[ 61.307854] __switch_to+0x6c/0x78
[ 61.308693] __schedule+0x268/0x8f0
[ 61.309545] schedule+0x2c/0x88
[ 61.310325] schedule_timeout+0x84/0x3b8
[ 61.311278] rcu_gp_kthread+0x4d4/0x7d8
[ 61.312213] kthread+0x134/0x138
[ 61.313001] ret_from_fork+0x10/0x1c
Maybe my previous patch is not perfect enough, thanks for your comments.
I digged it futher more, do you think below code logic is possibly
problematic?
vtimer_save_state?????????? (vtimer->loaded = false, cntv_ctl is 0)
kvm_arch_timer_handler????????(read cntv_ctl and set vtimer->cnt_ctl = 0)
vtimer_restore_state ? ? ? ? ?? (write vtimer->cnt_ctl to cntv_ctl, then
cntv_ctl will
??? ??? ??? ??? ?? ? ? be 0 forever)
If above analysis is reasonable, how about below patch? already tested
in my arm64 server.
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index f9555b1..ee6dd3f 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -99,7 +99,7 @@ static irqreturn_t kvm_arch_timer_handler(int irq,
void *dev_id)
??????? }
??????? vtimer = vcpu_vtimer(vcpu);
-?????? if (!vtimer->irq.level) {
+?????? if (vtimer->loaded && !vtimer->irq.level) {
??????????????? vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl);
??????????????? if (kvm_timer_irq_can_fire(vtimer))
??????????????????????? kvm_timer_update_irq(vcpu, true, vtimer);
Cheers,
Jia
On 12/13/2017 5:18 PM, Christoffer Dall Wrote:
> On Tue, Dec 12, 2017 at 11:00:07PM -0800, Jia He wrote:
>> In our Armv8a server (qualcomm Amberwing, non VHE), after applying
>> Christoffer's timer optimizing patchset(Optimize arch timer register
>> handling), the guest is hang during kernel booting.
>>
>> The error root cause might be as follows:
>> 1. in kvm_arch_timer_handler, it reset vtimer->cnt_ctl with current
>> cntv_ctl register value. And then it missed some cases to update timer's
>> irq (irq.level) when kvm_timer_irq_can_fire() is false
> Why should it set the irq level to true when the timer cannot fire?
>
>> 2. It causes kvm_vcpu_check_block return 0 instead of -EINTR
>> kvm_vcpu_check_block
>> kvm_cpu_has_pending_timer
>> kvm_timer_is_pending
>> kvm_timer_should_fire
>> 3. Thus, the kvm hyp code can not break the loop in kvm_vcpu_block (halt
>> poll process) and the guest is hang forever
> This is just a polling loop which will expire after some time, so it
> shouldn't halt the guest indefinitely, but merely slow it down for some
> while, if we have a bug. Is that the behavior you're seeing or are you
> seeing the guest coming to a complete halt?
>
>> Fixes: b103cc3f10c0 ("KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit")
>> Signed-off-by: Jia He <jia.he@hxt-semitech.com>
>> ---
>> virt/kvm/arm/arch_timer.c | 1 -
>> 1 file changed, 1 deletion(-)
>>
>> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
>> index f9555b1..bb86433 100644
>> --- a/virt/kvm/arm/arch_timer.c
>> +++ b/virt/kvm/arm/arch_timer.c
>> @@ -100,7 +100,6 @@ static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
>> vtimer = vcpu_vtimer(vcpu);
>>
>> if (!vtimer->irq.level) {
>> - vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl);
> This fix is clearly not correct, as it would prevent forwarding timer
> interrupts in some cases.
>
>> if (kvm_timer_irq_can_fire(vtimer))
>> kvm_timer_update_irq(vcpu, true, vtimer);
>> }
>> --
>> 2.7.4
>>
> I actually don't see how the above scenario you painted can happen.
>
> If you're in the polling loop, that means that the timer state is loaded
> on the vcpu, and that means you can take interrupts from the timer, and
> when you take interrupts, you will set the irq.level.
>
> And here's the first bit of logic in kvm_timer_is_pending():
>
> if (vtimer->irq.level || ptimer->irq.level)
> return true;
>
> So that would break the loop.
>
> I'm not able to reproduce on my side with a non-VHE platform.
>
> What is the workload you're running to reproduce this, and what is the
> exact kernel tree and kernel configuration you're using?
>
> Thanks,
> -Christoffer
>
>
>
^ permalink raw reply related
* [RFC PATCH 5/5] ARM: NOMMU: Support PMSAv8 MPU
From: afzal mohammed @ 2017-12-14 5:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513184527-44120-6-git-send-email-vladimir.murzin@arm.com>
Hi,
On Wed, Dec 13, 2017 at 05:02:07PM +0000, Vladimir Murzin wrote:
> ARMv8R/M architecture defines new memory protection scheme - PMSAv8
Is there a public ARMv8-R architecture reference manual available ?,
seems only ARMv8-A and ARMv8-M ARM's are publically available.
afzal
^ permalink raw reply
* [PATCH V4 09/12] boot_constraint: Add earlycon helper
From: Viresh Kumar @ 2017-12-14 5:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171213094450.GD13194@kroah.com>
On 13-12-17, 10:44, Greg Kroah-Hartman wrote:
> And this feels really odd, does it really save any work for the
> individual "constraint" to check for this option? I'm all for helper
> functions, but this feels like more work than it's worth...
Ok, will move this code to individual platform driver files for now.
--
viresh
^ permalink raw reply
* [PATCH] KVM: arm/arm64: don't set vtimer->cnt_ctl in kvm_arch_timer_handler
From: Jia He @ 2017-12-14 5:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <dc95b58c-ee6c-e5c7-1f37-8f69c789a1fc@gmail.com>
Hi
On 12/14/2017 12:57 PM, Jia He Wrote:
> Hi Christoffer
>
> I have tried your newer level-mapped-v7 branch, but bug is still there.
>
> There is no special load in both host and guest. The guest (kernel
> 4.14) is often hanging when booting
>
> the guest kernel log
>
> [ OK ] Reached target Remote File Systems.
> Starting File System Check on /dev/mapper/fedora-root...
> [ OK ] Started File System Check on /dev/mapper/fedora-root.
> Mounting /sysroot...
> [ 2.670764] SGI XFS with ACLs, security attributes, no debug enabled
> [ 2.678180] XFS (dm-0): Mounting V5 Filesystem
> [ 2.740364] XFS (dm-0): Ending clean mount
> [ OK ] Mounted /sysroot.
> [ OK ] Reached target Initrd Root File System.
> Starting Reload Configuration from the Real Root...
> [ 61.288215] INFO: rcu_sched detected stalls on CPUs/tasks:
> [ 61.290791] 1-...!: (0 ticks this GP) idle=574/0/0 softirq=5/5 fqs=1
> [ 61.293664] (detected by 0, t=6002 jiffies, g=-263, c=-264, q=39760)
> [ 61.296480] Task dump for CPU 1:
> [ 61.297938] swapper/1 R running task 0 0 1 0x00000020
> [ 61.300643] Call trace:
> [ 61.301260] __switch_to+0x6c/0x78
> [ 61.302095] cpu_number+0x0/0x8
> [ 61.302867] rcu_sched kthread starved for 6000 jiffies!
> g18446744073709551353 c18446744073709551352 f0x0 RCU_GP_WAIT_FQS(3)
> ->state=0x402 ->cpu=1
> [ 61.305941] rcu_sched I 0 8 2 0x00000020
> [ 61.307250] Call trace:
> [ 61.307854] __switch_to+0x6c/0x78
> [ 61.308693] __schedule+0x268/0x8f0
> [ 61.309545] schedule+0x2c/0x88
> [ 61.310325] schedule_timeout+0x84/0x3b8
> [ 61.311278] rcu_gp_kthread+0x4d4/0x7d8
> [ 61.312213] kthread+0x134/0x138
> [ 61.313001] ret_from_fork+0x10/0x1c
>
> Maybe my previous patch is not perfect enough, thanks for your comments.
>
> I digged it futher more, do you think below code logic is possibly
> problematic?
>
>
> vtimer_save_state?????????? (vtimer->loaded = false, cntv_ctl is 0)
>
> kvm_arch_timer_handler????????(read cntv_ctl and set vtimer->cnt_ctl = 0)
>
> vtimer_restore_state ? ? ? ? ?? (write vtimer->cnt_ctl to cntv_ctl,
> then cntv_ctl will
>
> ??? ??? ??? ??? ?? ? ? be 0 forever)
sorry, adjust the format, make it easy for reading:
vtimer_save_state?????????????????? (vtimer->loaded = false, cntv_ctl is 0)
kvm_arch_timer_handler????????(read cntv_ctl and set vtimer->cnt_ctl = 0)
vtimer_restore_state ? ? ? ? ???? (write vtimer->cnt_ctl to cntv_ctl,
then cntv_ctl will be 0 forever)
--
Cheers,
Jia
>
>
> If above analysis is reasonable, how about below patch? already tested
> in my arm64 server.
>
> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
> index f9555b1..ee6dd3f 100644
> --- a/virt/kvm/arm/arch_timer.c
> +++ b/virt/kvm/arm/arch_timer.c
> @@ -99,7 +99,7 @@ static irqreturn_t kvm_arch_timer_handler(int irq,
> void *dev_id)
> ??????? }
> ??????? vtimer = vcpu_vtimer(vcpu);
>
> -?????? if (!vtimer->irq.level) {
> +?????? if (vtimer->loaded && !vtimer->irq.level) {
> ??????????????? vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl);
> ??????????????? if (kvm_timer_irq_can_fire(vtimer))
> ??????????????????????? kvm_timer_update_irq(vcpu, true, vtimer);
>
> Cheers,
>
> Jia
>
>
>
> On 12/13/2017 5:18 PM, Christoffer Dall Wrote:
>> On Tue, Dec 12, 2017 at 11:00:07PM -0800, Jia He wrote:
>>> In our Armv8a server (qualcomm Amberwing, non VHE), after applying
>>> Christoffer's timer optimizing patchset(Optimize arch timer register
>>> handling), the guest is hang during kernel booting.
>>>
>>> The error root cause might be as follows:
>>> 1. in kvm_arch_timer_handler, it reset vtimer->cnt_ctl with current
>>> cntv_ctl register value. And then it missed some cases to update
>>> timer's
>>> irq (irq.level) when kvm_timer_irq_can_fire() is false
>> Why should it set the irq level to true when the timer cannot fire?
>>
>>> 2. It causes kvm_vcpu_check_block return 0 instead of -EINTR
>>> ????kvm_vcpu_check_block
>>> ??????? kvm_cpu_has_pending_timer
>>> ??????????? kvm_timer_is_pending
>>> ??????????????? kvm_timer_should_fire
>>> 3. Thus, the kvm hyp code can not break the loop in kvm_vcpu_block
>>> (halt
>>> poll process) and the guest is hang forever
>> This is just a polling loop which will expire after some time, so it
>> shouldn't halt the guest indefinitely, but merely slow it down for some
>> while, if we have a bug.? Is that the behavior you're seeing or are you
>> seeing the guest coming to a complete halt?
>>
>>> Fixes: b103cc3f10c0 ("KVM: arm/arm64: Avoid timer save/restore in
>>> vcpu entry/exit")
>>> Signed-off-by: Jia He <jia.he@hxt-semitech.com>
>>> ---
>>> ? virt/kvm/arm/arch_timer.c | 1 -
>>> ? 1 file changed, 1 deletion(-)
>>>
>>> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
>>> index f9555b1..bb86433 100644
>>> --- a/virt/kvm/arm/arch_timer.c
>>> +++ b/virt/kvm/arm/arch_timer.c
>>> @@ -100,7 +100,6 @@ static irqreturn_t kvm_arch_timer_handler(int
>>> irq, void *dev_id)
>>> ????? vtimer = vcpu_vtimer(vcpu);
>>> ? ????? if (!vtimer->irq.level) {
>>> -??????? vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl);
>> This fix is clearly not correct, as it would prevent forwarding timer
>> interrupts in some cases.
>>
>>> ????????? if (kvm_timer_irq_can_fire(vtimer))
>>> ????????????? kvm_timer_update_irq(vcpu, true, vtimer);
>>> ????? }
>>> --
>>> 2.7.4
>>>
>> I actually don't see how the above scenario you painted can happen.
>>
>> If you're in the polling loop, that means that the timer state is loaded
>> on the vcpu, and that means you can take interrupts from the timer, and
>> when you take interrupts, you will set the irq.level.
>>
>> And here's the first bit of logic in kvm_timer_is_pending():
>>
>> ????if (vtimer->irq.level || ptimer->irq.level)
>> ??????? return true;
>>
>> So that would break the loop.
>>
>> I'm not able to reproduce on my side with a non-VHE platform.
>>
>> What is the workload you're running to reproduce this, and what is the
>> exact kernel tree and kernel configuration you're using?
>>
>> Thanks,
>> -Christoffer
>>
>>
>>
^ permalink raw reply
* [xlnx:master 1118/1121] drivers/gpu/drm/xilinx/xilinx_drm_drv.c:401:24: warning: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'
From: kbuild test robot @ 2017-12-14 6:08 UTC (permalink / raw)
To: linux-arm-kernel
tree: https://github.com/Xilinx/linux-xlnx master
head: 9c2e29b2c81dbb1efb7ee4944b18e12226b97513
commit: ea3243d34738a7900ce247f812a16405fc25d0ef [1118/1121] drm: xilinx: drv: Update dma mask accordingly
config: i386-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.2.0-12) 7.2.1 20171025
reproduce:
git checkout ea3243d34738a7900ce247f812a16405fc25d0ef
# save the attached .config to linux build tree
make ARCH=i386
All warnings (new ones prefixed by >>):
In file included from include/linux/dma-mapping.h:6:0,
from include/drm/drmP.h:37,
from drivers/gpu/drm/xilinx/xilinx_drm_drv.c:18:
drivers/gpu/drm/xilinx/xilinx_drm_drv.c: In function 'xilinx_drm_load':
>> drivers/gpu/drm/xilinx/xilinx_drm_drv.c:401:24: warning: format '%lu' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int' [-Wformat=]
dev_info(&pdev->dev, "failed to set coherent mask (%lu)\n",
^
include/linux/device.h:1195:51: note: in definition of macro 'dev_info'
#define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg)
^~~
vim +401 drivers/gpu/drm/xilinx/xilinx_drm_drv.c
288
289 /* load xilinx drm */
290 static int xilinx_drm_load(struct drm_device *drm, unsigned long flags)
291 {
292 struct xilinx_drm_private *private;
293 struct drm_encoder *encoder;
294 struct drm_connector *connector;
295 struct device_node *encoder_node, *ep = NULL, *remote;
296 struct platform_device *pdev = drm->platformdev;
297 struct component_match *match = NULL;
298 unsigned int align, depth, i = 0;
299 int bpp, ret;
300
301 private = devm_kzalloc(drm->dev, sizeof(*private), GFP_KERNEL);
302 if (!private)
303 return -ENOMEM;
304
305 drm_mode_config_init(drm);
306
307 /* create a xilinx crtc */
308 private->crtc = xilinx_drm_crtc_create(drm);
309 if (IS_ERR(private->crtc)) {
310 DRM_DEBUG_DRIVER("failed to create xilinx crtc\n");
311 ret = PTR_ERR(private->crtc);
312 goto err_out;
313 }
314
315 while ((encoder_node = of_parse_phandle(drm->dev->of_node,
316 "xlnx,encoder-slave", i))) {
317 encoder = xilinx_drm_encoder_create(drm, encoder_node);
318 of_node_put(encoder_node);
319 if (IS_ERR(encoder)) {
320 DRM_DEBUG_DRIVER("failed to create xilinx encoder\n");
321 ret = PTR_ERR(encoder);
322 goto err_out;
323 }
324
325 connector = xilinx_drm_connector_create(drm, encoder, i);
326 if (IS_ERR(connector)) {
327 DRM_DEBUG_DRIVER("failed to create xilinx connector\n");
328 ret = PTR_ERR(connector);
329 goto err_out;
330 }
331
332 i++;
333 }
334
335 while (1) {
336 ep = of_graph_get_next_endpoint(drm->dev->of_node, ep);
337 if (!ep)
338 break;
339
340 of_node_put(ep);
341 remote = of_graph_get_remote_port_parent(ep);
342 if (!remote || !of_device_is_available(remote)) {
343 of_node_put(remote);
344 continue;
345 }
346
347 component_match_add(drm->dev, &match, compare_of, remote);
348 of_node_put(remote);
349 i++;
350 }
351
352 if (i == 0) {
353 DRM_ERROR("failed to get an encoder slave node\n");
354 return -ENODEV;
355 }
356
357 ret = drm_vblank_init(drm, 1);
358 if (ret) {
359 dev_err(&pdev->dev, "failed to initialize vblank\n");
360 goto err_master;
361 }
362
363 /* enable irq to enable vblank feature */
364 drm->irq_enabled = 1;
365
366 drm->dev_private = private;
367 private->drm = drm;
368 xilinx_drm_mode_config_init(drm);
369
370 /* initialize xilinx framebuffer */
371 drm_fb_get_bpp_depth(xilinx_drm_crtc_get_format(private->crtc),
372 &depth, &bpp);
373 if (bpp) {
374 align = xilinx_drm_crtc_get_align(private->crtc);
375 private->fb = xilinx_drm_fb_init(drm, bpp, 1, 1, align,
376 xilinx_drm_fbdev_vres);
377 if (IS_ERR(private->fb)) {
378 DRM_ERROR("failed to initialize drm fb\n");
379 private->fb = NULL;
380 }
381 }
382 if (!private->fb)
383 dev_info(&pdev->dev, "fbdev is not initialized\n");
384
385 drm_kms_helper_poll_init(drm);
386
387 drm_helper_disable_unused_functions(drm);
388
389 platform_set_drvdata(pdev, private);
390
391 if (match) {
392 ret = component_master_add_with_match(drm->dev,
393 &xilinx_drm_ops, match);
394 if (ret)
395 goto err_fb;
396 }
397
398 ret = dma_set_coherent_mask(&pdev->dev,
399 DMA_BIT_MASK(sizeof(dma_addr_t) * 8));
400 if (ret) {
> 401 dev_info(&pdev->dev, "failed to set coherent mask (%lu)\n",
402 sizeof(dma_addr_t));
403 }
404
405 return 0;
406
407 err_fb:
408 drm_vblank_cleanup(drm);
409 err_master:
410 component_master_del(drm->dev, &xilinx_drm_ops);
411 err_out:
412 drm_mode_config_cleanup(drm);
413 if (ret == -EPROBE_DEFER)
414 DRM_INFO("load() is defered & will be called again\n");
415 return ret;
416 }
417
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 57103 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171214/ee33c5e2/attachment-0001.gz>
^ permalink raw reply
* [PATCH 00/12] Marvell NAND controller rework with ->exec_op()
From: Boris Brezillon @ 2017-12-14 6:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20171207201814.30411-1-miquel.raynal@free-electrons.com>
Hi,
On Thu, 7 Dec 2017 21:18:02 +0100
Miquel Raynal <miquel.raynal@free-electrons.com> wrote:
> Hi,
>
> After the addition of the NAND framework ->exec_op() interface (see [1]
> for the series preparing it and [2] for the last version of the
> core-side implementation of ->exec_op() itself), this series replaces
> the current Marvell NAND controller driver pxa3xx_nand.c with a rework
> called marvell_nand.c.
>
> Aside the fact that it drops the big state machine, improves the overall
> speed and implements raw accesses, it is the first driver-side
> implementation of the ->exec_op() interface and may be used as reference
> for latter reworks of the same type.
>
> One may find more detail about why a completely new driver is needed in
> the commit log of:
>
> "mtd: nand: add reworked Marvell NAND controller driver"
>
> The series also changes the device tree NAND node definition for all
> platforms referring to the Marvell driver to use the new bindings. They
> are more hierarchical and fit the real organization of the hardware, by
> having NAND partitions that are part of NAND chip nodes, themselves part
> of the NAND controller node.
>
> These changes have been tested on:
> - PXA3xx platform with a CM-X300 board (2kiB page NAND, 1b/512B
> strength, Hamming ECC engine) [32 bits]
> - Armada 385 DB AP (4kiB page NAND, 4b/512B, BCH ECC engine) [32 bits]
> - Armada 398 DB (4kiB page NAND, 8b/512B, BCH ECC engine using a layout
> with a last chunk different than the others) [32 bits]
> - Armada 7040 DB and Armada 8040 DB (4kiB page NAND, 4b/512B, BCH ECC
> engine) [64 bits]
>
> Robert, it would be great if you could also do more testing on PXA and
> validate this driver. If needed, a branch ready to be tested is
> available at [3]. It is based on nand/next and has all the changes
> brought by the previously mentionned series as well as this one.
Robert, do you think you'll have some time to test Miquel's branch on
your PXA boards? Miquel already tested on one of these boards (CM-X300),
but we'd like to have other testers. Also feel free to review the
driver if have the time.
Thanks,
Boris
>
> Thank you,
> Miqu?l
>
>
> [1] https://www.spinics.net/lists/arm-kernel/msg619633.html
> [2] http://lists.infradead.org/pipermail/linux-mtd/2017-December/077965.html
> [3] https://github.com/miquelraynal/linux/tree/marvell/nand-next/nfc-rework
>
> Miquel Raynal (12):
> dt-bindings: mtd: add Marvell NAND controller documentation
> mtd: nand: add reworked Marvell NAND controller driver
> mtd: nand: replace pxa3xx_nand driver by its rework called
> marvell_nand
> dt-bindings: mtd: remove pxa3xx NAND controller documentation
> mtd: nand: remove useless fields from pxa3xx NAND platform data
> ARM: dts: armada-370-xp: use reworked NAND controller driver
> ARM: dts: armada-375: use reworked NAND controller driver
> ARM: dts: armada-38x: use reworked NAND controller driver
> ARM: dts: armada-39x: use reworked NAND controller driver
> ARM: dts: pxa: use reworked NAND controller driver
> ARM64: dts: marvell: use reworked NAND controller driver on Armada 7K
> ARM64: dts: marvell: use reworked NAND controller driver on Armada 8K
>
> .../devicetree/bindings/mtd/marvell-nand.txt | 84 +
> .../devicetree/bindings/mtd/pxa3xx-nand.txt | 50 -
> arch/arm/boot/dts/armada-370-db.dts | 57 +-
> arch/arm/boot/dts/armada-370-dlink-dns327l.dts | 120 +-
> arch/arm/boot/dts/armada-370-mirabox.dts | 51 +-
> arch/arm/boot/dts/armada-370-netgear-rn102.dts | 90 +-
> arch/arm/boot/dts/armada-370-netgear-rn104.dts | 90 +-
> arch/arm/boot/dts/armada-370-rd.dts | 52 +-
> arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi | 64 +-
> arch/arm/boot/dts/armada-370-xp.dtsi | 6 +-
> arch/arm/boot/dts/armada-375-db.dts | 50 +-
> arch/arm/boot/dts/armada-375.dtsi | 6 +-
> arch/arm/boot/dts/armada-385-db-ap.dts | 69 +-
> arch/arm/boot/dts/armada-385-linksys-caiman.dts | 129 +-
> arch/arm/boot/dts/armada-385-linksys-cobra.dts | 129 +-
> arch/arm/boot/dts/armada-385-linksys-rango.dts | 141 +-
> arch/arm/boot/dts/armada-385-linksys-shelby.dts | 129 +-
> arch/arm/boot/dts/armada-385-linksys.dtsi | 16 +-
> arch/arm/boot/dts/armada-388-db.dts | 55 +-
> arch/arm/boot/dts/armada-38x.dtsi | 6 +-
> arch/arm/boot/dts/armada-390-db.dts | 66 +-
> arch/arm/boot/dts/armada-395-gp.dts | 74 +-
> arch/arm/boot/dts/armada-398-db.dts | 60 +-
> arch/arm/boot/dts/armada-39x.dtsi | 6 +-
> arch/arm/boot/dts/armada-xp-db-dxbc2.dts | 2 +-
> arch/arm/boot/dts/armada-xp-db-xc3-24g4xg.dts | 2 +-
> arch/arm/boot/dts/armada-xp-db.dts | 2 +-
> arch/arm/boot/dts/armada-xp-gp.dts | 2 +-
> arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts | 2 +-
> arch/arm/boot/dts/armada-xp-linksys-mamba.dts | 156 +-
> arch/arm/boot/dts/armada-xp-netgear-rn2120.dts | 90 +-
> arch/arm/boot/dts/pxa3xx.dtsi | 6 +-
> arch/arm/configs/cm_x300_defconfig | 2 +-
> arch/arm/configs/mvebu_v7_defconfig | 2 +-
> arch/arm/configs/pxa3xx_defconfig | 3 +-
> arch/arm/configs/pxa_defconfig | 2 +-
> arch/arm/configs/raumfeld_defconfig | 2 +-
> arch/arm/mach-mmp/ttc_dkb.c | 4 +-
> arch/arm/mach-pxa/cm-x300.c | 8 +-
> arch/arm/mach-pxa/colibri-pxa3xx.c | 8 +-
> arch/arm/mach-pxa/colibri.h | 2 +-
> arch/arm/mach-pxa/littleton.c | 10 +-
> arch/arm/mach-pxa/mxm8x10.c | 10 +-
> arch/arm/mach-pxa/raumfeld.c | 6 +-
> arch/arm/mach-pxa/zylonite.c | 10 +-
> arch/arm64/boot/dts/marvell/armada-7040-db.dts | 52 +-
> arch/arm64/boot/dts/marvell/armada-8040-db.dts | 46 +-
> .../boot/dts/marvell/armada-cp110-master.dtsi | 8 +-
> .../arm64/boot/dts/marvell/armada-cp110-slave.dtsi | 10 +-
> drivers/mtd/nand/Kconfig | 12 +
> drivers/mtd/nand/Makefile | 2 +-
> drivers/mtd/nand/marvell_nand.c | 2950 ++++++++++++++++++++
> drivers/mtd/nand/pxa3xx_nand.c | 2104 --------------
> include/linux/platform_data/mtd-nand-pxa3xx.h | 43 +-
> 54 files changed, 4093 insertions(+), 3065 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/mtd/marvell-nand.txt
> delete mode 100644 Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
> create mode 100644 drivers/mtd/nand/marvell_nand.c
> delete mode 100644 drivers/mtd/nand/pxa3xx_nand.c
>
^ 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