* [PATCH v2 06/14] ASoC: sun4i-codec: Add support for A31 playback through headphone output
From: Chen-Yu Tsai @ 2016-11-04 1:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161103173602.zchyciwj66zdibc7@lukather>
On Fri, Nov 4, 2016 at 1:36 AM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Thu, Nov 03, 2016 at 03:55:48PM +0800, Chen-Yu Tsai wrote:
>> +/* headphone controls */
>> +static const char * const sun6i_codec_hp_src_enum_text[] = {
>> + "DAC", "Mixer",
>> +};
>> +
>> +static SOC_ENUM_DOUBLE_DECL(sun6i_codec_hp_src_enum,
>> + SUN6I_CODEC_OM_DACA_CTRL,
>> + SUN6I_CODEC_OM_DACA_CTRL_LHPIS,
>> + SUN6I_CODEC_OM_DACA_CTRL_RHPIS,
>> + sun6i_codec_hp_src_enum_text);
>> +
>> +static const struct snd_kcontrol_new sun6i_codec_hp_src[] = {
>> + SOC_DAPM_ENUM("Headphone Source Playback Route",
>> + sun6i_codec_hp_src_enum),
>> +};
>
> What is that route exactly? A muxer?
Yup. The following is part of the widgets list later in the code:
+ /* Headphone output path */
+ SND_SOC_DAPM_MUX("Headphone Source Playback Route",
+ SND_SOC_NOPM, 0, 0, sun6i_codec_hp_src),
ChenYu
^ permalink raw reply
* [PATCH 0/2] mm: fix the "counter.sh" failure for libhugetlbfs
From: Huang Shijie @ 2016-11-04 1:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <0a660010-5083-476a-b2c5-88d822089000@infradead.org>
On Thu, Nov 03, 2016 at 10:22:39AM -0700, Randy Dunlap wrote:
> On 11/02/16 19:51, Huang Shijie wrote:
> >
> > (2) The bug
> > After I tested the libhugetlbfs, I found the test case "counter.sh"
> > will fail with the gigantic page (32M page in arm64 board).
> >
> > This patch set adds support for gigantic surplus hugetlb pages,
> > allowing the counter.sh unit test to pass.
>
> Hi,
> Where is the counter.sh test? Where can I find it?
You can get the libhugetlbfs from:
https://github.com/libhugetlbfs/libhugetlbfs.git
Use the "make func" to test it, but the default libhugetlbfs can not run
for the 32M page hugetlbfs, there are several bugs in it. I have an
extra patch set to fix the libhugetlbfs bugs. Maybe I can send them out
later.
But for the 2M page size, you can test the "counter.sh" with "make
func".
thanks
Huang Shijie
^ permalink raw reply
* [PATCH 3/6] clk: rockchip: add clock controller for rk1108
From: Shawn Lin @ 2016-11-04 2:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478176713-12066-1-git-send-email-andy.yan@rock-chips.com>
Hi Andy,
On 2016/11/3 20:38, Andy Yan wrote:
> From: Shawn Lin <shawn.lin@rock-chips.com>
>
> Add the clock tree definition and driver for rk1108 SoC.
>
We should spilt out another patch for adding clock/rst ID
as it should be in a shared branch. :)
You could respin it after Heiko reviews the other parts of
your patchset.
> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> Signed-off-by: Andy Yan <andy.yan@rock-chips.com>
> ---
>
> drivers/clk/rockchip/Makefile | 1 +
> drivers/clk/rockchip/clk-rk1108.c | 463 +++++++++++++++++++++++++++++++++
> drivers/clk/rockchip/clk.h | 14 +
> include/dt-bindings/clock/rk1108-cru.h | 308 ++++++++++++++++++++++
> 4 files changed, 786 insertions(+)
> create mode 100644 drivers/clk/rockchip/clk-rk1108.c
> create mode 100644 include/dt-bindings/clock/rk1108-cru.h
>
> diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
> index b5f2c8e..16e098c 100644
> --- a/drivers/clk/rockchip/Makefile
> +++ b/drivers/clk/rockchip/Makefile
> @@ -11,6 +11,7 @@ obj-y += clk-mmc-phase.o
> obj-y += clk-ddr.o
> obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
>
> +obj-y += clk-rk1108.o
> obj-y += clk-rk3036.o
> obj-y += clk-rk3188.o
> obj-y += clk-rk3228.o
> diff --git a/drivers/clk/rockchip/clk-rk1108.c b/drivers/clk/rockchip/clk-rk1108.c
> new file mode 100644
> index 0000000..eafc623
> --- /dev/null
> +++ b/drivers/clk/rockchip/clk-rk1108.c
> @@ -0,0 +1,463 @@
> +/*
> + * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
> + * Author: Shawn Lin <shawn.lin@rock-chips.com>
> + * Andy Yan <andy.yan@rock-chips.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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/syscore_ops.h>
> +#include <dt-bindings/clock/rk1108-cru.h>
> +#include "clk.h"
> +
> +#define RK1108_GRF_SOC_STATUS0 0x480
> +
> +enum rk1108_plls {
> + apll, dpll, gpll,
> +};
> +
> +static struct rockchip_pll_rate_table rk1108_pll_rates[] = {
> + /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
> + RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
> + RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
> + RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
> + RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
> + RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
> + RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
> + RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
> + RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
> + RK3036_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0),
> + { /* sentinel */ },
> +};
> +
> +
> +#define RK1108_DIV_CORE_MASK 0xf
> +#define RK1108_DIV_CORE_SHIFT 4
> +
> +#define RK1108_CLKSEL0(_core_peri_div) \
> + { \
> + .reg = RK1108_CLKSEL_CON(1), \
> + .val = HIWORD_UPDATE(_core_peri_div, RK1108_DIV_CORE_MASK, \
> + RK1108_DIV_CORE_SHIFT) \
> + }
> +
> +#define RK1108_CPUCLK_RATE(_prate, _core_peri_div) \
> + { \
> + .prate = _prate, \
> + .divs = { \
> + RK1108_CLKSEL0(_core_peri_div), \
> + }, \
> + }
> +
> +static struct rockchip_cpuclk_rate_table rk1108_cpuclk_rates[] __initdata = {
> + RK1108_CPUCLK_RATE(816000000, 4),
> + RK1108_CPUCLK_RATE(600000000, 4),
> + RK1108_CPUCLK_RATE(312000000, 4),
> +};
> +
> +static const struct rockchip_cpuclk_reg_data rk1108_cpuclk_data = {
> + .core_reg = RK1108_CLKSEL_CON(0),
> + .div_core_shift = 0,
> + .div_core_mask = 0x1f,
> + .mux_core_alt = 1,
> + .mux_core_main = 0,
> + .mux_core_shift = 8,
> + .mux_core_mask = 0x1,
> +};
> +
> +PNAME(mux_pll_p) = { "xin24m", "xin24m"};
> +
> +PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr", "apll_ddr" };
> +PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" };
> +PNAME(mux_pmu_1f) = { "xin24m", "pmu_24m"};
> +PNAME(mux_usb480m_phy_p) = { "usb480m_phy0", "usb480m_phy1" };
> +PNAME(mux_usb480m_p) = { "usb480m_phy", "xin24m" };
> +PNAME(mux_hdmiphy_p) = { "hdmiphy_phy", "pclk_top_pre", "xin24m" };
> +
> +PNAME(mux_pll_src_4plls_p) = { "dpll", "hdmiphy", "gpll", "usb480m" };
> +PNAME(mux_pll_src_3plls_p) = { "apll", "gpll", "dpll" };
> +PNAME(mux_pll_src_2plls_p) = { "dpll", "gpll" };
> +
> +PNAME(mux_aclk_peri_src_p) = { "aclk_peri_src_dpll", "aclk_peri_src_gpll" };
> +PNAME(mux_aclk_bus_src_p) = { "aclk_bus_src_gpll", "aclk_bus_src_apll", "aclk_bus_src_dpll" };
> +
> +PNAME(mux_mmc_src_p) = { "dpll", "gpll", "xin24m", "usb480m" };
> +PNAME(mux_pll_src_dpll_gpll_usb480m_p) = { "dpll", "gpll", "usb480m" };
> +
> +
> +PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" };
> +PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" };
> +PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" };
> +
> +
> +static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = {
> + [apll] = PLL(pll_rk3399, RK1108_APLL_ID, "apll", mux_pll_p, 0, RK1108_PLL_CON(0),
> + RK1108_PLL_CON(3), 8, 31, 0, rk1108_pll_rates),
> + [dpll] = PLL(pll_rk3399, RK1108_DPLL_ID, "dpll", mux_pll_p, 0, RK1108_PLL_CON(8),
> + RK1108_PLL_CON(11), 8, 31, 0, NULL),
> + [gpll] = PLL(pll_rk3399, RK1108_GPLL_ID, "gpll", mux_pll_p, 0, RK1108_PLL_CON(16),
> + RK1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk1108_pll_rates),
> +};
> +
> +#define MFLAGS CLK_MUX_HIWORD_MASK
> +#define DFLAGS CLK_DIVIDER_HIWORD_MASK
> +#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
> +
> +
> +static struct rockchip_clk_branch rk1108_uart0_fracmux __initdata =
> + MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
> + RK1108_CLKSEL_CON(13), 8, 2, MFLAGS);
> +
> +static struct rockchip_clk_branch rk1108_uart1_fracmux __initdata =
> + MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
> + RK1108_CLKSEL_CON(14), 8, 2, MFLAGS);
> +
> +static struct rockchip_clk_branch rk1108_uart2_fracmux __initdata =
> + MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
> + RK1108_CLKSEL_CON(15), 8, 2, MFLAGS);
> +
> +static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
> + /*
> + * Clock-Architecture Diagram 2
> + */
> +
> + /* PD_CORE */
> + GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(0), 1, GFLAGS),
> + GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(0), 0, GFLAGS),
> + GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(0), 2, GFLAGS),
> + COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
> + RK1108_CLKGATE_CON(0), 5, GFLAGS),
> + COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
> + RK1108_CLKGATE_CON(0), 4, GFLAGS),
> + GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(11), 0, GFLAGS),
> + GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(11), 1, GFLAGS),
> +
> + /* PD_RKVENC */
> +
> + /* PD_RKVDEC */
> +
> + /* PD_PMU_wrapper */
> + COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(38), 0, 5, DFLAGS,
> + RK1108_CLKGATE_CON(8), 12, GFLAGS),
> + GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(10), 0, GFLAGS),
> + GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(10), 1, GFLAGS),
> + GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(10), 2, GFLAGS),
> + GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(10), 3, GFLAGS),
> + GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(10), 4, GFLAGS),
> + GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(10), 5, GFLAGS),
> + GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(10), 6, GFLAGS),
> + COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS,
> + RK1108_CLKGATE_CON(8), 15, GFLAGS),
> + COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS,
> + RK1108_CLKGATE_CON(8), 14, GFLAGS),
> + GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(8), 13, GFLAGS),
> +
> +
> +
> + /*
> + * Clock-Architecture Diagram 4
> + */
> + COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
> + RK1108_CLKGATE_CON(6), 0, GFLAGS),
> + GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(17), 0, GFLAGS),
> + COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0,
> + RK1108_CLKSEL_CON(29), 0, 5, DFLAGS,
> + RK1108_CLKGATE_CON(7), 2, GFLAGS),
> + COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0,
> + RK1108_CLKSEL_CON(29), 8, 5, DFLAGS,
> + RK1108_CLKGATE_CON(7), 3, GFLAGS),
> +
> +
> + /*
> + * Clock-Architecture Diagram 5
> + */
> +
> + /* PD_BUS */
> + GATE(0, "aclk_bus_src_gpll", "gpll", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(1), 0, GFLAGS),
> + GATE(0, "aclk_bus_src_apll", "apll", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(1), 1, GFLAGS),
> + GATE(0, "aclk_bus_src_dpll", "dpll", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(1), 2, GFLAGS),
> + COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0,
> + RK1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS),
> + COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0,
> + RK1108_CLKSEL_CON(3), 0, 5, DFLAGS,
> + RK1108_CLKGATE_CON(1), 4, GFLAGS),
> + COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0,
> + RK1108_CLKSEL_CON(3), 8, 5, DFLAGS,
> + RK1108_CLKGATE_CON(1), 5, GFLAGS),
> + GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(1), 6, GFLAGS),
> + GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(1), 7, GFLAGS),
> + GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(1), 8, GFLAGS),
> + GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(1), 9, GFLAGS),
> + GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(1), 10, GFLAGS),
> + GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(13), 4, GFLAGS),
> +
> + COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
> + RK1108_CLKGATE_CON(3), 1, GFLAGS),
> + COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
> + RK1108_CLKGATE_CON(3), 3, GFLAGS),
> + COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS,
> + RK1108_CLKGATE_CON(3), 5, GFLAGS),
> +
> + COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
> + RK1108_CLKSEL_CON(16), 0,
> + RK1108_CLKGATE_CON(3), 2, GFLAGS,
> + &rk1108_uart0_fracmux),
> + COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
> + RK1108_CLKSEL_CON(17), 0,
> + RK1108_CLKGATE_CON(3), 4, GFLAGS,
> + &rk1108_uart1_fracmux),
> + COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
> + RK1108_CLKSEL_CON(18), 0,
> + RK1108_CLKGATE_CON(3), 6, GFLAGS,
> + &rk1108_uart2_fracmux),
> + GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(13), 10, GFLAGS),
> + GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(13), 11, GFLAGS),
> + GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(13), 12, GFLAGS),
> +
> +
> + COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS,
> + RK1108_CLKGATE_CON(3), 7, GFLAGS),
> + COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS,
> + RK1108_CLKGATE_CON(3), 8, GFLAGS),
> + COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS,
> + RK1108_CLKGATE_CON(3), 9, GFLAGS),
> + GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(13), 0, GFLAGS),
> + GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(13), 1, GFLAGS),
> + GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(13), 2, GFLAGS),
> + COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS,
> + RK1108_CLKGATE_CON(3), 10, GFLAGS),
> + GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(13), 6, GFLAGS),
> + GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(13), 3, GFLAGS),
> + GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(13), 7, GFLAGS),
> + GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(13), 8, GFLAGS),
> + GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(13), 9, GFLAGS),
> +
> + GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(14), 0, GFLAGS),
> +
> + GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0,
> + RK1108_CLKGATE_CON(12), 2, GFLAGS),
> + GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(12), 3, GFLAGS),
> + GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(12), 1, GFLAGS),
> +
> + /* PD_DDR */
> + GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(0), 8, GFLAGS),
> + GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(0), 9, GFLAGS),
> + GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(0), 10, GFLAGS),
> + COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
> + RK1108_CLKGATE_CON(10), 9, GFLAGS),
> + GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(12), 4, GFLAGS),
> + GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(12), 5, GFLAGS),
> + GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(12), 6, GFLAGS),
> + GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(0), 11, GFLAGS),
> +
> + /*
> + * Clock-Architecture Diagram 6
> + */
> +
> + /* PD_PERI */
> + COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0,
> + RK1108_CLKSEL_CON(23), 10, 5, DFLAGS,
> + RK1108_CLKGATE_CON(4), 5, GFLAGS),
> + GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(15), 13, GFLAGS),
> + COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0,
> + RK1108_CLKSEL_CON(23), 5, 5, DFLAGS,
> + RK1108_CLKGATE_CON(4), 4, GFLAGS),
> + GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(15), 12, GFLAGS),
> +
> + GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(4), 1, GFLAGS),
> + GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED,
> + RK1108_CLKGATE_CON(4), 2, GFLAGS),
> + COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED,
> + RK1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS,
> + RK1108_CLKGATE_CON(15), 11, GFLAGS),
> +
> + COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
> + RK1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS,
> + RK1108_CLKGATE_CON(5), 0, GFLAGS),
> +
> + COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
> + RK1108_CLKSEL_CON(25), 10, 2, MFLAGS,
> + RK1108_CLKGATE_CON(5), 2, GFLAGS),
> + DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
> + RK1108_CLKSEL_CON(26), 0, 8, DFLAGS),
> +
> + COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0,
> + RK1108_CLKSEL_CON(25), 12, 2, MFLAGS,
> + RK1108_CLKGATE_CON(5), 1, GFLAGS),
> + DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0,
> + RK2928_CLKSEL_CON(26), 8, 8, DFLAGS),
> + GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 0, GFLAGS),
> + GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 1, GFLAGS),
> + GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 2, GFLAGS),
> +
> + COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0,
> + RK1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS,
> + RK1108_CLKGATE_CON(5), 3, GFLAGS),
> + GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 3, GFLAGS),
> +
> + COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0,
> + RK1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS,
> + RK1108_CLKGATE_CON(5), 4, GFLAGS),
> + GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 10, GFLAGS),
> + MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK1108_SDMMC_CON0, 1),
> + MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK1108_SDMMC_CON1, 1),
> +
> + MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK1108_SDIO_CON0, 1),
> + MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK1108_SDIO_CON1, 1),
> +
> + MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK1108_EMMC_CON0, 1),
> + MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK1108_EMMC_CON1, 1),
> +};
> +
> +static const char *const rk1108_critical_clocks[] __initconst = {
> + "aclk_core",
> + "aclk_bus_src_gpll",
> + "aclk_periph",
> + "hclk_periph",
> + "pclk_periph",
> +};
> +
> +static void __init rk1108_clk_init(struct device_node *np)
> +{
> + struct rockchip_clk_provider *ctx;
> + void __iomem *reg_base;
> +
> + reg_base = of_iomap(np, 0);
> + if (!reg_base) {
> + pr_err("%s: could not map cru region\n", __func__);
> + return;
> + }
> +
> + ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
> + if (IS_ERR(ctx)) {
> + pr_err("%s: rockchip clk init failed\n", __func__);
> + iounmap(reg_base);
> + return;
> + }
> +
> + rockchip_clk_register_plls(ctx, rk1108_pll_clks,
> + ARRAY_SIZE(rk1108_pll_clks),
> + RK1108_GRF_SOC_STATUS0);
> + rockchip_clk_register_branches(ctx, rk1108_clk_branches,
> + ARRAY_SIZE(rk1108_clk_branches));
> + rockchip_clk_protect_critical(rk1108_critical_clocks,
> + ARRAY_SIZE(rk1108_critical_clocks));
> +
> + rockchip_clk_register_armclk(ctx, RK1108_ARMCLK, "armclk",
> + mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
> + &rk1108_cpuclk_data, rk1108_cpuclk_rates,
> + ARRAY_SIZE(rk1108_cpuclk_rates));
> +
> + rockchip_register_softrst(np, 13, reg_base + RK1108_SOFTRST_CON(0),
> + ROCKCHIP_SOFTRST_HIWORD_MASK);
> +
> + rockchip_register_restart_notifier(ctx, RK1108_GLB_SRST_FST, NULL);
> +
> + rockchip_clk_of_add_provider(np, ctx);
> +}
> +CLK_OF_DECLARE(rk1108_cru, "rockchip,rk1108-cru", rk1108_clk_init);
> diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
> index 1653edd..90c580a 100644
> --- a/drivers/clk/rockchip/clk.h
> +++ b/drivers/clk/rockchip/clk.h
> @@ -34,6 +34,20 @@ struct clk;
> #define HIWORD_UPDATE(val, mask, shift) \
> ((val) << (shift) | (mask) << ((shift) + 16))
>
> +/* register positions shared by RK1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
> +#define RK1108_PLL_CON(x) ((x) * 0x4)
> +#define RK1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60)
> +#define RK1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120)
> +#define RK1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180)
> +#define RK1108_GLB_SRST_FST 0x1c0
> +#define RK1108_GLB_SRST_SND 0x1c4
> +#define RK1108_SDMMC_CON0 0x1d8
> +#define RK1108_SDMMC_CON1 0x1dc
> +#define RK1108_SDIO_CON0 0x1e0
> +#define RK1108_SDIO_CON1 0x1e4
> +#define RK1108_EMMC_CON0 0x1e8
> +#define RK1108_EMMC_CON1 0x1ec
> +
> #define RK2928_PLL_CON(x) ((x) * 0x4)
> #define RK2928_MODE_CON 0x40
> #define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44)
> diff --git a/include/dt-bindings/clock/rk1108-cru.h b/include/dt-bindings/clock/rk1108-cru.h
> new file mode 100644
> index 0000000..e731cc8
> --- /dev/null
> +++ b/include/dt-bindings/clock/rk1108-cru.h
> @@ -0,0 +1,308 @@
> +/*
> + * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
> + * Author:
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H
> +#define _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H
> +
> +/* pll id */
> +#define RK1108_APLL_ID 0
> +#define RK1108_DPLL_ID 1
> +#define RK1108_GPLL_ID 2
> +#define RK1108_ARMCLK 3
> +#define RK1108_END_PLL_ID 4
> +
> +/* sclk gates (special clocks) */
> +#define SCLK_SPI0 65
> +#define SCLK_NANDC 67
> +#define SCLK_SDMMC 68
> +#define SCLK_SDIO 69
> +#define SCLK_EMMC 71
> +#define SCLK_UART0 72
> +#define SCLK_UART1 73
> +#define SCLK_UART2 74
> +#define SCLK_I2S0 75
> +#define SCLK_I2S1 76
> +#define SCLK_I2S2 77
> +#define SCLK_TIMER0 78
> +#define SCLK_TIMER1 79
> +#define SCLK_SFC 80
> +#define SCLK_SDMMC_DRV 81
> +#define SCLK_SDIO_DRV 82
> +#define SCLK_EMMC_DRV 83
> +#define SCLK_SDMMC_SAMPLE 84
> +#define SCLK_SDIO_SAMPLE 85
> +#define SCLK_EMMC_SAMPLE 86
> +
> +/* aclk gates */
> +#define ACLK_DMAC 251
> +#define ACLK_PRE 252
> +#define ACLK_CORE 253
> +#define ACLK_ENMCORE 254
> +
> +/* pclk gates */
> +#define PCLK_GPIO1 321
> +#define PCLK_GPIO2 322
> +#define PCLK_GPIO3 323
> +#define PCLK_GRF 329
> +#define PCLK_I2C1 333
> +#define PCLK_I2C2 334
> +#define PCLK_I2C3 335
> +#define PCLK_SPI 338
> +#define PCLK_SFC 339
> +#define PCLK_UART0 341
> +#define PCLK_UART1 342
> +#define PCLK_UART2 343
> +#define PCLK_TSADC 344
> +#define PCLK_PWM 350
> +#define PCLK_TIMER 353
> +#define PCLK_PERI 363
> +
> +/* hclk gates */
> +#define HCLK_I2S0_8CH 442
> +#define HCLK_I2S1_8CH 443
> +#define HCLK_I2S2_2CH 444
> +#define HCLK_NANDC 453
> +#define HCLK_SDMMC 456
> +#define HCLK_SDIO 457
> +#define HCLK_EMMC 459
> +#define HCLK_PERI 478
> +#define HCLK_SFC 479
> +
> +#define CLK_NR_CLKS (HCLK_SFC + 1)
> +
> +/* reset id */
> +#define SRST_CORE_PO_AD 0
> +#define SRST_CORE_AD 1
> +#define SRST_L2_AD 2
> +#define SRST_CPU_NIU_AD 3
> +#define SRST_CORE_PO 4
> +#define SRST_CORE 5
> +#define SRST_L2 6
> +#define RST_0RES7 7
> +#define SRST_CORE_DBG 8
> +#define PRST_DBG 9
> +#define RST_DAP 10
> +#define PRST_DBG_NIU 11
> +#define RST_0RES12 12
> +#define RST_0RES13 13
> +#define RST_0RES14 14
> +#define ARST_STRC_SYS_AD 15
> +
> +#define SRST_DDRPHY_CLKDIV 16
> +#define SRST_DDRPHY 17
> +#define PRST_DDRPHY 18
> +#define PRST_HDMIPHY 19
> +#define PRST_VDACPHY 20
> +#define PRST_VADCPHY 21
> +#define PRST_MIPI_CSI_PHY 22
> +#define PRST_MIPI_DSI_PHY 23
> +#define PRST_ACODEC 24
> +#define ARST_BUS_NIU 25
> +#define PRST_TOP_NIU 26
> +#define ARST_INTMEM 27
> +#define HRST_ROM 28
> +#define ARST_DMAC 29
> +#define SRST_MSCH_NIU 30
> +#define PRST_MSCH_NIU 31
> +
> +#define PRST_DDRUPCTL 32
> +#define NRST_DDRUPCTL 33
> +#define PRST_DDRMON 34
> +#define HRST_I2S0_8CH 35
> +#define MRST_I2S0_8CH 36
> +#define HRST_I2S1_2CH 37
> +#define MRST_IS21_2CH 38
> +#define HRST_I2S2_2CH 39
> +#define MRST_I2S2_2CH 40
> +#define HRST_CRYPTO 41
> +#define SRST_CRYPTO 42
> +#define PRST_SPI 43
> +#define SRST_SPI 44
> +#define PRST_UART0 45
> +#define PRST_UART1 46
> +#define PRST_UART2 47
> +
> +#define SRST_UART0 48
> +#define SRST_UART1 49
> +#define SRST_UART2 50
> +#define PRST_I2C1 51
> +#define PRST_I2C2 52
> +#define PRST_I2C3 53
> +#define SRST_I2C1 54
> +#define SRST_I2C2 55
> +#define SRST_I2C3 56
> +#define RST_3RES9 57
> +#define PRST_PWM1 58
> +#define RST_3RES11 59
> +#define SRST_PWM1 60
> +#define PRST_WDT 61
> +#define PRST_GPIO1 62
> +#define PRST_GPIO2 63
> +
> +#define PRST_GPIO3 64
> +#define PRST_GRF 65
> +#define PRST_EFUSE 66
> +#define PRST_EFUSE512 67
> +#define PRST_TIMER0 68
> +#define SRST_TIMER0 69
> +#define SRST_TIMER1 70
> +#define PRST_TSADC 71
> +#define SRST_TSADC 72
> +#define PRST_SARADC 73
> +#define SRST_SARADC 74
> +#define HRST_SYSBUS 75
> +#define PRST_USBGRF 76
> +#define RST_4RES13 77
> +#define RST_4RES14 78
> +#define RST_4RES15 79
> +
> +#define ARST_PERIPH_NIU 80
> +#define HRST_PERIPH_NIU 81
> +#define PRST_PERIPH_NIU 82
> +#define HRST_PERIPH 83
> +#define HRST_SDMMC 84
> +#define HRST_SDIO 85
> +#define HRST_EMMC 86
> +#define HRST_NANDC 87
> +#define NRST_NANDC 88
> +#define HRST_SFC 89
> +#define SRST_SFC 90
> +#define ARST_GMAC 91
> +#define HRST_OTG 92
> +#define SRST_OTG 93
> +#define SRST_OTG_ADP 94
> +#define HRST_HOST0 95
> +
> +#define HRST_HOST0_AUX 96
> +#define HRST_HOST0_ARB 97
> +#define SRST_HOST0_EHCIPHY 98
> +#define SRST_HOST0_UTMI 99
> +#define SRST_USBPOR 100
> +#define SRST_UTMI0 101
> +#define SRST_UTMI1 102
> +#define RST_6RES7 103
> +#define RST_6RES8 104
> +#define RST_6RES9 105
> +#define RST_6RES10 106
> +#define RST_6RES11 107
> +#define RST_6RES12 108
> +#define RST_6RES13 109
> +#define RST_6RES14 110
> +#define RST_6RES15 101
> +
> +#define ARST_VIO0_NIU 102
> +#define ARST_VIO1_NIU 103
> +#define HRST_VIO_NIU 104
> +#define PRST_VIO_NIU 105
> +#define ARST_VOP 106
> +#define HRST_VOP 107
> +#define DRST_VOP 108
> +#define ARST_IEP 109
> +#define HRST_IEP 110
> +#define ARST_RGA 111
> +#define HRST_RGA 112
> +#define SRST_RGA 113
> +#define PRST_CVBS 114
> +#define PRST_HDMI 115
> +#define SRST_HDMI 116
> +#define PRST_MIPI_DSI 117
> +
> +#define ARST_ISP_NIU 118
> +#define HRST_ISP_NIU 119
> +#define HRST_ISP 120
> +#define SRST_ISP 121
> +#define ARST_VIP0 122
> +#define HRST_VIP0 123
> +#define PRST_VIP0 124
> +#define ARST_VIP1 125
> +#define HRST_VIP1 126
> +#define PRST_VIP1 127
> +#define ARST_VIP2 128
> +#define HRST_VIP2 129
> +#define PRST_VIP2 120
> +#define ARST_VIP3 121
> +#define HRST_VIP3 122
> +#define PRST_VIP4 123
> +
> +#define PRST_CIF1TO4 124
> +#define SRST_CVBS_CLK 125
> +#define HRST_CVBS 126
> +#define RST_9RES3 127
> +#define RST_9RES4 128
> +#define RST_9RES5 129
> +#define RST_9RES6 130
> +#define RST_9RES7 131
> +#define RST_9RES8 132
> +#define RST_9RES9 133
> +#define RST_9RES10 134
> +#define RST_9RES11 134
> +#define RST_9RES12 136
> +#define RST_9RES13 137
> +#define RST_9RES14 138
> +#define RST_9RES15 139
> +
> +#define ARST_VPU_NIU 140
> +#define HRST_VPU_NIU 141
> +#define ARST_VPU 142
> +#define HRST_VPU 143
> +#define ARST_RKVDEC_NIU 144
> +#define HRST_RKVDEC_NIU 145
> +#define ARST_RKVDEC 146
> +#define HRST_RKVDEC 147
> +#define SRST_RKVDEC_CABAC 148
> +#define SRST_RKVDEC_CORE 149
> +#define ARST_RKVENC_NIU 150
> +#define HRST_RKVENC_NIU 151
> +#define ARST_RKVENC 152
> +#define HRST_RKVENC 153
> +#define SRST_RKVENC_CORE 154
> +#define RST_10RES15 155
> +
> +#define SRST_DSP_CORE 156
> +#define SRST_DSP_SYS 157
> +#define SRST_DSP_GLOBAL 158
> +#define SRST_DSP_OECM 159
> +#define PRST_DSP_IOP_NIU 160
> +#define ARST_DSP_EPP_NIU 161
> +#define ARST_DSP_EDP_NIU 162
> +#define PRST_DSP_DBG_NIU 163
> +#define PRST_DSP_CFG_NIU 164
> +#define PRST_DSP_GRF 165
> +#define PRST_DSP_MAILBOX 166
> +#define PRST_DSP_INTC 167
> +#define RST_11RES12 168
> +#define PRST_DSP_PFM_MON 169
> +#define SRST_DSP_PFM_MON 170
> +#define ARST_DSP_EDAP_NIU 171
> +
> +#define SRST_PMU 172
> +#define SRST_PMU_I2C0 173
> +#define PRST_PMU_I2C0 174
> +#define PRST_PMU_GPIO0 175
> +#define PRST_PMU_INTMEM 176
> +#define PRST_PMU_PWM0 177
> +#define SRST_PMU_PWM0 178
> +#define PRST_PMU_GRF 179
> +#define SRST_PMU_NIU 180
> +#define SRST_PMU_PVTM 181
> +#define RST_12RES10 182
> +#define RST_12RES11 183
> +#define ARST_DSP_EDP_PERF 184
> +#define ARST_DSP_EPP_PERF 185
> +#define RST_12RES114 186
> +#define RST_12RES15 187
> +
> +#endif /* _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H */
> +
>
--
Best Regards
Shawn Lin
^ permalink raw reply
* [PATCH 1/2] arm64: hugetlb: remove the wrong pmd check in find_num_contig()
From: Huang Shijie @ 2016-11-04 2:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104001616.ssjbemliorxi6evl@localhost>
On Thu, Nov 03, 2016 at 06:16:16PM -0600, Catalin Marinas wrote:
> On Thu, Nov 03, 2016 at 10:27:38AM +0800, Huang Shijie wrote:
> > diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
> > index 2e49bd2..4811ef1 100644
> > --- a/arch/arm64/mm/hugetlbpage.c
> > +++ b/arch/arm64/mm/hugetlbpage.c
> > @@ -61,10 +61,6 @@ static int find_num_contig(struct mm_struct *mm, unsigned long addr,
> > return 1;
> > }
> > pmd = pmd_offset(pud, addr);
> > - if (!pmd_present(*pmd)) {
> > - VM_BUG_ON(!pmd_present(*pmd));
> > - return 1;
> > - }
> > if ((pte_t *)pmd == ptep) {
> > *pgsize = PMD_SIZE;
> > return CONT_PMDS;
>
> BTW, for the !pud_present() and !pgd_present() cases, shouldn't
The kernel will not call the find_num_contig() if the PGD/PUD are empty.
Please see the code in the hugetlb_fault().
------------------------------------------------------
ptep = huge_pte_offset(mm, address);
if (ptep) {
...............................
} else {
ptep = huge_pte_alloc(mm, address, huge_page_size(h));
if (!ptep)
return VM_FAULT_OOM;
}
------------------------------------------------------
Thanks
Huang Shijie
> find_num_contig() actually return 0? These are more likely real bugs, so
> no point in setting the huge pte.
^ permalink raw reply
* [PATCH v27 0/9] arm64: add kdump support
From: AKASHI Takahiro @ 2016-11-04 3:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161102044959.11954-1-takahiro.akashi@linaro.org>
For easier testing, I pushed my patches to:
https://git.linaro.org/people/takahiro.akashi/linux-aarch64.git arm64/kdump
https://git.linaro.org/people/takahiro.akashi/kexec-tools.git arm64/kdump
If anybody tries my patches, please let me know the result.
(Pratyush, thank you for your test.)
Thanks,
-Takahiro AKASHI
On Wed, Nov 02, 2016 at 01:49:59PM +0900, AKASHI Takahiro wrote:
> v27-specific note: In this version, the change made in v26 was reverted
> because I've got a comment that /reserved-memory DT property should
> not be used on UEFI/ACPI systems, even though it is workable under
> the current implementation. I've also confirmed that Rob doesn't argue
> any more against using "linux,usable-memory-range".
> So v27 is essentially the same as v25.
>
> This patch series adds kdump support on arm64.
>
> To load a crash-dump kernel to the systems, a series of patches to
> kexec-tools[1] are also needed. Please use the latest one, v4 [2].
>
> To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
> - crash utility (v7.1.6 or later) [3]
>
>
> [1] https://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git
> [1] http://lists.infradead.org/pipermail/kexec/2016-November/017555.html
> [2] https://github.com/crash-utility/crash.git
>
> Changes for v27 (Nov 2, 2016)
> o rebased to Linux-v4.9-rc3
> o revert v26 change, i.e. revive "linux,usable-memory-range" property
> (patch #2/#3, updating patch #9)
> o minor fixes per review comments (patch #3/#4/#6/#8)
> o re-order patches and improve commit messages for readability
>
> Changes for v26 (Sep 7, 2016):
> o Use /reserved-memory instead of "linux,usable-memory-range" property
> (dropping v25's patch#2 and #3, updating ex-patch#9.)
>
> Changes for v25 (Aug 29, 2016):
> o Rebase to Linux-4.8-rc4
> o Use memremap() instead of ioremap_cache() [patch#5]
>
> Changes for v24 (Aug 9, 2016):
> o Rebase to Linux-4.8-rc1
> o Update descriptions about newly added DT proerties
>
> Changes for v23 (July 26, 2016):
>
> o Move memblock_reserve() to a single place in reserve_crashkernel()
> o Use cpu_park_loop() in ipi_cpu_crash_stop()
> o Always enforce ARCH_LOW_ADDRESS_LIMIT to the memory range of crash kernel
> o Re-implement fdt_enforce_memory_region() to remove non-reserve regions
> (for ACPI) from usable memory at crash kernel
>
> Changes for v22 (July 12, 2016):
>
> o Export "crashkernel-base" and "crashkernel-size" via device-tree,
> and add some descriptions about them in chosen.txt
> o Rename "usable-memory" to "usable-memory-range" to avoid inconsistency
> with powerpc's "usable-memory"
> o Make cosmetic changes regarding "ifdef" usage
> o Correct some wordings in kdump.txt
>
> Changes for v21 (July 6, 2016):
>
> o Remove kexec patches.
> o Rebase to arm64's for-next/core (Linux-4.7-rc4 based).
> o Clarify the description about kvm in kdump.txt.
>
> See the following link [3] for older changes:
> [3] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438780.html
>
> AKASHI Takahiro (8):
> memblock: add memblock_cap_memory_range()
> arm64: limit memory regions based on DT property, usable-memory-range
> arm64: kdump: reserve memory for crash dump kernel
> arm64: kdump: implement machine_crash_shutdown()
> arm64: kdump: add VMCOREINFO's for user-space tools
> arm64: kdump: provide /proc/vmcore file
> arm64: kdump: enable kdump in defconfig
> Documentation: kdump: describe arm64 port
>
> James Morse (1):
> Documentation: dt: chosen properties for arm64 kdump
>
> Documentation/devicetree/bindings/chosen.txt | 50 +++++++
> Documentation/kdump/kdump.txt | 16 ++-
> arch/arm64/Kconfig | 11 ++
> arch/arm64/configs/defconfig | 1 +
> arch/arm64/include/asm/hardirq.h | 2 +-
> arch/arm64/include/asm/kexec.h | 42 +++++-
> arch/arm64/include/asm/smp.h | 2 +
> arch/arm64/kernel/Makefile | 1 +
> arch/arm64/kernel/crash_dump.c | 71 ++++++++++
> arch/arm64/kernel/machine_kexec.c | 67 ++++++++-
> arch/arm64/kernel/setup.c | 7 +-
> arch/arm64/kernel/smp.c | 63 +++++++++
> arch/arm64/mm/init.c | 199 +++++++++++++++++++++++++++
> include/linux/memblock.h | 1 +
> mm/memblock.c | 28 ++++
> 15 files changed, 554 insertions(+), 7 deletions(-)
> create mode 100644 arch/arm64/kernel/crash_dump.c
>
> --
> 2.10.0
>
^ permalink raw reply
* [PATCH] mm: hugetlb: rename some allocation functions
From: Huang Shijie @ 2016-11-04 3:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478141499-13825-2-git-send-email-shijie.huang@arm.com>
After a future patch, the __alloc_buddy_huge_page() will not necessarily
use the buddy allocator.
So this patch removes the "buddy" from these functions:
__alloc_buddy_huge_page -> __alloc_huge_page
__alloc_buddy_huge_page_no_mpol -> __alloc_huge_page_no_mpol
__alloc_buddy_huge_page_with_mpol -> __alloc_huge_page_with_mpol
This patch makes preparation for the later patch.
Acked-by: Steve Capper <steve.capper@arm.com>
Signed-off-by: Huang Shijie <shijie.huang@arm.com>
---
Fix the build error in the x86 platform.
---
mm/hugetlb.c | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 32594f1..9fdfc24 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1163,6 +1163,10 @@ static inline void destroy_compound_gigantic_page(struct page *page,
unsigned int order) { }
static inline int alloc_fresh_gigantic_page(struct hstate *h,
nodemask_t *nodes_allowed) { return 0; }
+static struct page *alloc_gigantic_page(int nid, unsigned int order)
+{
+ return NULL;
+}
#endif
static void update_and_free_page(struct hstate *h, struct page *page)
@@ -1568,7 +1572,7 @@ static struct page *__hugetlb_alloc_buddy_huge_page(struct hstate *h,
* For (2), we ignore 'vma' and 'addr' and use 'nid' exclusively. This
* implies that memory policies will not be taken in to account.
*/
-static struct page *__alloc_buddy_huge_page(struct hstate *h,
+static struct page *__alloc_huge_page(struct hstate *h,
struct vm_area_struct *vma, unsigned long addr, int nid)
{
struct page *page;
@@ -1649,21 +1653,21 @@ static struct page *__alloc_buddy_huge_page(struct hstate *h,
* anywhere.
*/
static
-struct page *__alloc_buddy_huge_page_no_mpol(struct hstate *h, int nid)
+struct page *__alloc_huge_page_no_mpol(struct hstate *h, int nid)
{
unsigned long addr = -1;
- return __alloc_buddy_huge_page(h, NULL, addr, nid);
+ return __alloc_huge_page(h, NULL, addr, nid);
}
/*
* Use the VMA's mpolicy to allocate a huge page from the buddy.
*/
static
-struct page *__alloc_buddy_huge_page_with_mpol(struct hstate *h,
+struct page *__alloc_huge_page_with_mpol(struct hstate *h,
struct vm_area_struct *vma, unsigned long addr)
{
- return __alloc_buddy_huge_page(h, vma, addr, NUMA_NO_NODE);
+ return __alloc_huge_page(h, vma, addr, NUMA_NO_NODE);
}
/*
@@ -1681,7 +1685,7 @@ struct page *alloc_huge_page_node(struct hstate *h, int nid)
spin_unlock(&hugetlb_lock);
if (!page)
- page = __alloc_buddy_huge_page_no_mpol(h, nid);
+ page = __alloc_huge_page_no_mpol(h, nid);
return page;
}
@@ -1711,7 +1715,7 @@ static int gather_surplus_pages(struct hstate *h, int delta)
retry:
spin_unlock(&hugetlb_lock);
for (i = 0; i < needed; i++) {
- page = __alloc_buddy_huge_page_no_mpol(h, NUMA_NO_NODE);
+ page = __alloc_huge_page_no_mpol(h, NUMA_NO_NODE);
if (!page) {
alloc_ok = false;
break;
@@ -1963,7 +1967,7 @@ struct page *alloc_huge_page(struct vm_area_struct *vma,
page = dequeue_huge_page_vma(h, vma, addr, avoid_reserve, gbl_chg);
if (!page) {
spin_unlock(&hugetlb_lock);
- page = __alloc_buddy_huge_page_with_mpol(h, vma, addr);
+ page = __alloc_huge_page_with_mpol(h, vma, addr);
if (!page)
goto out_uncharge_cgroup;
if (!avoid_reserve && vma_has_reserves(vma, gbl_chg)) {
@@ -2221,7 +2225,7 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
* First take pages out of surplus state. Then make up the
* remaining difference by allocating fresh huge pages.
*
- * We might race with __alloc_buddy_huge_page() here and be unable
+ * We might race with __alloc_huge_page() here and be unable
* to convert a surplus huge page to a normal huge page. That is
* not critical, though, it just means the overall size of the
* pool might be one hugepage larger than it needs to be, but
@@ -2267,7 +2271,7 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
* By placing pages into the surplus state independent of the
* overcommit value, we are allowing the surplus pool size to
* exceed overcommit. There are few sane options here. Since
- * __alloc_buddy_huge_page() is checking the global counter,
+ * __alloc_huge_page() is checking the global counter,
* though, we'll note that we're not allowed to exceed surplus
* and won't grow the pool anywhere else. Not until one of the
* sysctls are changed, or the surplus pages go out of use.
--
2.5.5
^ permalink raw reply related
* [PATCH 0/4] Add SCU device node support for Exynos4
From: Pankaj Dubey @ 2016-11-04 3:39 UTC (permalink / raw)
To: linux-arm-kernel
This patch series does some cleanup for Exynos4 SoC based boards.
We are currently statically mapping SCU SFRs in mach-exynos/exynos.c
which can be avoided and related dependencies can be removed by introduction
of SCU device node.
This patch series is tested on Exynos4210 based Origen board for SMP boot.
Pankaj Dubey (4):
ARM: EXYNOS: Remove smp_init_cpus hook from platsmp.c
ARM: dts: exynos: Add SCU device node to exynos4.dtsi
ARM: EXYNOS: Remove static mapping of SCU SFR
ARM: EXYNOS: Remove unused soc_is_exynos{4,5}
arch/arm/boot/dts/exynos4.dtsi | 5 +++
arch/arm/mach-exynos/common.h | 5 ---
arch/arm/mach-exynos/exynos.c | 22 -------------
arch/arm/mach-exynos/include/mach/map.h | 2 --
arch/arm/mach-exynos/platsmp.c | 49 +++++++---------------------
arch/arm/mach-exynos/pm.c | 14 ++++++--
arch/arm/mach-exynos/suspend.c | 15 ++++++---
arch/arm/plat-samsung/include/plat/map-s5p.h | 4 ---
8 files changed, 38 insertions(+), 78 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH 1/4] ARM: EXYNOS: Remove smp_init_cpus hook from platsmp.c
From: Pankaj Dubey @ 2016-11-04 3:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478230764-13748-1-git-send-email-pankaj.dubey@samsung.com>
We can safely remove exynos_smp_init_cpus() hook from mach-exynos/platsmp.c,
as all SMP platforms in mach-exynos can rely on DT for CPU core description
instead of determining number of cores from the SCU.
Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
---
arch/arm/mach-exynos/platsmp.c | 31 -------------------------------
1 file changed, 31 deletions(-)
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 98ffe1e..a5d6841 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -385,36 +385,6 @@ fail:
return pen_release != -1 ? ret : 0;
}
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
- */
-
-static void __init exynos_smp_init_cpus(void)
-{
- void __iomem *scu_base = scu_base_addr();
- unsigned int i, ncores;
-
- if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
- ncores = scu_base ? scu_get_core_count(scu_base) : 1;
- else
- /*
- * CPU Nodes are passed thru DT and set_cpu_possible
- * is set by "arm_dt_init_cpu_maps".
- */
- return;
-
- /* sanity check */
- if (ncores > nr_cpu_ids) {
- pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
- ncores, nr_cpu_ids);
- ncores = nr_cpu_ids;
- }
-
- for (i = 0; i < ncores; i++)
- set_cpu_possible(i, true);
-}
-
static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
{
int i;
@@ -479,7 +449,6 @@ static void exynos_cpu_die(unsigned int cpu)
#endif /* CONFIG_HOTPLUG_CPU */
const struct smp_operations exynos_smp_ops __initconst = {
- .smp_init_cpus = exynos_smp_init_cpus,
.smp_prepare_cpus = exynos_smp_prepare_cpus,
.smp_secondary_init = exynos_secondary_init,
.smp_boot_secondary = exynos_boot_secondary,
--
2.7.4
^ permalink raw reply related
* [PATCH 2/4] ARM: dts: exynos: Add SCU device node to exynos4.dtsi
From: Pankaj Dubey @ 2016-11-04 3:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478230764-13748-1-git-send-email-pankaj.dubey@samsung.com>
Exynos4 like other Cortex-A9 SoC's has a Snoop Control Unit(SCU)
and its SFR are used during SMP boot and S2R. Add SCU node to the device tree.
Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
---
arch/arm/boot/dts/exynos4.dtsi | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 5f034eb..6865ca9 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -78,6 +78,11 @@
reg = <0x10000000 0x100>;
};
+ scu: snoop-control-unit at 10500000 {
+ compatible = "arm,cortex-a9-scu";
+ reg = <0x10500000 0x2000>;
+ };
+
memory-controller at 12570000 {
compatible = "samsung,exynos4210-srom";
reg = <0x12570000 0x14>;
--
2.7.4
^ permalink raw reply related
* [PATCH 3/4] ARM: EXYNOS: Remove static mapping of SCU SFR
From: Pankaj Dubey @ 2016-11-04 3:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478230764-13748-1-git-send-email-pankaj.dubey@samsung.com>
Lets remove static mapping of SCU SFR mainly used in CORTEX-A9 SoC based boards.
Instead use mapping from device tree node of SCU.
Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
---
arch/arm/mach-exynos/exynos.c | 22 ----------------------
arch/arm/mach-exynos/include/mach/map.h | 2 --
arch/arm/mach-exynos/platsmp.c | 18 +++++++++++-------
arch/arm/mach-exynos/pm.c | 14 +++++++++++---
arch/arm/mach-exynos/suspend.c | 15 +++++++++++----
arch/arm/plat-samsung/include/plat/map-s5p.h | 4 ----
6 files changed, 33 insertions(+), 42 deletions(-)
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 757fc11..fa08ef9 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -28,15 +28,6 @@
#include "common.h"
-static struct map_desc exynos4_iodesc[] __initdata = {
- {
- .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
- .pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
- .length = SZ_8K,
- .type = MT_DEVICE,
- },
-};
-
static struct platform_device exynos_cpuidle = {
.name = "exynos_cpuidle",
#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
@@ -99,17 +90,6 @@ static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
return 1;
}
-/*
- * exynos_map_io
- *
- * register the standard cpu IO areas
- */
-static void __init exynos_map_io(void)
-{
- if (soc_is_exynos4())
- iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
-}
-
static void __init exynos_init_io(void)
{
debug_ll_io_init();
@@ -118,8 +98,6 @@ static void __init exynos_init_io(void)
/* detect cpu id and rev. */
s5p_init_cpu(S5P_VA_CHIPID);
-
- exynos_map_io();
}
/*
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 5fb0040..0eef407 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -18,6 +18,4 @@
#define EXYNOS_PA_CHIPID 0x10000000
-#define EXYNOS4_PA_COREPERI 0x10500000
-
#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index a5d6841..553d0d9 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -224,11 +224,6 @@ static void write_pen_release(int val)
sync_cache_w(&pen_release);
}
-static void __iomem *scu_base_addr(void)
-{
- return (void __iomem *)(S5P_VA_SCU);
-}
-
static DEFINE_SPINLOCK(boot_lock);
static void exynos_secondary_init(unsigned int cpu)
@@ -387,14 +382,23 @@ fail:
static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
{
+ struct device_node *np;
+ void __iomem *scu_base;
int i;
exynos_sysram_init();
exynos_set_delayed_reset_assertion(true);
- if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
- scu_enable(scu_base_addr());
+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
+ np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+ scu_base = of_iomap(np, 0);
+ if (scu_base) {
+ scu_enable(scu_base);
+ iounmap(scu_base);
+ }
+ of_node_put(np);
+ }
/*
* Write the address of secondary startup into the
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index 487295f..60e6827 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -18,6 +18,7 @@
#include <linux/cpu_pm.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/soc/samsung/exynos-regs-pmu.h>
#include <linux/soc/samsung/exynos-pmu.h>
@@ -26,8 +27,6 @@
#include <asm/suspend.h>
#include <asm/cacheflush.h>
-#include <mach/map.h>
-
#include "common.h"
static inline void __iomem *exynos_boot_vector_addr(void)
@@ -158,6 +157,8 @@ static int exynos_aftr_finisher(unsigned long flags)
void exynos_enter_aftr(void)
{
+ struct device_node *np;
+ void __iomem *scu_base;
unsigned int cpuid = smp_processor_id();
cpu_pm_enter();
@@ -177,7 +178,14 @@ void exynos_enter_aftr(void)
cpu_suspend(0, exynos_aftr_finisher);
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
- scu_enable(S5P_VA_SCU);
+ np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+ scu_base = of_iomap(np, 0);
+ if (scu_base) {
+ scu_enable(scu_base);
+ iounmap(scu_base);
+ }
+ of_node_put(np);
+
if (call_firmware_op(resume) == -ENOSYS)
exynos_cpu_restore_register();
}
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index 06332f6..7ab7e67 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -34,8 +34,6 @@
#include <asm/smp_scu.h>
#include <asm/suspend.h>
-#include <mach/map.h>
-
#include <plat/pm-common.h>
#include "common.h"
@@ -453,6 +451,8 @@ static void exynos_pm_release_retention(void)
static void exynos_pm_resume(void)
{
+ struct device_node *np;
+ void __iomem *scu_base;
u32 cpuid = read_cpuid_part();
if (exynos_pm_central_resume())
@@ -461,8 +461,15 @@ static void exynos_pm_resume(void)
/* For release retention */
exynos_pm_release_retention();
- if (cpuid == ARM_CPU_PART_CORTEX_A9)
- scu_enable(S5P_VA_SCU);
+ if (cpuid == ARM_CPU_PART_CORTEX_A9) {
+ np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+ scu_base = of_iomap(np, 0);
+ if (scu_base) {
+ scu_enable(scu_base);
+ iounmap(scu_base);
+ }
+ of_node_put(np);
+ }
if (call_firmware_op(resume) == -ENOSYS
&& cpuid == ARM_CPU_PART_CORTEX_A9)
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
index 0fe2828..512ed1f 100644
--- a/arch/arm/plat-samsung/include/plat/map-s5p.h
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -15,10 +15,6 @@
#define S5P_VA_CHIPID S3C_ADDR(0x02000000)
-#define S5P_VA_COREPERI_BASE S3C_ADDR(0x02800000)
-#define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x))
-#define S5P_VA_SCU S5P_VA_COREPERI(0x0)
-
#define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000))
#define VA_VIC0 VA_VIC(0)
#define VA_VIC1 VA_VIC(1)
--
2.7.4
^ permalink raw reply related
* [PATCH 4/4] ARM: EXYNOS: Remove unused soc_is_exynos{4,5}
From: Pankaj Dubey @ 2016-11-04 3:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478230764-13748-1-git-send-email-pankaj.dubey@samsung.com>
As no more user of soc_is_exynos{4,5} we can safely remove them.
Signed-off-by: Pankaj Dubey <pankaj.dubey@samsung.com>
---
arch/arm/mach-exynos/common.h | 5 -----
1 file changed, 5 deletions(-)
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 9424a8a..d19064b 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -105,11 +105,6 @@ IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK)
# define soc_is_exynos5800() 0
#endif
-#define soc_is_exynos4() (soc_is_exynos4210() || soc_is_exynos4212() || \
- soc_is_exynos4412())
-#define soc_is_exynos5() (soc_is_exynos5250() || soc_is_exynos5410() || \
- soc_is_exynos5420() || soc_is_exynos5800())
-
extern u32 cp15_save_diag;
extern u32 cp15_save_power;
--
2.7.4
^ permalink raw reply related
* [PATCH v4 4/4] ARM: dts: da850: Add the usb otg device node
From: David Lechner @ 2016-11-04 3:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478188752-22447-5-git-send-email-abailon@baylibre.com>
On 11/03/2016 10:59 AM, Alexandre Bailon wrote:
> This adds the device tree node for the usb otg
> controller present in the da850 family of SoC's.
> This also enables the otg usb controller for the lcdk board.
>
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> ---
> arch/arm/boot/dts/da850-lcdk.dts | 8 ++++++++
> arch/arm/boot/dts/da850.dtsi | 15 +++++++++++++++
> 2 files changed, 23 insertions(+)
>
> diff --git a/arch/arm/boot/dts/da850-lcdk.dts b/arch/arm/boot/dts/da850-lcdk.dts
> index 7b8ab21..9f5040c 100644
> --- a/arch/arm/boot/dts/da850-lcdk.dts
> +++ b/arch/arm/boot/dts/da850-lcdk.dts
> @@ -158,6 +158,14 @@
> rx-num-evt = <32>;
> };
>
> +&usb_phy {
> + status = "okay";
> + };
> +
> +&usb0 {
> + status = "okay";
> +};
> +
> &aemif {
> pinctrl-names = "default";
> pinctrl-0 = <&nand_pins>;
> diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
> index f79e1b9..322a31a 100644
> --- a/arch/arm/boot/dts/da850.dtsi
> +++ b/arch/arm/boot/dts/da850.dtsi
> @@ -372,6 +372,21 @@
> >;
> status = "disabled";
> };
> + usb_phy: usb-phy {
> + compatible = "ti,da830-usb-phy";
> + #phy-cells = <1>;
> + status = "disabled";
> + };
The usb_phy node is already in the device tree as a child of the cfgchip
syscon node[1]. It needs to be removed from this patch, otherwise we
will end up with duplicate usb_phy nodes.
[1]:
https://git.kernel.org/cgit/linux/kernel/git/nsekhar/linux-davinci.git/commit/?h=v4.10/dt&id=1b499f255589204466d8f8ab26e6b577d7b5c88f
> + usb0: usb at 200000 {
> + compatible = "ti,da830-musb";
> + reg = <0x200000 0x10000>;
> + interrupts = <58>;
> + interrupt-names = "mc";
> + dr_mode = "otg";
Isn't this the default value? Could we omit the dr_mode property here?
> + phys = <&usb_phy 0>;
> + phy-names = "usb-phy";
> + status = "disabled";
> + };
> gpio: gpio at 226000 {
> compatible = "ti,dm6441-gpio";
> gpio-controller;
>
^ permalink raw reply
* [PATCH v2 3/6] mfd: dt: Add bindings for the Aspeed LPC Host Controller (LPCHC)
From: Andrew Jeffery @ 2016-11-04 3:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACPK8XezumurK6TStNhmTnHdhoJuZBzkJrS3iOArKz1tf1=nLw@mail.gmail.com>
On Fri, 2016-11-04 at 09:36 +1030, Joel Stanley wrote:
> On Thu, Nov 3, 2016 at 1:07 AM, Andrew Jeffery <andrew@aj.id.au> wrote:
> >
> > The Aspeed LPC Host Controller is presented as a syscon device to
> > arbitrate access by LPC and pinmux drivers. LPC pinmux configuration on
> > fifth generation SoCs depends on bits in both the System Control Unit
> > and the LPC Host Controller.
> >
> > Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> > ---
> > ?Documentation/devicetree/bindings/mfd/aspeed-lpchc.txt | 17 +++++++++++++++++
> > ?1 file changed, 17 insertions(+)
> > ?create mode 100644 Documentation/devicetree/bindings/mfd/aspeed-lpchc.txt
> >
> > diff --git a/Documentation/devicetree/bindings/mfd/aspeed-lpchc.txt b/Documentation/devicetree/bindings/mfd/aspeed-lpchc.txt
> > new file mode 100644
> > index 000000000000..792651488c3d
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mfd/aspeed-lpchc.txt
> > @@ -0,0 +1,17 @@
> > +* Device tree bindings for the Aspeed LPC Host Controller (LPCHC)
> I had to check the data sheet for that acronym. They call the
> registers LHC. I somewhat prefer that name, but if you're happy with
> it as-is then that's fine.
I had an internal debate about this. I figured LPCHC might give a bit
more context to the acronym. I'm not unhappy with it but I wouldn't
claim I'm happy either. I will change it to LHC since you somewhat
prefer it, and it better aligns with the datasheet.
>
> I assume this is not an issue on the g4/ast2400?
Correct, we don't have the issue of pinmux needing to reach into the
LPC IO space on the AST2400. I don't think we've had anything else to
drive us to looking at the host controller space there, so I wasn't
going to add it to the bindings yet.
>
> >
> > +
> > +The LPCHC registers configure LPC behaviour between the BMC and the host
> > +system. The LPCHC also participates in pinmux requests on g5 SoCs and is
> > +therefore considered a syscon device.
> > +
> > +Required properties:
> > +- compatible:??????????"aspeed,ast2500-lpchc", "syscon"
> > +- reg:?????????????????contains offset/length value of the LPCHC memory
> > +???????????????????????region.
> > +
> > +Example:
> > +
> > +lpchc: lpchc at 1e7890a0 {
> > +???????compatible = "aspeed,ast2500-lpchc", "syscon";
> > +???????reg = <0x1e7890a0 0xc4>;
> Where's the 0xc4 come from? I can see 9 registers, which would mean
> the length should be 0x24?
Yes, it should be 0x24. I can't even claim that 'c' is near '2'. Thanks
for catching that.
Andrew
>
> Cheers,
>
> Joel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161104/19c05671/attachment.sig>
^ permalink raw reply
* [PATCH] iommu: arm-smmu: Set SMTNMB_TLBEN in ACR to enable caching of bypass entries
From: Nipun Gupta @ 2016-11-04 3:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <VI1PR0401MB263890564BC836B7BBE744018DA30@VI1PR0401MB2638.eurprd04.prod.outlook.com>
> -----Original Message-----
> From: Stuart Yoder
> Sent: Friday, November 04, 2016 2:27
> To: Nipun Gupta <nipun.gupta@nxp.com>; robin.murphy at arm.com;
> will.deacon at arm.com; linux-arm-kernel at lists.infradead.org;
> iommu at lists.linux-foundation.org
> Cc: Nipun Gupta <nipun.gupta@nxp.com>
> Subject: RE: [PATCH] iommu: arm-smmu: Set SMTNMB_TLBEN in ACR to enable
> caching of bypass entries
>
>
>
> > -----Original Message-----
> > From: Nipun Gupta [mailto:nipun.gupta at nxp.com]
> > Sent: Thursday, November 03, 2016 7:27 PM
> > To: robin.murphy at arm.com; will.deacon at arm.com;
> > linux-arm-kernel at lists.infradead.org; iommu at lists.linux-
> > foundation.org
> > Cc: Stuart Yoder <stuart.yoder@nxp.com>; Nipun Gupta
> > <nipun.gupta@nxp.com>
> > Subject: [PATCH] iommu: arm-smmu: Set SMTNMB_TLBEN in ACR to enable
> > caching of bypass entries
>
> When you respin a patch, put the version number in the patch subject:
>
> [PATCH v2] iommu: arm-smmu: Set SMTNMB_TLBEN in ACR to enable caching
> of bypass entries
I added that first, but in the last moment used git format-patch after minor updates
and somehow missed it in the final patch :/. Re-spinning v3 with correct version number.
Thanks,
Nipun
>
> Stuart
^ permalink raw reply
* [PATCH v2 4/6] pinctrl: aspeed: Read and write bits in LPCHC and GFX controllers
From: Andrew Jeffery @ 2016-11-04 3:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACPK8Xd1aisN4d2C01NXAYTZ1FW=C4b_hjvHce-RY9ReRq2cDw@mail.gmail.com>
On Fri, 2016-11-04 at 09:54 +1030, Joel Stanley wrote:
> On Thu, Nov 3, 2016 at 1:07 AM, Andrew Jeffery <andrew@aj.id.au> wrote:
> >
> > The System Control Unit IP block in the Aspeed SoCs is typically where
> > the pinmux configuration is found, but not always. A number of pins
> > depend on state in one of LPC Host Control (LPCHC) or SoC Display
> > Controller (GFX) IP blocks, so the Aspeed pinmux drivers should have the
> > means to adjust these as necessary.
> >
> > We use syscon to cast a regmap over the GFX and LPCHCR blocks, which is
> > used as an arbitration layer between the relevant driver and the pinctrl
> > subsystem. The regmaps are then exposed to the SoC-specific pinctrl
> > drivers by phandles in the devicetree, and are selected during a mux
> > request by querying a new 'ip' member in struct aspeed_sig_desc.
> >
> > Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
> I like this a lot more than the first go. Good work.
>
> Some minor comments below.
>
> >
> > ---
> > Since v1:
> >
> > The change is now proactive: instead of reporting that we need to flip bits in
> > controllers we can't access, the patch provides access via regmaps for the
> > relevant controllers. The implementation also splits out the IP block ID into
> > its own variable rather than packing the value into the upper bits of the reg
> > member of struct aspeed_sig_desc. This drives some churn in the diff, but I've
> > tried to minimise it.
> >
> > ?.../devicetree/bindings/pinctrl/pinctrl-aspeed.txt | 50 +++++++++++++---
> > ?drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c?????????| 18 +++---
> > ?drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c?????????| 39 ++++++++++---
> > ?drivers/pinctrl/aspeed/pinctrl-aspeed.c????????????| 66 +++++++++++++---------
> > ?drivers/pinctrl/aspeed/pinctrl-aspeed.h????????????| 32 ++++++++---
> > ?5 files changed, 144 insertions(+), 61 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt
> > index 2ad18c4ea55c..115b0cce6c1c 100644
> > --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt
> > +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-aspeed.txt
> > @@ -4,12 +4,19 @@ Aspeed Pin Controllers
> > ?The Aspeed SoCs vary in functionality inside a generation but have a common mux
> > ?device register layout.
> >
> > -Required properties:
> > -- compatible : Should be any one of the following:
> > -???????????????"aspeed,ast2400-pinctrl"
> > -???????????????"aspeed,g4-pinctrl"
> > -???????????????"aspeed,ast2500-pinctrl"
> > -???????????????"aspeed,g5-pinctrl"
> > +Required properties for g4:
> > +- compatible :?????????????????????????Should be any one of the following:
> > +???????????????????????????????"aspeed,ast2400-pinctrl"
> > +???????????????????????????????"aspeed,g4-pinctrl"
> > +
> > +Required properties for g5:
> > +- compatible :?????????????????????????Should be any one of the following:
> > +???????????????????????????????"aspeed,ast2500-pinctrl"
> > +???????????????????????????????"aspeed,g5-pinctrl"
> > +
> > +- aspeed,external-nodes:???????A cell of phandles to external controller nodes:
> > +???????????????????????????????0: compatible with "aspeed,ast2500-gfx", "syscon"
> > +???????????????????????????????1: compatible with "aspeed,ast2500-lpchc", "syscon"
> >
> > ?The pin controller node should be a child of a syscon node with the required
> > ?property:
> > @@ -47,7 +54,7 @@ RGMII1 RGMII2 RMII1 RMII2 SD1 SPI1 SPI1DEBUG SPI1PASSTHRU TIMER4 TIMER5 TIMER6
> > ?TIMER7 TIMER8 VGABIOSROM
> >
> >
> > -Examples:
> > +g4 Example:
> >
> > ?syscon: scu at 1e6e2000 {
> > ????????compatible = "syscon", "simple-mfd";
> > @@ -63,5 +70,34 @@ syscon: scu at 1e6e2000 {
> > ????????};
> > ?};
> >
> > +g5 Example:
> > +
> > +apb {
> > +???????gfx: display at 1e6e6000 {
> > +???????????????compatible = "aspeed,ast2500-gfx", "syscon";
> > +???????????????reg = <0x1e6e6000 0x1000>;
> > +???????};
> > +
> > +???????lpchc: lpchc at 1e7890a0 {
> > +???????????????compatible = "aspeed,ast2500-lpchc", "syscon";
> > +???????????????reg = <0x1e7890a0 0xc4>;
> > +???????};
> > +
> > +???????syscon: scu at 1e6e2000 {
> > +???????????????compatible = "syscon", "simple-mfd";
> > +???????????????reg = <0x1e6e2000 0x1a8>;
> > +
> > +???????????????pinctrl: pinctrl {
> > +???????????????????????compatible = "aspeed,g5-pinctrl";
> > +???????????????????????aspeed,external-nodes = <&gfx, &lpchc>;
> > +
> > +???????????????????????pinctrl_i2c3_default: i2c3_default {
> > +???????????????????????????????function = "I2C3";
> > +???????????????????????????????groups = "I2C3";
> > +???????????????????????};
> > +???????????????};
> > +???????};
> > +};
> > +
> > ?Please refer to pinctrl-bindings.txt in this directory for details of the
> > ?common pinctrl bindings used by client devices.
> > diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
> > index a21b071ff290..558bd102416c 100644
> > --- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
> > +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g4.c
> > @@ -292,7 +292,7 @@ SSSF_PIN_DECL(U18, GPIOG7, FLWP, SIG_DESC_SET(SCU84, 7));
> > ?#define UART6_DESC?????SIG_DESC_SET(SCU90, 7)
> > ?#define ROM16_DESC?????SIG_DESC_SET(SCU90, 6)
> > ?#define FLASH_WIDE?????SIG_DESC_SET(HW_STRAP1, 4)
> > -#define BOOT_SRC_NOR???{ HW_STRAP1, GENMASK(1, 0), 0, 0 }
> > +#define BOOT_SRC_NOR???{ ASPEED_IP_SCU, HW_STRAP1, GENMASK(1, 0), 0, 0 }
> >
> > ?#define A8 56
> > ?SIG_EXPR_DECL(ROMD8, ROM16, ROM16_DESC);
> > @@ -418,9 +418,9 @@ FUNC_GROUP_DECL(I2C8, G5, F3);
> > ?#define U1 88
> > ?SSSF_PIN_DECL(U1, GPIOL0, NCTS1, SIG_DESC_SET(SCU84, 16));
> >
> > -#define VPI18_DESC?????{ SCU90, GENMASK(5, 4), 1, 0 }
> > -#define VPI24_DESC?????{ SCU90, GENMASK(5, 4), 2, 0 }
> > -#define VPI30_DESC?????{ SCU90, GENMASK(5, 4), 3, 0 }
> > +#define VPI18_DESC?????{ ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 1, 0 }
> > +#define VPI24_DESC?????{ ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 2, 0 }
> > +#define VPI30_DESC?????{ ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 3, 0 }
> >
> > ?#define T5 89
> > ?#define T5_DESC?????????SIG_DESC_SET(SCU84, 17)
> > @@ -641,11 +641,11 @@ SSSF_PIN_DECL(Y22, GPIOR2, ROMCS3, SIG_DESC_SET(SCU88, 26));
> > ?#define U19 139
> > ?SSSF_PIN_DECL(U19, GPIOR3, ROMCS4, SIG_DESC_SET(SCU88, 27));
> >
> > -#define VPOOFF0_DESC???{ SCU94, GENMASK(1, 0), 0, 0 }
> > -#define VPO12_DESC?????{ SCU94, GENMASK(1, 0), 1, 0 }
> > -#define VPO24_DESC?????{ SCU94, GENMASK(1, 0), 2, 0 }
> > -#define VPOOFF1_DESC???{ SCU94, GENMASK(1, 0), 3, 0 }
> > -#define VPO_OFF_12??????{ SCU94, 0x2, 0, 0 }
> > +#define VPOOFF0_DESC???{ ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 0, 0 }
> > +#define VPO12_DESC?????{ ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 1, 0 }
> > +#define VPO24_DESC?????{ ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 2, 0 }
> > +#define VPOOFF1_DESC???{ ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 3, 0 }
> > +#define VPO_OFF_12??????{ ASPEED_IP_SCU, SCU94, 0x2, 0, 0 }
> > ?#define VPO_24_OFF??????SIG_DESC_SET(SCU94, 1)
> >
> > ?#define V21 140
> > diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
> > index 87b46390b695..99c4fa9bf861 100644
> > --- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
> > +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
> > @@ -10,6 +10,7 @@
> > ?#include
> > ?#include
> > ?#include
> > +#include
> > ?#include
> > ?#include
> > ?#include
> > @@ -26,8 +27,8 @@
> >
> > ?#define ASPEED_G5_NR_PINS 228
> >
> > -#define COND1??????????{ SCU90, BIT(6), 0, 0 }
> > -#define COND2??????????{ SCU94, GENMASK(1, 0), 0, 0 }
> > +#define COND1??????????{ ASPEED_IP_SCU, SCU90, BIT(6), 0, 0 }
> > +#define COND2??????????{ ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 0, 0 }
> >
> > ?#define B14 0
> > ?SSSF_PIN_DECL(B14, GPIOA0, MAC1LINK, SIG_DESC_SET(SCU80, 0));
> > @@ -186,9 +187,12 @@ MS_PIN_DECL(C20, GPIOE1, NDCD3, GPIE0OUT);
> >
> > ?FUNC_GROUP_DECL(GPIE0, B20, C20);
> >
> > -#define SPI1_DESC??????????????{ HW_STRAP1, GENMASK(13, 12), 1, 0 }
> > -#define SPI1DEBUG_DESC?????????{ HW_STRAP1, GENMASK(13, 12), 2, 0 }
> > -#define SPI1PASSTHRU_DESC??????{ HW_STRAP1, GENMASK(13, 12), 3, 0 }
> > +#define SPI1_DESC \
> > +???????{ ASPEED_IP_SCU, HW_STRAP1, GENMASK(13, 12), 1, 0 }
> > +#define SPI1DEBUG_DESC \
> > +???????{ ASPEED_IP_SCU, HW_STRAP1, GENMASK(13, 12), 2, 0 }
> > +#define SPI1PASSTHRU_DESC \
> > +???????{ ASPEED_IP_SCU, HW_STRAP1, GENMASK(13, 12), 3, 0 }
> >
> > ?#define C18 64
> > ?SIG_EXPR_DECL(SYSCS, SPI1DEBUG, COND1, SPI1DEBUG_DESC);
> > @@ -325,10 +329,11 @@ SS_PIN_DECL(R1, GPIOK7, SDA8);
> >
> > ?FUNC_GROUP_DECL(I2C8, P2, R1);
> >
> > -#define VPIOFF0_DESC????{ SCU90, GENMASK(5, 4), 0, 0 }
> > -#define VPIOFF1_DESC????{ SCU90, GENMASK(5, 4), 1, 0 }
> > -#define VPI24_DESC??????{ SCU90, GENMASK(5, 4), 2, 0 }
> > -#define VPIRSVD_DESC????{ SCU90, GENMASK(5, 4), 3, 0 }
> > +#define VPIOFF0_DESC????{ ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 0, 0 }
> > +#define VPIOFF1_DESC????{ ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 1, 0 }
> > +#define VPI24_DESC??????{ ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 2, 0 }
> > +#define VPIRSVD_DESC????{ ASPEED_IP_SCU, SCU90, GENMASK(5, 4), 3, 0 }
> > +
> >
> > ?#define V2 104
> > ?#define V2_DESC?????????SIG_DESC_SET(SCU88, 0)
> > @@ -848,10 +853,26 @@ static struct pinctrl_desc aspeed_g5_pinctrl_desc = {
> > ?static int aspeed_g5_pinctrl_probe(struct platform_device *pdev)
> > ?{
> > ????????int i;
> > +???????struct regmap **map;
> > +???????struct device_node *node;
> >
> > ????????for (i = 0; i < ARRAY_SIZE(aspeed_g5_pins); i++)
> > ????????????????aspeed_g5_pins[i].number = i;
> >
> > +???????map = &aspeed_g5_pinctrl_data.maps[ASPEED_IP_GFX];
> > +???????node = of_parse_phandle(pdev->dev.of_node, "aspeed,external-nodes", 0);
> > +???????*map = syscon_node_to_regmap(node);
> I think you can use syscon_regmap_lookup_by_phandle to replace both of
> these lines.
Good call, will do.
>
> >
> > +???????of_node_put(node);
> > +???????if (IS_ERR(*map))
> > +???????????????return PTR_ERR(*map);
> Do we want to fail, or warn and continue?
We would need to add further checks to defend against null dereferences
if we were to continue. I think the broken devicetree should be fixed.
>
> The sequence is a bit messy. How about:
>
> struct regmap *map;
>
> map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
> "aspeed,external-nodes");
> if (IS_ERR(map))
> ???return PTR_ERR(map);
>
> aspeed_g5_pinctrl_data.maps[ASPEED_IP_GFX] = map;
That looks neater, I will switch.
>
>
> >
> > +
> > +???????map = &aspeed_g5_pinctrl_data.maps[ASPEED_IP_LPCHC];
> > +???????node = of_parse_phandle(pdev->dev.of_node, "aspeed,external-nodes", 1);
> > +???????*map = syscon_node_to_regmap(node);
> > +???????of_node_put(node);
> > +???????if (IS_ERR(*map))
> > +???????????????return PTR_ERR(*map);
> > +
> Same comments as above.
Ack.
>
> >
> > ????????return aspeed_pinctrl_probe(pdev, &aspeed_g5_pinctrl_desc,
> > ????????????????????????&aspeed_g5_pinctrl_data);
> > ?}
> > diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
> > index 49aeba912531..23586aac7a5a 100644
> > --- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c
> > +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c
> > @@ -14,6 +14,12 @@
> > ?#include "../core.h"
> > ?#include "pinctrl-aspeed.h"
> >
> > +static const char *const aspeed_pinmux_ips[] = {
> > +???????[ASPEED_IP_SCU] = "SCU",
> > +???????[ASPEED_IP_GFX] = "GFX",
> > +???????[ASPEED_IP_LPCHC] = "LHCR",
> We've got both LPCHC and LHCR here. As I said when commenting on the
> regmap bindings, I like LHC(R) better.
>
> >
> > +};
> > +
> > ?int aspeed_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
> > ?{
> > ????????struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
> > @@ -78,7 +84,8 @@ int aspeed_pinmux_get_fn_groups(struct pinctrl_dev *pctldev,
> > ?static inline void aspeed_sig_desc_print_val(
> > ????????????????const struct aspeed_sig_desc *desc, bool enable, u32 rv)
> What's a rv? Perhaps "reg" or "value"?
>
> >
> > ?{
> > -???????pr_debug("SCU%x[0x%08x]=0x%x, got 0x%x from 0x%08x\n", desc->reg,
> > +???????pr_debug("Want %s%X[0x%08X]=0x%X, got 0x%X from 0x%08X\n",
> > +???????????????????????aspeed_pinmux_ips[desc->ip], desc->reg,
> > ????????????????????????desc->mask, enable ? desc->enable : desc->disable,
> > ????????????????????????(rv & desc->mask) >> __ffs(desc->mask), rv);
> > ?}
> > @@ -88,7 +95,7 @@ static inline void aspeed_sig_desc_print_val(
> > ? *
> > ? * @desc: The signal descriptor of interest
> > ? * @enabled: True to query the enabled state, false to query disabled state
> > - * @regmap: The SCU regmap instance
> > + * @regmap: The IP block's regmap instance
> > ? *
> > ? * @return True if the descriptor's bitfield is configured to the state
> > ? * selected by @enabled, false otherwise
> > @@ -119,7 +126,7 @@ static bool aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
> > ? *
> > ? * @expr: An expression controlling the signal for a mux function on a pin
> > ? * @enabled: True to query the enabled state, false to query disabled state
> > - * @regmap: The SCU regmap instance
> > + * @maps: The list of regmap instances
> > ? *
> > ? * @return True if the expression composed by @enabled evaluates true, false
> > ? * otherwise
> > @@ -136,15 +143,16 @@ static bool aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
> > ? * either condition as required.
> > ? */
> > ?static bool aspeed_sig_expr_eval(const struct aspeed_sig_expr *expr,
> > -????????????????????????????????bool enabled, struct regmap *map)
> > +????????????????????????????????bool enabled, struct regmap * const *maps)
> > ?{
> > ????????int i;
> >
> > ????????for (i = 0; i < expr->ndescs; i++) {
> > ????????????????const struct aspeed_sig_desc *desc = &expr->descs[i];
> >
> > -???????????????if (!aspeed_sig_desc_eval(desc, enabled, map))
> > +???????????????if (!aspeed_sig_desc_eval(desc, enabled, maps[desc->ip]))
> > ????????????????????????return false;
> > +
> > ????????}
> >
> > ????????return true;
> > @@ -158,12 +166,12 @@ static bool aspeed_sig_expr_eval(const struct aspeed_sig_expr *expr,
> > ? *????????configured
> > ? * @enable: true to enable an function's signal through a pin's signal
> > ? *??????????expression, false to disable the function's signal
> > - * @map: The SCU's regmap instance for pinmux register access.
> > + * @maps: The list of regmap instances for pinmux register access.
> > ? *
> > ? * @return true if the expression is configured as requested, false otherwise
> > ? */
> > ?static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
> > -???????????????????????????????bool enable, struct regmap *map)
> > +???????????????????????????????bool enable, struct regmap * const *maps)
> > ?{
> > ????????int i;
> >
> > @@ -171,6 +179,7 @@ static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
> > ????????????????bool ret;
> > ????????????????const struct aspeed_sig_desc *desc = &expr->descs[i];
> > ????????????????u32 pattern = enable ? desc->enable : desc->disable;
> > +???????????????u32 val = (pattern << __ffs(desc->mask));
> >
> > ????????????????/*
> > ?????????????????* Strap registers are configured in hardware or by early-boot
> > @@ -179,48 +188,49 @@ static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr,
> > ?????????????????* deconfigured and is the reason we re-evaluate after writing
> > ?????????????????* all descriptor bits.
> > ?????????????????*/
> > -???????????????if (desc->reg == HW_STRAP1 || desc->reg == HW_STRAP2)
> > +???????????????if ((desc->reg == HW_STRAP1 || desc->reg == HW_STRAP2) &&
> > +???????????????????????????????desc->ip == ASPEED_IP_SCU)
> > ????????????????????????continue;
> >
> > -???????????????ret = regmap_update_bits(map, desc->reg, desc->mask,
> > -???????????????????????????????pattern << __ffs(desc->mask)) == 0;
> > +???????????????ret = regmap_update_bits(maps[desc->ip], desc->reg,
> > +????????????????????????????????????????desc->mask, val) == 0;
> >
> > ????????????????if (!ret)
> > ????????????????????????return ret;
> > ????????}
> >
> > -???????return aspeed_sig_expr_eval(expr, enable, map);
> > +???????return aspeed_sig_expr_eval(expr, enable, maps);
> > ?}
> >
> > ?static bool aspeed_sig_expr_enable(const struct aspeed_sig_expr *expr,
> > -??????????????????????????????????struct regmap *map)
> > +??????????????????????????????????struct regmap * const *maps)
> > ?{
> > -???????if (aspeed_sig_expr_eval(expr, true, map))
> > +???????if (aspeed_sig_expr_eval(expr, true, maps))
> > ????????????????return true;
> >
> > -???????return aspeed_sig_expr_set(expr, true, map);
> > +???????return aspeed_sig_expr_set(expr, true, maps);
> > ?}
> >
> > ?static bool aspeed_sig_expr_disable(const struct aspeed_sig_expr *expr,
> > -???????????????????????????????????struct regmap *map)
> > +???????????????????????????????????struct regmap * const *maps)
> > ?{
> > -???????if (!aspeed_sig_expr_eval(expr, true, map))
> > +???????if (!aspeed_sig_expr_eval(expr, true, maps))
> > ????????????????return true;
> >
> > -???????return aspeed_sig_expr_set(expr, false, map);
> > +???????return aspeed_sig_expr_set(expr, false, maps);
> > ?}
> >
> > ?/**
> > ? * Disable a signal on a pin by disabling all provided signal expressions.
> > ? *
> > ? * @exprs: The list of signal expressions (from a priority level on a pin)
> > - * @map: The SCU's regmap instance for pinmux register access.
> > + * @maps: The list of regmap instances for pinmux register access.
> > ? *
> > ? * @return true if all expressions in the list are successfully disabled, false
> > ? * otherwise
> > ? */
> > ?static bool aspeed_disable_sig(const struct aspeed_sig_expr **exprs,
> > -??????????????????????????????struct regmap *map)
> > +??????????????????????????????struct regmap * const *maps)
> > ?{
> > ????????bool disabled = true;
> >
> > @@ -230,7 +240,7 @@ static bool aspeed_disable_sig(const struct aspeed_sig_expr **exprs,
> > ????????while (*exprs) {
> > ????????????????bool ret;
> >
> > -???????????????ret = aspeed_sig_expr_disable(*exprs, map);
> > +???????????????ret = aspeed_sig_expr_disable(*exprs, maps);
> > ????????????????disabled = disabled && ret;
> >
> > ????????????????exprs++;
> > @@ -343,6 +353,8 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
> > ????????????????const struct aspeed_sig_expr **funcs;
> > ????????????????const struct aspeed_sig_expr ***prios;
> >
> > +???????????????pr_debug("Muxing pin %d for %s\n", pin, pfunc->name);
> > +
> > ????????????????if (!pdesc)
> > ????????????????????????return -EINVAL;
> >
> > @@ -358,7 +370,7 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
> > ????????????????????????if (expr)
> > ????????????????????????????????break;
> >
> > -???????????????????????if (!aspeed_disable_sig(funcs, pdata->map))
> > +???????????????????????if (!aspeed_disable_sig(funcs, pdata->maps))
> > ????????????????????????????????return -EPERM;
> >
> > ????????????????????????prios++;
> > @@ -377,7 +389,7 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
> > ????????????????????????return -ENXIO;
> > ????????????????}
> >
> > -???????????????if (!aspeed_sig_expr_enable(expr, pdata->map))
> > +???????????????if (!aspeed_sig_expr_enable(expr, pdata->maps))
> > ????????????????????????return -EPERM;
> > ????????}
> >
> > @@ -432,7 +444,7 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
> > ????????????????if (aspeed_gpio_in_exprs(funcs))
> > ????????????????????????break;
> >
> > -???????????????if (!aspeed_disable_sig(funcs, pdata->map))
> > +???????????????if (!aspeed_disable_sig(funcs, pdata->maps))
> > ????????????????????????return -EPERM;
> >
> > ????????????????prios++;
> > @@ -462,7 +474,7 @@ int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
> > ?????????* If GPIO is not the lowest priority signal type, assume there is only
> > ?????????* one expression defined to enable the GPIO function
> > ?????????*/
> > -???????if (!aspeed_sig_expr_enable(expr, pdata->map))
> > +???????if (!aspeed_sig_expr_enable(expr, pdata->maps))
> > ????????????????return -EPERM;
> >
> > ????????return 0;
> > @@ -481,10 +493,10 @@ int aspeed_pinctrl_probe(struct platform_device *pdev,
> > ????????????????return -ENODEV;
> > ????????}
> >
> > -???????pdata->map = syscon_node_to_regmap(parent->of_node);
> > -???????if (IS_ERR(pdata->map)) {
> > +???????pdata->maps[ASPEED_IP_SCU] = syscon_node_to_regmap(parent->of_node);
> > +???????if (IS_ERR(pdata->maps[ASPEED_IP_SCU])) {
> > ????????????????dev_err(&pdev->dev, "No regmap for syscon pincontroller parent\n");
> > -???????????????return PTR_ERR(pdata->map);
> > +???????????????return PTR_ERR(pdata->maps[ASPEED_IP_SCU]);
> > ????????}
> >
> > ????????pctl = pinctrl_register(pdesc, &pdev->dev, pdata);
> > diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.h b/drivers/pinctrl/aspeed/pinctrl-aspeed.h
> > index 3e72ef8c54bf..727728b86c07 100644
> > --- a/drivers/pinctrl/aspeed/pinctrl-aspeed.h
> > +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.h
> > @@ -232,6 +232,11 @@
> > ? * group.
> > ? */
> >
> > +#define ASPEED_IP_SCU??0
> > +#define ASPEED_IP_GFX??1
> > +#define ASPEED_IP_LPCHC????????2
> > +#define ASPEED_NR_PINMUX_IPS???3
> > +
> > ?/*
> > ? * The "Multi-function Pins Mapping and Control" table in the SoC datasheet
> > ? * references registers by the device/offset mnemonic. The register macros
> > @@ -261,7 +266,9 @@
> > ???* A signal descriptor, which describes the register, bits and the
> > ???* enable/disable values that should be compared or written.
> > ???*
> > -??* @reg: The register offset from base in bytes
> > +??* @ip: The IP block identifier, used as an index into the regmap array in
> > +??*??????struct aspeed_pinctrl_data
> > +??* @reg: The register offset with respect to the base address of the IP block
> > ???* @mask: The mask to apply to the register. The lowest set bit of the mask is
> > ???*????????used to derive the shift value.
> > ???* @enable: The value that enables the function. Value should be in the LSBs,
> > @@ -270,6 +277,7 @@
> > ???*???????????LSBs, not at the position of the mask.
> > ???*/
> > ?struct aspeed_sig_desc {
> > +???????unsigned int ip;
> > ????????unsigned int reg;
> > ????????u32 mask;
> > ????????u32 enable;
> > @@ -313,24 +321,30 @@ struct aspeed_pin_desc {
> >
> > ?/* Macro hell */
> >
> > +#define SIG_DESC_IP_BIT(ip, reg, idx, val) \
> > +???????{ ip, reg, BIT_MASK(idx), val, (((val) + 1) & 1) }
> > +
> > ?/**
> > - * Short-hand macro for describing a configuration enabled by the state of one
> > - * bit. The disable value is derived.
> > + * Short-hand macro for describing an SCU descriptor enabled by the state of
> > + * one bit. The disable value is derived.
> > ? *
> > ? * @reg: The signal's associated register, offset from base
> > ? * @idx: The signal's bit index in the register
> > ? * @val: The value (0 or 1) that enables the function
> > ? */
> > ?#define SIG_DESC_BIT(reg, idx, val) \
> > -???????{ reg, BIT_MASK(idx), val, (((val) + 1) & 1) }
> > +???????SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, val)
> > +
> > +#define SIG_DESC_IP_SET(ip, reg, idx) SIG_DESC_IP_BIT(ip, reg, idx, 1)
> >
> > ?/**
> > - * A further short-hand macro describing a configuration enabled with a set bit.
> > + * A further short-hand macro expanding to an SCU descriptor enabled by a set
> > + * bit.
> > ? *
> > - * @reg: The configuration's associated register, offset from base
> > - * @idx: The configuration's bit index in the register
> > + * @reg: The register, offset from base
> > + * @idx: The bit index in the register
> > ? */
> > -#define SIG_DESC_SET(reg, idx) SIG_DESC_BIT(reg, idx, 1)
> > +#define SIG_DESC_SET(reg, idx) SIG_DESC_IP_BIT(ASPEED_IP_SCU, reg, idx, 1)
> >
> > ?#define SIG_DESC_LIST_SYM(sig, func) sig_descs_ ## sig ## _ ## func
> > ?#define SIG_DESC_LIST_DECL(sig, func, ...) \
> > @@ -500,7 +514,7 @@ struct aspeed_pin_desc {
> > ????????MS_PIN_DECL_(pin, SIG_EXPR_LIST_PTR(gpio))
> >
> > ?struct aspeed_pinctrl_data {
> > -???????struct regmap *map;
> > +???????struct regmap *maps[ASPEED_NR_PINMUX_IPS];
> >
> > ????????const struct pinctrl_pin_desc *pins;
> > ????????const unsigned int npins;
> > --
> > 2.7.4
> >
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161104/a6f587a0/attachment-0001.sig>
^ permalink raw reply
* [RFC 0/8] KVM PCIe/MSI passthrough on ARM/ARM64 (Alt II)
From: Alex Williamson @ 2016-11-04 4:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478209178-3009-1-git-send-email-eric.auger@redhat.com>
On Thu, 3 Nov 2016 21:39:30 +0000
Eric Auger <eric.auger@redhat.com> wrote:
> Following Will & Robin's suggestions, this series attempts to propose
> an alternative to [1] where the host would arbitrarily decide the
> location of the IOVA MSI window and would be able to report to the
> userspace the list of reserved IOVA regions that cannot be used
> along with VFIO_IOMMU_MAP_DMA. This would allow the userspace to react
> in case of conflict.
>
> Userspace can retrieve all the reserved regions through the VFIO_IOMMU_GET_INFO
> IOCTL by querying the new RESV_IOVA_RANGE chained capability. Each reserved
> IOVA range is put in a separate capability.
Doesn't it make more sense to describe the non-holes (ie. what I
can use for DMA) rather the holes (what I can't use for DMA)? For
example on VT-d, the IOMMU not only has the block of MSI addresses
handled through interrupt remapping, but it also has a maximum address
width. Rather than describing the reserved space we could describe the
usable DMA ranges above and below that reserved block.
Anyway, there's also a pretty harsh problem that I came up with in
talking to Will. If the platform describes a fixed IOVA range as
reserved, that's great for the use case when a VM is instantiated with
a device attached, but it seems like it nearly excludes the case of
hotplugging a device. We can't dynamically decide that a set of RAM
pages in the VM cannot be used as a DMA target. Does the user need to
create the VM with a predefined hole that lines up with the reserved
regions for this platform? How do they know the reserved regions for
this platform? How would we handle migration where an assigned device
hot-add might not occur until after we've migrated to a slightly
different platform from the one we started on, that might have
different reserved memory requirements?
We can always have QEMU reject hot-adding the device if the reserved
region overlaps existing guest RAM, but I don't even really see how we
advise users to give them a reasonable chance of avoiding that
possibility. Apparently there are also ARM platforms where MSI pages
cannot be remapped to support the previous programmable user/VM
address, is it even worthwhile to support those platforms? Does that
decision influence whether user programmable MSI reserved regions are
really a second class citizen to fixed reserved regions? I expect
we'll be talking about this tomorrow morning, but I certainly haven't
come up with any viable solutions to this. Thanks,
Alex
> At IOMMU level, the reserved regions are stored in an iommu_domain list
> which is populated on each device attachment. An IOMMU add_reserved_regions
> callback specializes the registration of the reserved regions.
>
> On x86, the [FEE0_0000h - FEF0_000h] MSI window is registered (NOT tested).
>
> On ARM, the PCI host bridge windows (ACS check to be added?) + the MSI IOVA
> reserved regions are populated by the arm-smmu driver. Currently the MSI
> IOVA region is arbitrarily located at 0x8000000 and 1MB sized. An IOVA domain
> is created in add_reserved_regions callback. Then MSIs are transparently
> mapped using this IOVA domain.
>
> This series currently does not address some features addressed in [1]:
> - MSI IOVA size requirement computation
> - IRQ safety assessment
>
> This RFC was just tested on ARM Overdrive with QEMU and is sent to help
> potential discussions at LPC. Additionnal development + testing is needed.
>
> 2 tentative fixes may be submitted separately:
> - vfio: fix vfio_info_cap_add/shift
> - iommu/iova: fix __alloc_and_insert_iova_range
>
> Best Regards
>
> Eric
>
> [1] [PATCH v14 00/16] KVM PCIe/MSI passthrough on ARM/ARM64
> https://lkml.org/lkml/2016/10/12/347
>
> Git: complete series available at
> https://github.com/eauger/linux/tree/v4.9-rc3-reserved-rfc
>
>
> Eric Auger (7):
> vfio: fix vfio_info_cap_add/shift
> iommu/iova: fix __alloc_and_insert_iova_range
> iommu: Add a list of iommu_reserved_region in iommu_domain
> vfio/type1: Introduce RESV_IOVA_RANGE capability
> iommu: Handle the list of reserved regions
> iommu/vt-d: Implement add_reserved_regions callback
> iommu/arm-smmu: implement add_reserved_regions callback
>
> Robin Murphy (1):
> iommu/dma: Allow MSI-only cookies
>
> drivers/iommu/arm-smmu.c | 63 +++++++++++++++++++++++++++++++++++++++++
> drivers/iommu/dma-iommu.c | 39 +++++++++++++++++++++++++
> drivers/iommu/intel-iommu.c | 48 ++++++++++++++++++++++---------
> drivers/iommu/iommu.c | 25 ++++++++++++++++
> drivers/iommu/iova.c | 2 +-
> drivers/vfio/vfio.c | 5 ++--
> drivers/vfio/vfio_iommu_type1.c | 63 ++++++++++++++++++++++++++++++++++++++++-
> include/linux/dma-iommu.h | 9 ++++++
> include/linux/iommu.h | 23 +++++++++++++++
> include/uapi/linux/vfio.h | 16 ++++++++++-
> 10 files changed, 275 insertions(+), 18 deletions(-)
>
^ permalink raw reply
* [PATCH v2 2/3] irqchip: mtk-cirq: Add mediatek mtk-cirq implement
From: Youlin Pei @ 2016-11-04 4:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <86twbrj586.fsf@arm.com>
On Tue, 2016-11-01 at 20:49 +0000, Marc Zyngier wrote:
> On Tue, Nov 01 2016 at 11:52:01 AM, Youlin Pei <youlin.pei@mediatek.com> wrote:
> > In Mediatek SOCs, the CIRQ is a low power interrupt controller
> > designed to works outside MCUSYS which comprises with Cortex-Ax
> > cores,CCI and GIC.
> >
> > The CIRQ controller is integrated in between MCUSYS( include
> > Cortex-Ax, CCI and GIC ) and interrupt sources as the second
> > level interrupt controller. The external interrupts which outside
> > MCUSYS will feed through CIRQ then bypass to GIC. CIRQ can monitors
> > all edge trigger interupts. When an edge interrupt is triggered,
> > CIRQ can record the status and generate a pulse signal to GIC when
> > flush command executed.
> >
> > When system enters sleep mode, MCUSYS will be turned off to improve
> > power consumption, also GIC is power down. The edge trigger interrupts
> > will be lost in this scenario without CIRQ.
> >
> > This commit provides the CIRQ irqchip implement.
> >
> > Signed-off-by: Youlin Pei <youlin.pei@mediatek.com>
> > ---
> > drivers/irqchip/Makefile | 2 +-
> > drivers/irqchip/irq-mtk-cirq.c | 262 ++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 263 insertions(+), 1 deletion(-)
> > create mode 100644 drivers/irqchip/irq-mtk-cirq.c
> >
> > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> > index e4dbfc8..8f33580 100644
> > --- a/drivers/irqchip/Makefile
> > +++ b/drivers/irqchip/Makefile
> > @@ -60,7 +60,7 @@ obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o
> > obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o
> > obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o
> > obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o
> > -obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o
> > +obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o irq-mtk-cirq.o
> > obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o
> > obj-$(CONFIG_RENESAS_H8300H_INTC) += irq-renesas-h8300h.o
> > obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o
> > diff --git a/drivers/irqchip/irq-mtk-cirq.c b/drivers/irqchip/irq-mtk-cirq.c
> > new file mode 100644
> > index 0000000..fc43ef3
> > --- /dev/null
> > +++ b/drivers/irqchip/irq-mtk-cirq.c
> > @@ -0,0 +1,262 @@
> > +/*
> > + * Copyright (c) 2016 MediaTek Inc.
> > + * Author: Youlin.Pei <youlin.pei@mediatek.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.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#include <linux/irq.h>
> > +#include <linux/irqchip.h>
> > +#include <linux/irqdomain.h>
> > +#include <linux/of.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/of_address.h>
> > +#include <linux/io.h>
> > +#include <linux/slab.h>
> > +#include <linux/syscore_ops.h>
> > +
> > +#define CIRQ_ACK 0x40
> > +#define CIRQ_MASK_SET 0xc0
> > +#define CIRQ_MASK_CLR 0x100
> > +#define CIRQ_SENS_SET 0x180
> > +#define CIRQ_SENS_CLR 0x1c0
> > +#define CIRQ_POL_SET 0x240
> > +#define CIRQ_POL_CLR 0x280
> > +#define CIRQ_CONTROL 0x300
> > +
> > +#define CIRQ_EN 0x1
> > +#define CIRQ_EDGE 0x2
> > +#define CIRQ_FLUSH 0x4
> > +
> > +#define CIRQ_IRQ_NUM 0x200
> > +
> > +struct mtk_cirq_chip_data {
> > + void __iomem *base;
> > + unsigned int ext_irq_start;
> > +};
> > +
> > +static struct mtk_cirq_chip_data *cirq_data;
>
> Are you guaranteed that you'll only ever have a single CIRQ in any
> system?
In Mediatek's SOC, only hace a single CIRQ.
>
> > +
> > +static void mtk_cirq_write_mask(struct irq_data *data, unsigned int offset)
> > +{
> > + struct mtk_cirq_chip_data *chip_data = data->chip_data;
> > + unsigned int cirq_num = data->hwirq;
> > + u32 mask = 1 << (cirq_num % 32);
> > +
> > + writel(mask, chip_data->base + offset + (cirq_num / 32) * 4);
>
> Why can't you use the relaxed accessors?
It seems that i use wrong function, i will change the writel to
writel_relaxed in next version.
>
> > +}
> > +
> > +static void mtk_cirq_mask(struct irq_data *data)
> > +{
> > + mtk_cirq_write_mask(data, CIRQ_MASK_SET);
> > + irq_chip_mask_parent(data);
> > +}
> > +
> > +static void mtk_cirq_unmask(struct irq_data *data)
> > +{
> > + mtk_cirq_write_mask(data, CIRQ_MASK_CLR);
> > + irq_chip_unmask_parent(data);
> > +}
> > +
> > +static void mtk_cirq_eoi(struct irq_data *data)
> > +{
> > + mtk_cirq_write_mask(data, CIRQ_ACK);
>
> EOI and ACK have very different semantics. What is this write actually
> doing? Also, you're now doing an additional MMIO write on each interrupt
> EOI, doubling its cost. Do you really need to do actually signal the HW
> that we've EOIed an interrupt? I would have hoped that you'd be able to
> put it in "bypass" mode as long as you're not suspending...
>
When external interrupt happened, CIRQ status register record the status
even CIRQ is not enabled. when execute the flush command, CIRQ will
resend the signals according to the status. So if don't clear the
status, CIRQ will resend the wrong signals. the ACK write operation will
clear the status.
> > + irq_chip_eoi_parent(data);
> > +}
> > +
> > +static int mtk_cirq_set_type(struct irq_data *data, unsigned int type)
> > +{
> > + int ret;
> > +
> > + switch (type & IRQ_TYPE_SENSE_MASK) {
> > + case IRQ_TYPE_EDGE_FALLING:
> > + mtk_cirq_write_mask(data, CIRQ_POL_CLR);
> > + mtk_cirq_write_mask(data, CIRQ_SENS_CLR);
> > + break;
> > + case IRQ_TYPE_EDGE_RISING:
> > + mtk_cirq_write_mask(data, CIRQ_POL_SET);
> > + mtk_cirq_write_mask(data, CIRQ_SENS_CLR);
> > + break;
> > + case IRQ_TYPE_LEVEL_LOW:
> > + mtk_cirq_write_mask(data, CIRQ_POL_CLR);
> > + mtk_cirq_write_mask(data, CIRQ_SENS_SET);
> > + break;
> > + case IRQ_TYPE_LEVEL_HIGH:
> > + mtk_cirq_write_mask(data, CIRQ_POL_SET);
> > + mtk_cirq_write_mask(data, CIRQ_SENS_SET);
> > + break;
> > + default:
> > + break;
> > + }
> > +
> > + data = data->parent_data;
> > + ret = data->chip->irq_set_type(data, type);
> > + return ret;
> > +}
> > +
> > +static struct irq_chip mtk_cirq_chip = {
> > + .name = "MT_CIRQ",
> > + .irq_mask = mtk_cirq_mask,
> > + .irq_unmask = mtk_cirq_unmask,
> > + .irq_eoi = mtk_cirq_eoi,
> > + .irq_set_type = mtk_cirq_set_type,
> > + .irq_retrigger = irq_chip_retrigger_hierarchy,
> > +#ifdef CONFIG_SMP
> > + .irq_set_affinity = irq_chip_set_affinity_parent,
> > +#endif
> > +};
> > +
> > +static int mtk_cirq_domain_translate(struct irq_domain *d,
> > + struct irq_fwspec *fwspec,
> > + unsigned long *hwirq,
> > + unsigned int *type)
> > +{
> > + if (is_of_node(fwspec->fwnode)) {
> > + if (fwspec->param_count != 3)
> > + return -EINVAL;
> > +
> > + /* No PPI should point to this domain */
> > + if (fwspec->param[0] != 0)
> > + return -EINVAL;
> > +
> > + /* cirq support irq number check */
> > + if (fwspec->param[1] < cirq_data->ext_irq_start)
> > + return -EINVAL;
> > +
> > + *hwirq = fwspec->param[1] - cirq_data->ext_irq_start;
>
> What if the result is > CIRQ_IRQ_NUM?
will add CIRQ supported irq range in DT, and do range check here in next
version.
>
> > + *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
> > + return 0;
> > + }
> > +
> > + return -EINVAL;
> > +}
> > +
> > +static int mtk_cirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
> > + unsigned int nr_irqs, void *arg)
> > +{
> > + int i;
> > + irq_hw_number_t hwirq;
> > + struct irq_fwspec *fwspec = arg;
> > + struct irq_fwspec parent_fwspec = *fwspec;
> > +
> > + if (fwspec->param_count != 3)
> > + return -EINVAL;
> > +
> > + /* cirq doesn't support PPI */
> > + if (fwspec->param[0])
> > + return -EINVAL;
> > +
> > + if (fwspec->param[1] < cirq_data->ext_irq_start)
> > + return -EINVAL;
> > +
> > + hwirq = fwspec->param[1] - cirq_data->ext_irq_start;
>
> All this is a pure copy of mtk_cirq_domain_translate(). Please use it.
will fix in next version.
> > + for (i = 0; i < nr_irqs; i++)
> > + irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
> > + &mtk_cirq_chip,
> > + domain->host_data);
>
> This is a bit silly. This loop only exists for the benefit of MSI
> support, which we're not dealing with here. So please stick a
>
> if (WARN_ON(nr_irqs != 1))
> return -EINVAL;
>
> and drop the loop.
will fix in next version.
>
> > +
> > + parent_fwspec.fwnode = domain->parent->fwnode;
> > + return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
> > + &parent_fwspec);
> > +}
> > +
> > +static const struct irq_domain_ops cirq_domain_ops = {
> > + .translate = mtk_cirq_domain_translate,
> > + .alloc = mtk_cirq_domain_alloc,
> > + .free = irq_domain_free_irqs_common,
> > +};
> > +
> > +#ifdef CONFIG_PM_SLEEP
> > +static int mtk_cirq_suspend(void)
> > +{
> > + u32 value;
> > +
> > + /* set edge_only mode, record edge-triggerd interrupts */
> > + /* enable cirq */
> > + value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
> > + value |= (CIRQ_EDGE | CIRQ_EN);
> > + writel(value, cirq_data->base + CIRQ_CONTROL);
>
> You're mixing relaxed and non-relaxed accessors. Why?
will change writel to writel_relaxed in next version.
>
> > + return 0;
> > +}
> > +
> > +static void mtk_cirq_resume(void)
> > +{
> > + u32 value;
> > +
> > + /* flush recored interrupts, will send signals to parent controller */
> > + value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
> > + writel(value | CIRQ_FLUSH, cirq_data->base + CIRQ_CONTROL);
>
> Same remark.
will change writel to writel_relaxed in next version.
>
> > +
> > + /* disable cirq */
> > + value = readl_relaxed(cirq_data->base + CIRQ_CONTROL);
> > + value &= ~(CIRQ_EDGE | CIRQ_EN);
> > + writel(value, cirq_data->base + CIRQ_CONTROL);
>
> So from this, I infer that CIRQ is not enabled when the kernel is
> running (not suspended). It really makes me wonder why you need to do
> anything in the EOI callback.
>
> > +}
> > +
> > +static struct syscore_ops mtk_cirq_syscore_ops = {
> > + .suspend = mtk_cirq_suspend,
> > + .resume = mtk_cirq_resume,
> > +};
> > +
> > +static void mtk_cirq_syscore_init(void)
> > +{
> > + register_syscore_ops(&mtk_cirq_syscore_ops);
> > +}
> > +#else
> > +static inline void mtk_cirq_syscore_init(void) {}
> > +#endif
> > +
> > +static int __init mtk_cirq_of_init(struct device_node *node,
> > + struct device_node *parent)
> > +{
> > + struct irq_domain *domain, *domain_parent;
> > + int ret;
> > +
> > + domain_parent = irq_find_host(parent);
> > + if (!domain_parent) {
> > + pr_err("mtk_cirq: interrupt-parent not found\n");
> > + return -EINVAL;
> > + }
> > +
> > + cirq_data = kzalloc(sizeof(*cirq_data), GFP_KERNEL);
> > + if (!cirq_data)
> > + return -ENOMEM;
> > +
> > + cirq_data->base = of_iomap(node, 0);
> > + if (!cirq_data->base) {
> > + pr_err("mtk_cirq: unable to map cirq register\n");
> > + ret = -ENXIO;
> > + goto out_free;
> > + }
> > +
> > + ret = of_property_read_u32(node, "mediatek,ext-irq-start",
> > + &cirq_data->ext_irq_start);
> > + if (ret)
> > + goto out_unmap;
> > +
> > + domain = irq_domain_add_hierarchy(domain_parent, 0, CIRQ_IRQ_NUM, node,
> > + &cirq_domain_ops, cirq_data);
>
> So you support at most 512 interrupts, and yet the GIC supports up to
> 987 SPIs. What happens for interrupt lines that out of the CIRQ range?
> Maybe having an explicit range in DT would be a good thing. That also
> brings back the question of having a single CIRQ in the system...
>
In next version, i will add an explicit CIRQ supported range in DT.
Thanks a lot!
> > + if (!domain) {
> > + ret = -ENOMEM;
> > + goto out_unmap;
> > + }
> > +
> > + mtk_cirq_syscore_init();
> > +
> > + return 0;
> > +
> > +out_unmap:
> > + iounmap(cirq_data->base);
> > +out_free:
> > + kfree(cirq_data);
> > + return ret;
> > +}
> > +
> > +IRQCHIP_DECLARE(mtk_cirq, "mediatek,mtk-cirq", mtk_cirq_of_init);
>
> Thanks,
>
> M.
^ permalink raw reply
* [PATCH v2 2/2] power: bq27xxx_battery: add poll interval property query
From: Matt Ranostay @ 2016-11-04 5:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161102082206.GE21488@amd>
On Wed, Nov 2, 2016 at 1:22 AM, Pavel Machek <pavel@ucw.cz> wrote:
> Hi!
>
>> >> >> Better then previous one.
>> >> >>
>> >> >> But my version of bq27xxx_battery.c already contains this:
>> >> >
>> >> > This is for allowing udev rule to set the properties as well.
>> >> > otherwise a kinda crude RUN = " echo value >
>> >> > /sys/module/bq27xxx_battery/parameters/poll_interval" is required.
>> >>
>> >> Any thoughts on this?
>> >
>> > I'd say echo value >
>> > /sys/module/bq27xxx_battery/parameters/poll_interval .. is quite
>> > adequate solution...?
>> >
>> > Alternatively, convince us that something else is useful for everyone,
>> > and we can do the right thing (poll more often when battery is nearly
>> > empty), automatically...
>>
>> Ok should have had the patchset set it per device, and not use the
>> global poll_interval. Of need to add some logic to see if uses the
>> global poll_interval or it's own setting.
>>
>> There are times where you could have multiple batteries connected to
>> multiple fuel gauges, and want to up the polling interval on certain
>> ones that are discharging at different rates.
>>
>> But of course I'll let you guys let me know if this seems useful at all.
>
> I agree per-device polling would be cleaner.
>
Ok I'll work something up for RFC.
> But unless you have hardware with more than one bq27xxx, I'd avoid the
> work...
>
> Now... its also possible that poll_interval should change itself
> (within kernel) to do the right thing.
>
True but that is state machine territory, but I'll worry about that later...
> Best regards,
>
> Pavel
> --
> (english) http://www.livejournal.com/~pavelmachek
> (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply
* [RESEND PATCH v1 05/11] dt-bindings: perf: hisi: Add Devicetree bindings for Hisilicon SoC PMU
From: Anurup M @ 2016-11-04 5:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161103182609.GA11071@kozik-lap>
On Thursday 03 November 2016 11:56 PM, Krzysztof Kozlowski wrote:
> On Thu, Nov 03, 2016 at 01:42:01AM -0400, Anurup M wrote:
>> 1) Device tree bindings for Hisilicon SoC PMU.
>> 2) Add example for Hisilicon L3 cache, MN and DDRC PMU.
> Get rid of this weird indentation in all patches.
Thanks. I shall remove the TAB from the commit message in all patches.
>
>> Signed-off-by: Anurup M <anurup.m@huawei.com>
>> Signed-off-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
>> ---
>> .../devicetree/bindings/arm/hisilicon/pmu.txt | 127 +++++++++++++++++++++
>> 1 file changed, 127 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/arm/hisilicon/pmu.txt
>>
>> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/pmu.txt b/Documentation/devicetree/bindings/arm/hisilicon/pmu.txt
>> new file mode 100644
>> index 0000000..e7b35e0
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/hisilicon/pmu.txt
>> @@ -0,0 +1,127 @@
>> +Hisilicon SoC hip05/06/07 ARMv8 PMU
>> +===================================
>> +
>> +The Hisilicon SoC chips like hip05/06/07 etc. consist of varous independent
>> +system device PMU's such as L3 cache (L3C), Miscellaneous Nodes(MN) and DDR
>> +comtroller. These PMU devices are independent and have hardware logic to
>> +gather statistics and performance information.
>> +
>> +HiSilicon SoC chip is encapsulated by multiple CPU and IO die's. The CPU die
>> +is called as Super CPU cluster (SCCL) which includes 16 cpu-cores. Every SCCL
>> +is further grouped as CPU clusters (CCL) which includes 4 cpu-cores each.
>> +e.g. In the case of hip05/06/07, each SCCL has 1 L3 cache and 1 MN PMU device.
>> +
>> +The Hisilicon SoC PMU DT node bindigs for uncore PMU devices are as below.
>> +For PMU devices like L3 cache. MN etc. which are accessed using the djtag,
>> +the parent node will be the djtag node of the corresponding CPU die(SCCL).
>> +
>> +For uncore PMU devices there are some common required properties as detailed
>> +below.
>> +
>> +Required properties:
>> + - compatible : This field contain two values. The first value is
>> + always "hisilicon" and second value is the Module type as shown
>> + in below examples:
> Over-complicated sentence. Just:
>
> - compatible : One of:
> "hisilicon,hisi-pmu-l3c-v1" for Hisilicon SoC L3C PMU
> device (Version 1)
> ...
> ...
Thanks. Shall refine it in next version.
> BTW, No need of CC-ing me. I am not a maintainer of relevant subsystems.
Sure.
Thanks,
Anurup
> Best regards,
> Krzysztof
^ permalink raw reply
* [PATCH v6 0/7] add NS2 support to bgmac
From: Jon Mason @ 2016-11-04 5:10 UTC (permalink / raw)
To: linux-arm-kernel
Changes in v6:
* Use a common bgmac_phy_connect_direct (per Rafal Milecki)
* Rebased on latest net-next
* Added Reviewed-by to the relevant patches
Changes in v5:
* Change a pr_err to netdev_err (per Scott Branden)
* Reword the lane swap binding documentation (per Andrew Lunn)
Changes in v4:
* Actually send out the lane swap binding doc patch (Per Scott Branden)
* Remove unused #define (Per Andrew Lunn)
Changes in v3:
* Clean-up the bgmac DT binding doc (per Rob Herring)
* Document the lane swap binding and make it generic (Per Andrew Lunn)
Changes in v2:
* Remove the PHY power-on (per Andrew Lunn)
* Misc PHY clean-ups regarding comments and #defines (per Andrew Lunn)
This results on none of the original PHY code from Vikas being
present. So, I'm removing him as an author and giving him
"Inspired-by" credit.
* Move PHY lane swapping to PHY driver (per Andrew Lunn and Florian
Fainelli)
* Remove bgmac sleep (per Florian Fainelli)
* Re-add bgmac chip reset (per Florian Fainelli and Ray Jui)
* Rebased on latest net-next
* Added patch for bcm54xx_auxctl_read, which is used in the BCM54810
Jon Mason (7):
net: phy: broadcom: add bcm54xx_auxctl_read
Documentation: devicetree: add PHY lane swap binding
net: phy: broadcom: Add BCM54810 PHY entry
Documentation: devicetree: net: add NS2 bindings to amac
net: ethernet: bgmac: device tree phy enablement
net: ethernet: bgmac: add NS2 support
arm64: dts: NS2: add AMAC ethernet support
.../devicetree/bindings/net/brcm,amac.txt | 16 +++--
Documentation/devicetree/bindings/net/phy.txt | 4 ++
arch/arm64/boot/dts/broadcom/ns2-svk.dts | 5 ++
arch/arm64/boot/dts/broadcom/ns2.dtsi | 12 ++++
drivers/net/ethernet/broadcom/bgmac-bcma.c | 22 +++++++
drivers/net/ethernet/broadcom/bgmac-platform.c | 74 +++++++++++++++++++++-
drivers/net/ethernet/broadcom/bgmac.c | 32 +++-------
drivers/net/ethernet/broadcom/bgmac.h | 9 +++
drivers/net/phy/Kconfig | 2 +-
drivers/net/phy/broadcom.c | 68 +++++++++++++++++++-
include/linux/brcmphy.h | 10 +++
11 files changed, 222 insertions(+), 32 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH v6 1/7] net: phy: broadcom: add bcm54xx_auxctl_read
From: Jon Mason @ 2016-11-04 5:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478236262-3351-1-git-send-email-jon.mason@broadcom.com>
Add a helper function to read the AUXCTL register for the BCM54xx. This
mirrors the bcm54xx_auxctl_write function already present in the code.
Signed-off-by: Jon Mason <jon.mason@broadcom.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/phy/broadcom.c | 10 ++++++++++
include/linux/brcmphy.h | 1 +
2 files changed, 11 insertions(+)
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 583ef8a..3a64b3d 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -30,6 +30,16 @@ MODULE_DESCRIPTION("Broadcom PHY driver");
MODULE_AUTHOR("Maciej W. Rozycki");
MODULE_LICENSE("GPL");
+static int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum)
+{
+ /* The register must be written to both the Shadow Register Select and
+ * the Shadow Read Register Selector
+ */
+ phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum |
+ regnum << MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT);
+ return phy_read(phydev, MII_BCM54XX_AUX_CTL);
+}
+
static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
{
return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h
index 60def78..0ed6691 100644
--- a/include/linux/brcmphy.h
+++ b/include/linux/brcmphy.h
@@ -110,6 +110,7 @@
#define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX 0x0200
#define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC 0x7000
#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x0007
+#define MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT 12
#define MII_BCM54XX_AUXCTL_SHDWSEL_MASK 0x0007
--
2.7.4
^ permalink raw reply related
* [PATCH v6 2/7] Documentation: devicetree: add PHY lane swap binding
From: Jon Mason @ 2016-11-04 5:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478236262-3351-1-git-send-email-jon.mason@broadcom.com>
Add the documentation for PHY lane swapping. This is a boolean entry to
notify the phy device drivers that the TX/RX lanes need to be swapped.
Signed-off-by: Jon Mason <jon.mason@broadcom.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
Documentation/devicetree/bindings/net/phy.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/phy.txt b/Documentation/devicetree/bindings/net/phy.txt
index bc1c3c8..4627da3 100644
--- a/Documentation/devicetree/bindings/net/phy.txt
+++ b/Documentation/devicetree/bindings/net/phy.txt
@@ -35,6 +35,10 @@ Optional Properties:
- broken-turn-around: If set, indicates the PHY device does not correctly
release the turn around line low at the end of a MDIO transaction.
+- enet-phy-lane-swap: If set, indicates the PHY will swap the TX/RX lanes to
+ compensate for the board being designed with the lanes swapped.
+
+
Example:
ethernet-phy at 0 {
--
2.7.4
^ permalink raw reply related
* [PATCH v6 3/7] net: phy: broadcom: Add BCM54810 PHY entry
From: Jon Mason @ 2016-11-04 5:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478236262-3351-1-git-send-email-jon.mason@broadcom.com>
The BCM54810 PHY requires some semi-unique configuration, which results
in some additional configuration in addition to the standard config.
Also, some users of the BCM54810 require the PHY lanes to be swapped.
Since there is no way to detect this, add a device tree query to see if
it is applicable.
Inspired-by: Vikas Soni <vsoni@broadcom.com>
Signed-off-by: Jon Mason <jon.mason@broadcom.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
drivers/net/phy/Kconfig | 2 +-
drivers/net/phy/broadcom.c | 58 +++++++++++++++++++++++++++++++++++++++++++++-
include/linux/brcmphy.h | 9 +++++++
3 files changed, 67 insertions(+), 2 deletions(-)
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index ff31c10..d3fcfd2 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -217,7 +217,7 @@ config BROADCOM_PHY
select BCM_NET_PHYLIB
---help---
Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
- BCM5481 and BCM5482 PHYs.
+ BCM5481, BCM54810 and BCM5482 PHYs.
config CICADA_PHY
tristate "Cicada PHYs"
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 3a64b3d..b1e32e9 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -18,7 +18,7 @@
#include <linux/module.h>
#include <linux/phy.h>
#include <linux/brcmphy.h>
-
+#include <linux/of.h>
#define BRCM_PHY_MODEL(phydev) \
((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
@@ -45,6 +45,34 @@ static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
}
+static int bcm54810_config(struct phy_device *phydev)
+{
+ int rc, val;
+
+ val = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
+ val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
+ rc = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL,
+ val);
+ if (rc < 0)
+ return rc;
+
+ val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
+ val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
+ val |= MII_BCM54XX_AUXCTL_MISC_WREN;
+ rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
+ val);
+ if (rc < 0)
+ return rc;
+
+ val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
+ val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
+ rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
/* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
static int bcm50610_a0_workaround(struct phy_device *phydev)
{
@@ -217,6 +245,12 @@ static int bcm54xx_config_init(struct phy_device *phydev)
(phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
bcm54xx_adjust_rxrefclk(phydev);
+ if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
+ err = bcm54810_config(phydev);
+ if (err)
+ return err;
+ }
+
bcm54xx_phydsp_config(phydev);
return 0;
@@ -314,6 +348,7 @@ static int bcm5482_read_status(struct phy_device *phydev)
static int bcm5481_config_aneg(struct phy_device *phydev)
{
+ struct device_node *np = phydev->mdio.dev.of_node;
int ret;
/* Aneg firsly. */
@@ -344,6 +379,14 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
phy_write(phydev, 0x18, reg);
}
+ if (of_property_read_bool(np, "enet-phy-lane-swap")) {
+ /* Lane Swap - Undocumented register...magic! */
+ ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9,
+ 0x11B);
+ if (ret < 0)
+ return ret;
+ }
+
return ret;
}
@@ -578,6 +621,18 @@ static struct phy_driver broadcom_drivers[] = {
.ack_interrupt = bcm_phy_ack_intr,
.config_intr = bcm_phy_config_intr,
}, {
+ .phy_id = PHY_ID_BCM54810,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Broadcom BCM54810",
+ .features = PHY_GBIT_FEATURES |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+ .config_init = bcm54xx_config_init,
+ .config_aneg = bcm5481_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = bcm_phy_ack_intr,
+ .config_intr = bcm_phy_config_intr,
+}, {
.phy_id = PHY_ID_BCM5482,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5482",
@@ -661,6 +716,7 @@ static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
{ PHY_ID_BCM54616S, 0xfffffff0 },
{ PHY_ID_BCM5464, 0xfffffff0 },
{ PHY_ID_BCM5481, 0xfffffff0 },
+ { PHY_ID_BCM54810, 0xfffffff0 },
{ PHY_ID_BCM5482, 0xfffffff0 },
{ PHY_ID_BCM50610, 0xfffffff0 },
{ PHY_ID_BCM50610M, 0xfffffff0 },
diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h
index 0ed6691..848dc50 100644
--- a/include/linux/brcmphy.h
+++ b/include/linux/brcmphy.h
@@ -13,6 +13,7 @@
#define PHY_ID_BCM5241 0x0143bc30
#define PHY_ID_BCMAC131 0x0143bc70
#define PHY_ID_BCM5481 0x0143bca0
+#define PHY_ID_BCM54810 0x03625d00
#define PHY_ID_BCM5482 0x0143bcb0
#define PHY_ID_BCM5411 0x00206070
#define PHY_ID_BCM5421 0x002060e0
@@ -56,6 +57,7 @@
#define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00002000
#define PHY_BRCM_CLEAR_RGMII_MODE 0x00004000
#define PHY_BRCM_DIS_TXCRXC_NOENRGY 0x00008000
+
/* Broadcom BCM7xxx specific workarounds */
#define PHY_BRCM_7XXX_REV(x) (((x) >> 8) & 0xff)
#define PHY_BRCM_7XXX_PATCH(x) ((x) & 0xff)
@@ -111,6 +113,7 @@
#define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC 0x7000
#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x0007
#define MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT 12
+#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN (1 << 8)
#define MII_BCM54XX_AUXCTL_SHDWSEL_MASK 0x0007
@@ -192,6 +195,12 @@
#define BCM5482_SSD_SGMII_SLAVE_EN 0x0002 /* Slave mode enable */
#define BCM5482_SSD_SGMII_SLAVE_AD 0x0001 /* Slave auto-detection */
+/* BCM54810 Registers */
+#define BCM54810_EXP_BROADREACH_LRE_MISC_CTL (MII_BCM54XX_EXP_SEL_ER + 0x90)
+#define BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN (1 << 0)
+#define BCM54810_SHD_CLK_CTL 0x3
+#define BCM54810_SHD_CLK_CTL_GTXCLK_EN (1 << 9)
+
/*****************************************************************************/
/* Fast Ethernet Transceiver definitions. */
--
2.7.4
^ permalink raw reply related
* [PATCH v6 4/7] Documentation: devicetree: net: add NS2 bindings to amac
From: Jon Mason @ 2016-11-04 5:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478236262-3351-1-git-send-email-jon.mason@broadcom.com>
Clean-up the documentation to the bgmac-amac driver, per suggestion by
Rob Herring, and add details for NS2 support.
Signed-off-by: Jon Mason <jon.mason@broadcom.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
---
Documentation/devicetree/bindings/net/brcm,amac.txt | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/brcm,amac.txt b/Documentation/devicetree/bindings/net/brcm,amac.txt
index ba5ecc1..2fefa1a 100644
--- a/Documentation/devicetree/bindings/net/brcm,amac.txt
+++ b/Documentation/devicetree/bindings/net/brcm,amac.txt
@@ -2,11 +2,17 @@ Broadcom AMAC Ethernet Controller Device Tree Bindings
-------------------------------------------------------------
Required properties:
- - compatible: "brcm,amac" or "brcm,nsp-amac"
- - reg: Address and length of the GMAC registers,
- Address and length of the GMAC IDM registers
- - reg-names: Names of the registers. Must have both "amac_base" and
- "idm_base"
+ - compatible: "brcm,amac"
+ "brcm,nsp-amac"
+ "brcm,ns2-amac"
+ - reg: Address and length of the register set for the device. It
+ contains the information of registers in the same order as
+ described by reg-names
+ - reg-names: Names of the registers.
+ "amac_base": Address and length of the GMAC registers
+ "idm_base": Address and length of the GMAC IDM registers
+ "nicpm_base": Address and length of the NIC Port Manager
+ registers (required for Northstar2)
- interrupts: Interrupt number
Optional properties:
--
2.7.4
^ permalink raw reply related
* [PATCH v6 5/7] net: ethernet: bgmac: device tree phy enablement
From: Jon Mason @ 2016-11-04 5:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478236262-3351-1-git-send-email-jon.mason@broadcom.com>
Change the bgmac driver to allow for phy's defined by the device tree
Signed-off-by: Jon Mason <jon.mason@broadcom.com>
---
drivers/net/ethernet/broadcom/bgmac-bcma.c | 22 +++++++++++++++++++
drivers/net/ethernet/broadcom/bgmac-platform.c | 22 ++++++++++++++++++-
drivers/net/ethernet/broadcom/bgmac.c | 29 +++++---------------------
drivers/net/ethernet/broadcom/bgmac.h | 8 +++++++
4 files changed, 56 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bgmac-bcma.c b/drivers/net/ethernet/broadcom/bgmac-bcma.c
index c16ec3a..4a4ffc0 100644
--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
@@ -80,6 +80,24 @@ static void bcma_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset, u32 mask,
bcma_maskset32(bgmac->bcma.cmn, offset, mask, set);
}
+static int bcma_phy_connect(struct bgmac *bgmac)
+{
+ struct phy_device *phy_dev;
+ char bus_id[MII_BUS_ID_SIZE + 3];
+
+ /* Connect to the PHY */
+ snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id,
+ bgmac->phyaddr);
+ phy_dev = phy_connect(bgmac->net_dev, bus_id, bgmac_adjust_link,
+ PHY_INTERFACE_MODE_MII);
+ if (IS_ERR(phy_dev)) {
+ dev_err(bgmac->dev, "PHY connection failed\n");
+ return PTR_ERR(phy_dev);
+ }
+
+ return 0;
+}
+
static const struct bcma_device_id bgmac_bcma_tbl[] = {
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT,
BCMA_ANY_REV, BCMA_ANY_CLASS),
@@ -275,6 +293,10 @@ static int bgmac_probe(struct bcma_device *core)
bgmac->cco_ctl_maskset = bcma_bgmac_cco_ctl_maskset;
bgmac->get_bus_clock = bcma_bgmac_get_bus_clock;
bgmac->cmn_maskset32 = bcma_bgmac_cmn_maskset32;
+ if (bgmac->mii_bus)
+ bgmac->phy_connect = bcma_phy_connect;
+ else
+ bgmac->phy_connect = bgmac_phy_connect_direct;
err = bgmac_enet_probe(bgmac);
if (err)
diff --git a/drivers/net/ethernet/broadcom/bgmac-platform.c b/drivers/net/ethernet/broadcom/bgmac-platform.c
index be52f27..4642940 100644
--- a/drivers/net/ethernet/broadcom/bgmac-platform.c
+++ b/drivers/net/ethernet/broadcom/bgmac-platform.c
@@ -16,6 +16,7 @@
#include <linux/bcma/bcma.h>
#include <linux/etherdevice.h>
#include <linux/of_address.h>
+#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include "bgmac.h"
@@ -86,6 +87,20 @@ static void platform_bgmac_cmn_maskset32(struct bgmac *bgmac, u16 offset,
WARN_ON(1);
}
+static int platform_phy_connect(struct bgmac *bgmac)
+{
+ struct phy_device *phy_dev;
+
+ phy_dev = of_phy_get_and_connect(bgmac->net_dev, bgmac->dev->of_node,
+ bgmac_adjust_link);
+ if (!phy_dev) {
+ dev_err(bgmac->dev, "PHY connection failed\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
static int bgmac_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -102,7 +117,6 @@ static int bgmac_probe(struct platform_device *pdev)
/* Set the features of the 4707 family */
bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
- bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4;
bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP;
bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP;
@@ -151,6 +165,12 @@ static int bgmac_probe(struct platform_device *pdev)
bgmac->cco_ctl_maskset = platform_bgmac_cco_ctl_maskset;
bgmac->get_bus_clock = platform_bgmac_get_bus_clock;
bgmac->cmn_maskset32 = platform_bgmac_cmn_maskset32;
+ if (of_parse_phandle(np, "phy-handle", 0)) {
+ bgmac->phy_connect = platform_phy_connect;
+ } else {
+ bgmac->phy_connect = bgmac_phy_connect_direct;
+ bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
+ }
return bgmac_enet_probe(bgmac);
}
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 31ca204..7f66ea7 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -1388,7 +1388,7 @@ static const struct ethtool_ops bgmac_ethtool_ops = {
* MII
**************************************************/
-static void bgmac_adjust_link(struct net_device *net_dev)
+void bgmac_adjust_link(struct net_device *net_dev)
{
struct bgmac *bgmac = netdev_priv(net_dev);
struct phy_device *phy_dev = net_dev->phydev;
@@ -1411,8 +1411,9 @@ static void bgmac_adjust_link(struct net_device *net_dev)
phy_print_status(phy_dev);
}
}
+EXPORT_SYMBOL_GPL(bgmac_adjust_link);
-static int bgmac_phy_connect_direct(struct bgmac *bgmac)
+int bgmac_phy_connect_direct(struct bgmac *bgmac)
{
struct fixed_phy_status fphy_status = {
.link = 1,
@@ -1437,24 +1438,7 @@ static int bgmac_phy_connect_direct(struct bgmac *bgmac)
return err;
}
-
-static int bgmac_phy_connect(struct bgmac *bgmac)
-{
- struct phy_device *phy_dev;
- char bus_id[MII_BUS_ID_SIZE + 3];
-
- /* Connect to the PHY */
- snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id,
- bgmac->phyaddr);
- phy_dev = phy_connect(bgmac->net_dev, bus_id, &bgmac_adjust_link,
- PHY_INTERFACE_MODE_MII);
- if (IS_ERR(phy_dev)) {
- dev_err(bgmac->dev, "PHY connection failed\n");
- return PTR_ERR(phy_dev);
- }
-
- return 0;
-}
+EXPORT_SYMBOL_GPL(bgmac_phy_connect_direct);
int bgmac_enet_probe(struct bgmac *info)
{
@@ -1507,10 +1491,7 @@ int bgmac_enet_probe(struct bgmac *info)
netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);
- if (!bgmac->mii_bus)
- err = bgmac_phy_connect_direct(bgmac);
- else
- err = bgmac_phy_connect(bgmac);
+ err = bgmac_phy_connect(bgmac);
if (err) {
dev_err(bgmac->dev, "Cannot connect to phy\n");
goto err_dma_free;
diff --git a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h
index 80836b4..bfd9f40 100644
--- a/drivers/net/ethernet/broadcom/bgmac.h
+++ b/drivers/net/ethernet/broadcom/bgmac.h
@@ -513,10 +513,13 @@ struct bgmac {
u32 (*get_bus_clock)(struct bgmac *bgmac);
void (*cmn_maskset32)(struct bgmac *bgmac, u16 offset, u32 mask,
u32 set);
+ int (*phy_connect)(struct bgmac *bgmac);
};
int bgmac_enet_probe(struct bgmac *info);
void bgmac_enet_remove(struct bgmac *bgmac);
+void bgmac_adjust_link(struct net_device *net_dev);
+int bgmac_phy_connect_direct(struct bgmac *bgmac);
struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr);
void bcma_mdio_mii_unregister(struct mii_bus *mii_bus);
@@ -583,4 +586,9 @@ static inline void bgmac_set(struct bgmac *bgmac, u16 offset, u32 set)
{
bgmac_maskset(bgmac, offset, ~0, set);
}
+
+static inline int bgmac_phy_connect(struct bgmac *bgmac)
+{
+ return bgmac->phy_connect(bgmac);
+}
#endif /* _BGMAC_H */
--
2.7.4
^ 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