Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ARM: shmobile: select errata 798181 for SoCs with CA15 cores
From: Magnus Damm @ 2016-10-27  7:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMuHMdVKwg0SzEmu804UxTEE+N4atYjeKHNfCJ0eXf28fL+KJA@mail.gmail.com>

Hi Geert and Simon,

On Thu, Oct 27, 2016 at 4:33 PM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> Hi Magnus,
>
> On Thu, Oct 27, 2016 at 9:28 AM, Magnus Damm <magnus.damm@gmail.com> wrote:
>> On Thu, Oct 27, 2016 at 4:00 PM, Simon Horman
>> <horms+renesas@verge.net.au> wrote:
>>> Select ARM errata 798181 on SoCs cores affected CA15 cores.
>>>
>>> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
>>> ---
>>>  arch/arm/mach-shmobile/Kconfig | 6 ++++++
>>>  1 file changed, 6 insertions(+)
>>>
>>> diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
>>> index c48be1d332ed..6fbd9b7d2d67 100644
>>> --- a/arch/arm/mach-shmobile/Kconfig
>>> +++ b/arch/arm/mach-shmobile/Kconfig
>>> @@ -60,6 +60,7 @@ config ARCH_R7S72100
>>>  config ARCH_R8A73A4
>>>         bool "R-Mobile APE6 (R8A73A40)"
>>>         select ARCH_RMOBILE
>>> +       select ARM_ERRATA_798181 if SMP
>>>         select RENESAS_IRQC
>>>
>>>  config ARCH_R8A7740
>>> @@ -70,6 +71,7 @@ config ARCH_R8A7740
>>>  config ARCH_R8A7743
>>>         bool "RZ/G1M (R8A77430)"
>>>         select ARCH_RCAR_GEN2
>>> +       select ARM_ERRATA_798181 if SMP
>>>
>>>  config ARCH_R8A7778
>>>         bool "R-Car M1A (R8A77781)"
>>> @@ -82,20 +84,24 @@ config ARCH_R8A7779
>>>  config ARCH_R8A7790
>>>         bool "R-Car H2 (R8A77900)"
>>>         select ARCH_RCAR_GEN2
>>> +       select ARM_ERRATA_798181 if SMP
>>>         select I2C
>>
>> Thanks for your help.
>>
>> I'm probably misunderstanding what this patch does and how the errata
>> effects the system, but the commit message says CA15 cores. The above
>> R-Car Gen1 and r8a7740 SoCs are not using CA15 - instead they use CA9.
>> Not sure if the errata still applies though.
>
> Please don't become misled by the @@ context ;-)

Ouch, right... Sorry for the noise. The patch looks good, please proceed.

Thanks,

/ magnus

^ permalink raw reply

* [PATCH] fpga zynq: Check the bitstream for validity
From: Michal Simek @ 2016-10-27  7:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161026225413.GA6220@obsidianresearch.com>

On 27.10.2016 00:54, Jason Gunthorpe wrote:
> There is no sense in sending a bitstream we know will not work, and
> with the variety of options for bitstream generation in Xilinx tools
> it is not terribly clear or very well documented what the correct
> input should be, especially since auto-detection was removed from this
> driver.
> 
> All Zynq full configuration bitstreams must start with the sync word in
> the correct byte order.
> 
> Zynq is also only able to DMA dword quantities, so bitstreams must be
> a multiple of 4 bytes. This also fixes a DMA-past the end bug.
> 
> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> ---
>  drivers/fpga/zynq-fpga.c | 25 ++++++++++++++++---------
>  1 file changed, 16 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
> index c2fb4120bd62..46a38772e7ee 100644
> --- a/drivers/fpga/zynq-fpga.c
> +++ b/drivers/fpga/zynq-fpga.c
> @@ -184,12 +184,26 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
>  
>  	priv = mgr->priv;
>  
> +	/* All valid bitstreams are multiples of 32 bits */
> +	if ((count % 4) != 0)
> +		return -EINVAL;
> +
>  	err = clk_enable(priv->clk);
>  	if (err)
>  		return err;
>  
>  	/* don't globally reset PL if we're doing partial reconfig */
>  	if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) {
> +		/* Sanity check the proposed bitstream. It must start with the
> +		 * sync word in the correct byte order and be a multiple of 4
> +		 * bytes.
> +		 */
> +		if (count <= 4 || buf[0] != 0x66 || buf[1] != 0x55 ||
> +		    buf[2] != 0x99 || buf[3] != 0xaa) {
> +			err = -EINVAL;
> +			goto out_err;
> +		}

I am not quite sure about this and I didn't try it on real hw.
But minimum bitstream size 52+B and more likely much more than this.

This is taken from u-boot source code and this is full BIN header.
The code above is checking only the last word.

#define DUMMY_WORD      0xffffffff

/* Xilinx binary format header */
static const u32 bin_format[] = {
        DUMMY_WORD, /* Dummy words */
        DUMMY_WORD,
        DUMMY_WORD,
        DUMMY_WORD,
        DUMMY_WORD,
        DUMMY_WORD,
        DUMMY_WORD,
        DUMMY_WORD,
        0x000000bb, /* Sync word */
        0x11220044, /* Sync word */
        DUMMY_WORD,
        DUMMY_WORD,
        0xaa995566, /* Sync word */
};

Thanks,
Michal

^ permalink raw reply

* [PATCH 0/5] Minimal cpuidle fixes for omap5 and dra7
From: H. Nikolaus Schaller @ 2016-10-27  7:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161026151703.24730-1-tony@atomide.com>


> Am 26.10.2016 um 17:16 schrieb Tony Lindgren <tony@atomide.com>:
> 
> Hi all,
> 
> Here are some fixes to get minimal cpuidle support working with omap5
> and dra7. Not sure if there are still some unsorted issues on enabling
> this on dra7, but at least omap5 has been behving for me for few
> weeks with these.

Seems to work on Pyra, but I could not really test.
At least it has no adverse effect.

BR,
Nikolaus

^ permalink raw reply

* [PATCH v6 1/2] MMC: meson: initial support for GX platforms
From: Ulf Hansson @ 2016-10-27  7:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161019181825.2186-1-khilman@baylibre.com>

On 19 October 2016 at 20:18, Kevin Hilman <khilman@baylibre.com> wrote:
> Initial support for the SD/eMMC controller in the Amlogic S905/GX*
> family of SoCs.
>
> Signed-off-by: Kevin Hilman <khilman@baylibre.com>

Thanks, applied for next!

Kind regards
Uffe

> ---
> Changes since v5:
> - dropped MODULE_ALIAS
> - renmaed file to meson-gx-mmc (for more useful module name)
> - update DRIVER_NAME: s/gxbb/gx/
>
>  MAINTAINERS                     |   1 +
>  drivers/mmc/host/Kconfig        |  10 +
>  drivers/mmc/host/Makefile       |   1 +
>  drivers/mmc/host/meson-gx-mmc.c | 852 ++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 864 insertions(+)
>  create mode 100644 drivers/mmc/host/meson-gx-mmc.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1cd38a7e0064..73e8d64ec28c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1036,6 +1036,7 @@ F:        arch/arm/mach-meson/
>  F:     arch/arm/boot/dts/meson*
>  F:     arch/arm64/boot/dts/amlogic/
>  F:     drivers/pinctrl/meson/
> +F:     drivers/mmc/host/meson*
>  N:     meson
>
>  ARM/Annapurna Labs ALPINE ARCHITECTURE
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index 5274f503a39a..5cf7ebaf1e8b 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -322,6 +322,16 @@ config MMC_SDHCI_IPROC
>
>           If unsure, say N.
>
> +config MMC_MESON_GX
> +       tristate "Amlogic S905/GX* SD/MMC Host Controller support"
> +       depends on ARCH_MESON && MMC
> +       help
> +         This selects support for the Amlogic SD/MMC Host Controller
> +         found on the S905/GX* family of SoCs.  This controller is
> +         MMC 5.1 compliant and supports SD, eMMC and SDIO interfaces.
> +
> +         If you have a controller with this interface, say Y here.
> +
>  config MMC_MOXART
>         tristate "MOXART SD/MMC Host Controller support"
>         depends on ARCH_MOXART && MMC
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index e2bdaaf43184..e609bf04346b 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -53,6 +53,7 @@ obj-$(CONFIG_MMC_JZ4740)      += jz4740_mmc.o
>  obj-$(CONFIG_MMC_VUB300)       += vub300.o
>  obj-$(CONFIG_MMC_USHC)         += ushc.o
>  obj-$(CONFIG_MMC_WMT)          += wmt-sdmmc.o
> +obj-$(CONFIG_MMC_MESON_GX)     += meson-gx-mmc.o
>  obj-$(CONFIG_MMC_MOXART)       += moxart-mmc.o
>  obj-$(CONFIG_MMC_SUNXI)                += sunxi-mmc.o
>  obj-$(CONFIG_MMC_USDHI6ROL0)   += usdhi6rol0.o
> diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
> new file mode 100644
> index 000000000000..1fcab7116f26
> --- /dev/null
> +++ b/drivers/mmc/host/meson-gx-mmc.c
> @@ -0,0 +1,852 @@
> +/*
> + * Amlogic SD/eMMC driver for the GX/S905 family SoCs
> + *
> + * Copyright (c) 2016 BayLibre, SAS.
> + * Author: Kevin Hilman <khilman@baylibre.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of version 2 of the GNU General Public License 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + * The full GNU General Public License is included in this distribution
> + * in the file called COPYING.
> + */
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/device.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/ioport.h>
> +#include <linux/spinlock.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/mmc/host.h>
> +#include <linux/mmc/mmc.h>
> +#include <linux/mmc/sdio.h>
> +#include <linux/mmc/slot-gpio.h>
> +#include <linux/io.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/regulator/consumer.h>
> +
> +#define DRIVER_NAME "meson-gx-mmc"
> +
> +#define SD_EMMC_CLOCK 0x0
> +#define   CLK_DIV_SHIFT 0
> +#define   CLK_DIV_WIDTH 6
> +#define   CLK_DIV_MASK 0x3f
> +#define   CLK_DIV_MAX 63
> +#define   CLK_SRC_SHIFT 6
> +#define   CLK_SRC_WIDTH 2
> +#define   CLK_SRC_MASK 0x3
> +#define   CLK_SRC_XTAL 0   /* external crystal */
> +#define   CLK_SRC_XTAL_RATE 24000000
> +#define   CLK_SRC_PLL 1    /* FCLK_DIV2 */
> +#define   CLK_SRC_PLL_RATE 1000000000
> +#define   CLK_PHASE_SHIFT 8
> +#define   CLK_PHASE_MASK 0x3
> +#define   CLK_PHASE_0 0
> +#define   CLK_PHASE_90 1
> +#define   CLK_PHASE_180 2
> +#define   CLK_PHASE_270 3
> +#define   CLK_ALWAYS_ON BIT(24)
> +
> +#define SD_EMMC_DElAY 0x4
> +#define SD_EMMC_ADJUST 0x8
> +#define SD_EMMC_CALOUT 0x10
> +#define SD_EMMC_START 0x40
> +#define   START_DESC_INIT BIT(0)
> +#define   START_DESC_BUSY BIT(1)
> +#define   START_DESC_ADDR_SHIFT 2
> +#define   START_DESC_ADDR_MASK (~0x3)
> +
> +#define SD_EMMC_CFG 0x44
> +#define   CFG_BUS_WIDTH_SHIFT 0
> +#define   CFG_BUS_WIDTH_MASK 0x3
> +#define   CFG_BUS_WIDTH_1 0x0
> +#define   CFG_BUS_WIDTH_4 0x1
> +#define   CFG_BUS_WIDTH_8 0x2
> +#define   CFG_DDR BIT(2)
> +#define   CFG_BLK_LEN_SHIFT 4
> +#define   CFG_BLK_LEN_MASK 0xf
> +#define   CFG_RESP_TIMEOUT_SHIFT 8
> +#define   CFG_RESP_TIMEOUT_MASK 0xf
> +#define   CFG_RC_CC_SHIFT 12
> +#define   CFG_RC_CC_MASK 0xf
> +#define   CFG_STOP_CLOCK BIT(22)
> +#define   CFG_CLK_ALWAYS_ON BIT(18)
> +#define   CFG_AUTO_CLK BIT(23)
> +
> +#define SD_EMMC_STATUS 0x48
> +#define   STATUS_BUSY BIT(31)
> +
> +#define SD_EMMC_IRQ_EN 0x4c
> +#define   IRQ_EN_MASK 0x3fff
> +#define   IRQ_RXD_ERR_SHIFT 0
> +#define   IRQ_RXD_ERR_MASK 0xff
> +#define   IRQ_TXD_ERR BIT(8)
> +#define   IRQ_DESC_ERR BIT(9)
> +#define   IRQ_RESP_ERR BIT(10)
> +#define   IRQ_RESP_TIMEOUT BIT(11)
> +#define   IRQ_DESC_TIMEOUT BIT(12)
> +#define   IRQ_END_OF_CHAIN BIT(13)
> +#define   IRQ_RESP_STATUS BIT(14)
> +#define   IRQ_SDIO BIT(15)
> +
> +#define SD_EMMC_CMD_CFG 0x50
> +#define SD_EMMC_CMD_ARG 0x54
> +#define SD_EMMC_CMD_DAT 0x58
> +#define SD_EMMC_CMD_RSP 0x5c
> +#define SD_EMMC_CMD_RSP1 0x60
> +#define SD_EMMC_CMD_RSP2 0x64
> +#define SD_EMMC_CMD_RSP3 0x68
> +
> +#define SD_EMMC_RXD 0x94
> +#define SD_EMMC_TXD 0x94
> +#define SD_EMMC_LAST_REG SD_EMMC_TXD
> +
> +#define SD_EMMC_CFG_BLK_SIZE 512 /* internal buffer max: 512 bytes */
> +#define SD_EMMC_CFG_RESP_TIMEOUT 256 /* in clock cycles */
> +#define SD_EMMC_CFG_CMD_GAP 16 /* in clock cycles */
> +#define MUX_CLK_NUM_PARENTS 2
> +
> +struct meson_host {
> +       struct  device          *dev;
> +       struct  mmc_host        *mmc;
> +       struct  mmc_request     *mrq;
> +       struct  mmc_command     *cmd;
> +
> +       spinlock_t lock;
> +       void __iomem *regs;
> +       int irq;
> +       u32 ocr_mask;
> +       struct clk *core_clk;
> +       struct clk_mux mux;
> +       struct clk *mux_clk;
> +       struct clk *mux_parent[MUX_CLK_NUM_PARENTS];
> +       unsigned long mux_parent_rate[MUX_CLK_NUM_PARENTS];
> +
> +       struct clk_divider cfg_div;
> +       struct clk *cfg_div_clk;
> +
> +       unsigned int bounce_buf_size;
> +       void *bounce_buf;
> +       dma_addr_t bounce_dma_addr;
> +
> +       bool vqmmc_enabled;
> +};
> +
> +struct sd_emmc_desc {
> +       u32 cmd_cfg;
> +       u32 cmd_arg;
> +       u32 cmd_data;
> +       u32 cmd_resp;
> +};
> +#define CMD_CFG_LENGTH_SHIFT 0
> +#define CMD_CFG_LENGTH_MASK 0x1ff
> +#define CMD_CFG_BLOCK_MODE BIT(9)
> +#define CMD_CFG_R1B BIT(10)
> +#define CMD_CFG_END_OF_CHAIN BIT(11)
> +#define CMD_CFG_TIMEOUT_SHIFT 12
> +#define CMD_CFG_TIMEOUT_MASK 0xf
> +#define CMD_CFG_NO_RESP BIT(16)
> +#define CMD_CFG_NO_CMD BIT(17)
> +#define CMD_CFG_DATA_IO BIT(18)
> +#define CMD_CFG_DATA_WR BIT(19)
> +#define CMD_CFG_RESP_NOCRC BIT(20)
> +#define CMD_CFG_RESP_128 BIT(21)
> +#define CMD_CFG_RESP_NUM BIT(22)
> +#define CMD_CFG_DATA_NUM BIT(23)
> +#define CMD_CFG_CMD_INDEX_SHIFT 24
> +#define CMD_CFG_CMD_INDEX_MASK 0x3f
> +#define CMD_CFG_ERROR BIT(30)
> +#define CMD_CFG_OWNER BIT(31)
> +
> +#define CMD_DATA_MASK (~0x3)
> +#define CMD_DATA_BIG_ENDIAN BIT(1)
> +#define CMD_DATA_SRAM BIT(0)
> +#define CMD_RESP_MASK (~0x1)
> +#define CMD_RESP_SRAM BIT(0)
> +
> +static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate)
> +{
> +       struct mmc_host *mmc = host->mmc;
> +       int ret = 0;
> +       u32 cfg;
> +
> +       if (clk_rate) {
> +               if (WARN_ON(clk_rate > mmc->f_max))
> +                       clk_rate = mmc->f_max;
> +               else if (WARN_ON(clk_rate < mmc->f_min))
> +                       clk_rate = mmc->f_min;
> +       }
> +
> +       if (clk_rate == mmc->actual_clock)
> +               return 0;
> +
> +       /* stop clock */
> +       cfg = readl(host->regs + SD_EMMC_CFG);
> +       if (!(cfg & CFG_STOP_CLOCK)) {
> +               cfg |= CFG_STOP_CLOCK;
> +               writel(cfg, host->regs + SD_EMMC_CFG);
> +       }
> +
> +       dev_dbg(host->dev, "change clock rate %u -> %lu\n",
> +               mmc->actual_clock, clk_rate);
> +
> +       if (clk_rate == 0) {
> +               mmc->actual_clock = 0;
> +               return 0;
> +       }
> +
> +       ret = clk_set_rate(host->cfg_div_clk, clk_rate);
> +       if (ret)
> +               dev_warn(host->dev, "Unable to set cfg_div_clk to %lu. ret=%d\n",
> +                        clk_rate, ret);
> +       else if (clk_rate && clk_rate != clk_get_rate(host->cfg_div_clk))
> +               dev_warn(host->dev, "divider requested rate %lu != actual rate %lu: ret=%d\n",
> +                        clk_rate, clk_get_rate(host->cfg_div_clk), ret);
> +       else
> +               mmc->actual_clock = clk_rate;
> +
> +       /* (re)start clock, if non-zero */
> +       if (!ret && clk_rate) {
> +               cfg = readl(host->regs + SD_EMMC_CFG);
> +               cfg &= ~CFG_STOP_CLOCK;
> +               writel(cfg, host->regs + SD_EMMC_CFG);
> +       }
> +
> +       return ret;
> +}
> +
> +/*
> + * The SD/eMMC IP block has an internal mux and divider used for
> + * generating the MMC clock.  Use the clock framework to create and
> + * manage these clocks.
> + */
> +static int meson_mmc_clk_init(struct meson_host *host)
> +{
> +       struct clk_init_data init;
> +       char clk_name[32];
> +       int i, ret = 0;
> +       const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
> +       unsigned int mux_parent_count = 0;
> +       const char *clk_div_parents[1];
> +       unsigned int f_min = UINT_MAX;
> +       u32 clk_reg, cfg;
> +
> +       /* get the mux parents */
> +       for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
> +               char name[16];
> +
> +               snprintf(name, sizeof(name), "clkin%d", i);
> +               host->mux_parent[i] = devm_clk_get(host->dev, name);
> +               if (IS_ERR(host->mux_parent[i])) {
> +                       ret = PTR_ERR(host->mux_parent[i]);
> +                       if (PTR_ERR(host->mux_parent[i]) != -EPROBE_DEFER)
> +                               dev_err(host->dev, "Missing clock %s\n", name);
> +                       host->mux_parent[i] = NULL;
> +                       return ret;
> +               }
> +
> +               host->mux_parent_rate[i] = clk_get_rate(host->mux_parent[i]);
> +               mux_parent_names[i] = __clk_get_name(host->mux_parent[i]);
> +               mux_parent_count++;
> +               if (host->mux_parent_rate[i] < f_min)
> +                       f_min = host->mux_parent_rate[i];
> +       }
> +
> +       /* cacluate f_min based on input clocks, and max divider value */
> +       if (f_min != UINT_MAX)
> +               f_min = DIV_ROUND_UP(CLK_SRC_XTAL_RATE, CLK_DIV_MAX);
> +       else
> +               f_min = 4000000;  /* default min: 400 MHz */
> +       host->mmc->f_min = f_min;
> +
> +       /* create the mux */
> +       snprintf(clk_name, sizeof(clk_name), "%s#mux", dev_name(host->dev));
> +       init.name = clk_name;
> +       init.ops = &clk_mux_ops;
> +       init.flags = 0;
> +       init.parent_names = mux_parent_names;
> +       init.num_parents = mux_parent_count;
> +
> +       host->mux.reg = host->regs + SD_EMMC_CLOCK;
> +       host->mux.shift = CLK_SRC_SHIFT;
> +       host->mux.mask = CLK_SRC_MASK;
> +       host->mux.flags = 0;
> +       host->mux.table = NULL;
> +       host->mux.hw.init = &init;
> +
> +       host->mux_clk = devm_clk_register(host->dev, &host->mux.hw);
> +       if (WARN_ON(IS_ERR(host->mux_clk)))
> +               return PTR_ERR(host->mux_clk);
> +
> +       /* create the divider */
> +       snprintf(clk_name, sizeof(clk_name), "%s#div", dev_name(host->dev));
> +       init.name = devm_kstrdup(host->dev, clk_name, GFP_KERNEL);
> +       init.ops = &clk_divider_ops;
> +       init.flags = CLK_SET_RATE_PARENT;
> +       clk_div_parents[0] = __clk_get_name(host->mux_clk);
> +       init.parent_names = clk_div_parents;
> +       init.num_parents = ARRAY_SIZE(clk_div_parents);
> +
> +       host->cfg_div.reg = host->regs + SD_EMMC_CLOCK;
> +       host->cfg_div.shift = CLK_DIV_SHIFT;
> +       host->cfg_div.width = CLK_DIV_WIDTH;
> +       host->cfg_div.hw.init = &init;
> +       host->cfg_div.flags = CLK_DIVIDER_ONE_BASED |
> +               CLK_DIVIDER_ROUND_CLOSEST | CLK_DIVIDER_ALLOW_ZERO;
> +
> +       host->cfg_div_clk = devm_clk_register(host->dev, &host->cfg_div.hw);
> +       if (WARN_ON(PTR_ERR_OR_ZERO(host->cfg_div_clk)))
> +               return PTR_ERR(host->cfg_div_clk);
> +
> +       /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
> +       clk_reg = 0;
> +       clk_reg |= CLK_PHASE_180 << CLK_PHASE_SHIFT;
> +       clk_reg |= CLK_SRC_XTAL << CLK_SRC_SHIFT;
> +       clk_reg |= CLK_DIV_MAX << CLK_DIV_SHIFT;
> +       clk_reg &= ~CLK_ALWAYS_ON;
> +       writel(clk_reg, host->regs + SD_EMMC_CLOCK);
> +
> +       /* Ensure clock starts in "auto" mode, not "always on" */
> +       cfg = readl(host->regs + SD_EMMC_CFG);
> +       cfg &= ~CFG_CLK_ALWAYS_ON;
> +       cfg |= CFG_AUTO_CLK;
> +       writel(cfg, host->regs + SD_EMMC_CFG);
> +
> +       ret = clk_prepare_enable(host->cfg_div_clk);
> +       if (!ret)
> +               ret = meson_mmc_clk_set(host, f_min);
> +
> +       if (!ret)
> +               clk_disable_unprepare(host->cfg_div_clk);
> +
> +       return ret;
> +}
> +
> +static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> +{
> +       struct meson_host *host = mmc_priv(mmc);
> +       u32 bus_width;
> +       u32 val, orig;
> +
> +       /*
> +        * GPIO regulator, only controls switching between 1v8 and
> +        * 3v3, doesn't support MMC_POWER_OFF, MMC_POWER_ON.
> +        */
> +       switch (ios->power_mode) {
> +       case MMC_POWER_OFF:
> +               if (!IS_ERR(mmc->supply.vmmc))
> +                       mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
> +
> +               if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) {
> +                       regulator_disable(mmc->supply.vqmmc);
> +                       host->vqmmc_enabled = false;
> +               }
> +
> +               break;
> +
> +       case MMC_POWER_UP:
> +               if (!IS_ERR(mmc->supply.vmmc))
> +                       mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
> +               break;
> +
> +       case MMC_POWER_ON:
> +               if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) {
> +                       int ret = regulator_enable(mmc->supply.vqmmc);
> +
> +                       if (ret < 0)
> +                               dev_err(mmc_dev(mmc),
> +                                       "failed to enable vqmmc regulator\n");
> +                       else
> +                               host->vqmmc_enabled = true;
> +               }
> +
> +               break;
> +       }
> +
> +
> +       meson_mmc_clk_set(host, ios->clock);
> +
> +       /* Bus width */
> +       val = readl(host->regs + SD_EMMC_CFG);
> +       switch (ios->bus_width) {
> +       case MMC_BUS_WIDTH_1:
> +               bus_width = CFG_BUS_WIDTH_1;
> +               break;
> +       case MMC_BUS_WIDTH_4:
> +               bus_width = CFG_BUS_WIDTH_4;
> +               break;
> +       case MMC_BUS_WIDTH_8:
> +               bus_width = CFG_BUS_WIDTH_8;
> +               break;
> +       default:
> +               dev_err(host->dev, "Invalid ios->bus_width: %u.  Setting to 4.\n",
> +                       ios->bus_width);
> +               bus_width = CFG_BUS_WIDTH_4;
> +               return;
> +       }
> +
> +       val = readl(host->regs + SD_EMMC_CFG);
> +       orig = val;
> +
> +       val &= ~(CFG_BUS_WIDTH_MASK << CFG_BUS_WIDTH_SHIFT);
> +       val |= bus_width << CFG_BUS_WIDTH_SHIFT;
> +
> +       val &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
> +       val |= ilog2(SD_EMMC_CFG_BLK_SIZE) << CFG_BLK_LEN_SHIFT;
> +
> +       val &= ~(CFG_RESP_TIMEOUT_MASK << CFG_RESP_TIMEOUT_SHIFT);
> +       val |= ilog2(SD_EMMC_CFG_RESP_TIMEOUT) << CFG_RESP_TIMEOUT_SHIFT;
> +
> +       val &= ~(CFG_RC_CC_MASK << CFG_RC_CC_SHIFT);
> +       val |= ilog2(SD_EMMC_CFG_CMD_GAP) << CFG_RC_CC_SHIFT;
> +
> +       writel(val, host->regs + SD_EMMC_CFG);
> +
> +       if (val != orig)
> +               dev_dbg(host->dev, "%s: SD_EMMC_CFG: 0x%08x -> 0x%08x\n",
> +                       __func__, orig, val);
> +}
> +
> +static int meson_mmc_request_done(struct mmc_host *mmc, struct mmc_request *mrq)
> +{
> +       struct meson_host *host = mmc_priv(mmc);
> +
> +       WARN_ON(host->mrq != mrq);
> +
> +       host->mrq = NULL;
> +       host->cmd = NULL;
> +       mmc_request_done(host->mmc, mrq);
> +
> +       return 0;
> +}
> +
> +static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
> +{
> +       struct meson_host *host = mmc_priv(mmc);
> +       struct sd_emmc_desc *desc, desc_tmp;
> +       u32 cfg;
> +       u8 blk_len, cmd_cfg_timeout;
> +       unsigned int xfer_bytes = 0;
> +
> +       /* Setup descriptors */
> +       dma_rmb();
> +       desc = &desc_tmp;
> +       memset(desc, 0, sizeof(struct sd_emmc_desc));
> +
> +       desc->cmd_cfg |= (cmd->opcode & CMD_CFG_CMD_INDEX_MASK) <<
> +               CMD_CFG_CMD_INDEX_SHIFT;
> +       desc->cmd_cfg |= CMD_CFG_OWNER;  /* owned by CPU */
> +       desc->cmd_arg = cmd->arg;
> +
> +       /* Response */
> +       if (cmd->flags & MMC_RSP_PRESENT) {
> +               desc->cmd_cfg &= ~CMD_CFG_NO_RESP;
> +               if (cmd->flags & MMC_RSP_136)
> +                       desc->cmd_cfg |= CMD_CFG_RESP_128;
> +               desc->cmd_cfg |= CMD_CFG_RESP_NUM;
> +               desc->cmd_resp = 0;
> +
> +               if (!(cmd->flags & MMC_RSP_CRC))
> +                       desc->cmd_cfg |= CMD_CFG_RESP_NOCRC;
> +
> +               if (cmd->flags & MMC_RSP_BUSY)
> +                       desc->cmd_cfg |= CMD_CFG_R1B;
> +       } else {
> +               desc->cmd_cfg |= CMD_CFG_NO_RESP;
> +       }
> +
> +       /* data? */
> +       if (cmd->data) {
> +               desc->cmd_cfg |= CMD_CFG_DATA_IO;
> +               if (cmd->data->blocks > 1) {
> +                       desc->cmd_cfg |= CMD_CFG_BLOCK_MODE;
> +                       desc->cmd_cfg |=
> +                               (cmd->data->blocks & CMD_CFG_LENGTH_MASK) <<
> +                               CMD_CFG_LENGTH_SHIFT;
> +
> +                       /* check if block-size matches, if not update */
> +                       cfg = readl(host->regs + SD_EMMC_CFG);
> +                       blk_len = cfg & (CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
> +                       blk_len >>= CFG_BLK_LEN_SHIFT;
> +                       if (blk_len != ilog2(cmd->data->blksz)) {
> +                               dev_warn(host->dev, "%s: update blk_len %d -> %d\n",
> +                                       __func__, blk_len,
> +                                        ilog2(cmd->data->blksz));
> +                               blk_len = ilog2(cmd->data->blksz);
> +                               cfg &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
> +                               cfg |= blk_len << CFG_BLK_LEN_SHIFT;
> +                               writel(cfg, host->regs + SD_EMMC_CFG);
> +                       }
> +               } else {
> +                       desc->cmd_cfg &= ~CMD_CFG_BLOCK_MODE;
> +                       desc->cmd_cfg |=
> +                               (cmd->data->blksz & CMD_CFG_LENGTH_MASK) <<
> +                               CMD_CFG_LENGTH_SHIFT;
> +               }
> +
> +               cmd->data->bytes_xfered = 0;
> +               xfer_bytes = cmd->data->blksz * cmd->data->blocks;
> +               if (cmd->data->flags & MMC_DATA_WRITE) {
> +                       desc->cmd_cfg |= CMD_CFG_DATA_WR;
> +                       WARN_ON(xfer_bytes > host->bounce_buf_size);
> +                       sg_copy_to_buffer(cmd->data->sg, cmd->data->sg_len,
> +                                         host->bounce_buf, xfer_bytes);
> +                       cmd->data->bytes_xfered = xfer_bytes;
> +                       dma_wmb();
> +               } else {
> +                       desc->cmd_cfg &= ~CMD_CFG_DATA_WR;
> +               }
> +
> +               if (xfer_bytes > 0) {
> +                       desc->cmd_cfg &= ~CMD_CFG_DATA_NUM;
> +                       desc->cmd_data = host->bounce_dma_addr & CMD_DATA_MASK;
> +               } else {
> +                       /* write data to data_addr */
> +                       desc->cmd_cfg |= CMD_CFG_DATA_NUM;
> +                       desc->cmd_data = 0;
> +               }
> +
> +               cmd_cfg_timeout = 12;
> +       } else {
> +               desc->cmd_cfg &= ~CMD_CFG_DATA_IO;
> +               cmd_cfg_timeout = 10;
> +       }
> +       desc->cmd_cfg |= (cmd_cfg_timeout & CMD_CFG_TIMEOUT_MASK) <<
> +               CMD_CFG_TIMEOUT_SHIFT;
> +
> +       host->cmd = cmd;
> +
> +       /* Last descriptor */
> +       desc->cmd_cfg |= CMD_CFG_END_OF_CHAIN;
> +       writel(desc->cmd_cfg, host->regs + SD_EMMC_CMD_CFG);
> +       writel(desc->cmd_data, host->regs + SD_EMMC_CMD_DAT);
> +       writel(desc->cmd_resp, host->regs + SD_EMMC_CMD_RSP);
> +       wmb(); /* ensure descriptor is written before kicked */
> +       writel(desc->cmd_arg, host->regs + SD_EMMC_CMD_ARG);
> +}
> +
> +static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
> +{
> +       struct meson_host *host = mmc_priv(mmc);
> +
> +       WARN_ON(host->mrq != NULL);
> +
> +       /* Stop execution */
> +       writel(0, host->regs + SD_EMMC_START);
> +
> +       /* clear, ack, enable all interrupts */
> +       writel(0, host->regs + SD_EMMC_IRQ_EN);
> +       writel(IRQ_EN_MASK, host->regs + SD_EMMC_STATUS);
> +       writel(IRQ_EN_MASK, host->regs + SD_EMMC_IRQ_EN);
> +
> +       host->mrq = mrq;
> +
> +       if (mrq->sbc)
> +               meson_mmc_start_cmd(mmc, mrq->sbc);
> +       else
> +               meson_mmc_start_cmd(mmc, mrq->cmd);
> +}
> +
> +static int meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd)
> +{
> +       struct meson_host *host = mmc_priv(mmc);
> +
> +       if (cmd->flags & MMC_RSP_136) {
> +               cmd->resp[0] = readl(host->regs + SD_EMMC_CMD_RSP3);
> +               cmd->resp[1] = readl(host->regs + SD_EMMC_CMD_RSP2);
> +               cmd->resp[2] = readl(host->regs + SD_EMMC_CMD_RSP1);
> +               cmd->resp[3] = readl(host->regs + SD_EMMC_CMD_RSP);
> +       } else if (cmd->flags & MMC_RSP_PRESENT) {
> +               cmd->resp[0] = readl(host->regs + SD_EMMC_CMD_RSP);
> +       }
> +
> +       return 0;
> +}
> +
> +static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
> +{
> +       struct meson_host *host = dev_id;
> +       struct mmc_request *mrq;
> +       struct mmc_command *cmd = host->cmd;
> +       u32 irq_en, status, raw_status;
> +       irqreturn_t ret = IRQ_HANDLED;
> +
> +       if (WARN_ON(!host))
> +               return IRQ_NONE;
> +
> +       mrq = host->mrq;
> +
> +       if (WARN_ON(!mrq))
> +               return IRQ_NONE;
> +
> +       if (WARN_ON(!cmd))
> +               return IRQ_NONE;
> +
> +       spin_lock(&host->lock);
> +       irq_en = readl(host->regs + SD_EMMC_IRQ_EN);
> +       raw_status = readl(host->regs + SD_EMMC_STATUS);
> +       status = raw_status & irq_en;
> +
> +       if (!status) {
> +               dev_warn(host->dev, "Spurious IRQ! status=0x%08x, irq_en=0x%08x\n",
> +                        raw_status, irq_en);
> +               ret = IRQ_NONE;
> +               goto out;
> +       }
> +
> +       cmd->error = 0;
> +       if (status & IRQ_RXD_ERR_MASK) {
> +               dev_dbg(host->dev, "Unhandled IRQ: RXD error\n");
> +               cmd->error = -EILSEQ;
> +       }
> +       if (status & IRQ_TXD_ERR) {
> +               dev_dbg(host->dev, "Unhandled IRQ: TXD error\n");
> +               cmd->error = -EILSEQ;
> +       }
> +       if (status & IRQ_DESC_ERR)
> +               dev_dbg(host->dev, "Unhandled IRQ: Descriptor error\n");
> +       if (status & IRQ_RESP_ERR) {
> +               dev_dbg(host->dev, "Unhandled IRQ: Response error\n");
> +               cmd->error = -EILSEQ;
> +       }
> +       if (status & IRQ_RESP_TIMEOUT) {
> +               dev_dbg(host->dev, "Unhandled IRQ: Response timeout\n");
> +               cmd->error = -ETIMEDOUT;
> +       }
> +       if (status & IRQ_DESC_TIMEOUT) {
> +               dev_dbg(host->dev, "Unhandled IRQ: Descriptor timeout\n");
> +               cmd->error = -ETIMEDOUT;
> +       }
> +       if (status & IRQ_SDIO)
> +               dev_dbg(host->dev, "Unhandled IRQ: SDIO.\n");
> +
> +       if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS))
> +               ret = IRQ_WAKE_THREAD;
> +       else  {
> +               dev_warn(host->dev, "Unknown IRQ! status=0x%04x: MMC CMD%u arg=0x%08x flags=0x%08x stop=%d\n",
> +                        status, cmd->opcode, cmd->arg,
> +                        cmd->flags, mrq->stop ? 1 : 0);
> +               if (cmd->data) {
> +                       struct mmc_data *data = cmd->data;
> +
> +                       dev_warn(host->dev, "\tblksz %u blocks %u flags 0x%08x (%s%s)",
> +                                data->blksz, data->blocks, data->flags,
> +                                data->flags & MMC_DATA_WRITE ? "write" : "",
> +                                data->flags & MMC_DATA_READ ? "read" : "");
> +               }
> +       }
> +
> +out:
> +       /* ack all (enabled) interrupts */
> +       writel(status, host->regs + SD_EMMC_STATUS);
> +
> +       if (ret == IRQ_HANDLED) {
> +               meson_mmc_read_resp(host->mmc, cmd);
> +               meson_mmc_request_done(host->mmc, cmd->mrq);
> +       }
> +
> +       spin_unlock(&host->lock);
> +       return ret;
> +}
> +
> +static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
> +{
> +       struct meson_host *host = dev_id;
> +       struct mmc_request *mrq = host->mrq;
> +       struct mmc_command *cmd = host->cmd;
> +       struct mmc_data *data;
> +       unsigned int xfer_bytes;
> +       int ret = IRQ_HANDLED;
> +
> +       if (WARN_ON(!mrq))
> +               ret = IRQ_NONE;
> +
> +       if (WARN_ON(!cmd))
> +               ret = IRQ_NONE;
> +
> +       data = cmd->data;
> +       if (data) {
> +               xfer_bytes = data->blksz * data->blocks;
> +               if (data->flags & MMC_DATA_READ) {
> +                       WARN_ON(xfer_bytes > host->bounce_buf_size);
> +                       sg_copy_from_buffer(data->sg, data->sg_len,
> +                                           host->bounce_buf, xfer_bytes);
> +                       data->bytes_xfered = xfer_bytes;
> +               }
> +       }
> +
> +       meson_mmc_read_resp(host->mmc, cmd);
> +       if (!data || !data->stop || mrq->sbc)
> +               meson_mmc_request_done(host->mmc, mrq);
> +       else
> +               meson_mmc_start_cmd(host->mmc, data->stop);
> +
> +       return ret;
> +}
> +
> +/*
> + * NOTE: we only need this until the GPIO/pinctrl driver can handle
> + * interrupts.  For now, the MMC core will use this for polling.
> + */
> +static int meson_mmc_get_cd(struct mmc_host *mmc)
> +{
> +       int status = mmc_gpio_get_cd(mmc);
> +
> +       if (status == -ENOSYS)
> +               return 1; /* assume present */
> +
> +       return status;
> +}
> +
> +static const struct mmc_host_ops meson_mmc_ops = {
> +       .request        = meson_mmc_request,
> +       .set_ios        = meson_mmc_set_ios,
> +       .get_cd         = meson_mmc_get_cd,
> +};
> +
> +static int meson_mmc_probe(struct platform_device *pdev)
> +{
> +       struct resource *res;
> +       struct meson_host *host;
> +       struct mmc_host *mmc;
> +       int ret;
> +
> +       mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev);
> +       if (!mmc)
> +               return -ENOMEM;
> +       host = mmc_priv(mmc);
> +       host->mmc = mmc;
> +       host->dev = &pdev->dev;
> +       dev_set_drvdata(&pdev->dev, host);
> +
> +       spin_lock_init(&host->lock);
> +
> +       /* Get regulators and the supported OCR mask */
> +       host->vqmmc_enabled = false;
> +       ret = mmc_regulator_get_supply(mmc);
> +       if (ret == -EPROBE_DEFER)
> +               goto free_host;
> +
> +       ret = mmc_of_parse(mmc);
> +       if (ret) {
> +               dev_warn(&pdev->dev, "error parsing DT: %d\n", ret);
> +               goto free_host;
> +       }
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       host->regs = devm_ioremap_resource(&pdev->dev, res);
> +       if (IS_ERR(host->regs)) {
> +               ret = PTR_ERR(host->regs);
> +               goto free_host;
> +       }
> +
> +       host->irq = platform_get_irq(pdev, 0);
> +       if (host->irq == 0) {
> +               dev_err(&pdev->dev, "failed to get interrupt resource.\n");
> +               ret = -EINVAL;
> +               goto free_host;
> +       }
> +
> +       host->core_clk = devm_clk_get(&pdev->dev, "core");
> +       if (IS_ERR(host->core_clk)) {
> +               ret = PTR_ERR(host->core_clk);
> +               goto free_host;
> +       }
> +
> +       ret = clk_prepare_enable(host->core_clk);
> +       if (ret)
> +               goto free_host;
> +
> +       ret = meson_mmc_clk_init(host);
> +       if (ret)
> +               goto free_host;
> +
> +       /* Stop execution */
> +       writel(0, host->regs + SD_EMMC_START);
> +
> +       /* clear, ack, enable all interrupts */
> +       writel(0, host->regs + SD_EMMC_IRQ_EN);
> +       writel(IRQ_EN_MASK, host->regs + SD_EMMC_STATUS);
> +
> +       ret = devm_request_threaded_irq(&pdev->dev, host->irq,
> +                                       meson_mmc_irq, meson_mmc_irq_thread,
> +                                       IRQF_SHARED, DRIVER_NAME, host);
> +       if (ret)
> +               goto free_host;
> +
> +       /* data bounce buffer */
> +       host->bounce_buf_size = SZ_512K;
> +       host->bounce_buf =
> +               dma_alloc_coherent(host->dev, host->bounce_buf_size,
> +                                  &host->bounce_dma_addr, GFP_KERNEL);
> +       if (host->bounce_buf == NULL) {
> +               dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
> +               ret = -ENOMEM;
> +               goto free_host;
> +       }
> +
> +       mmc->ops = &meson_mmc_ops;
> +       mmc_add_host(mmc);
> +
> +       return 0;
> +
> +free_host:
> +       clk_disable_unprepare(host->cfg_div_clk);
> +       clk_disable_unprepare(host->core_clk);
> +       mmc_free_host(mmc);
> +       return ret;
> +}
> +
> +static int meson_mmc_remove(struct platform_device *pdev)
> +{
> +       struct meson_host *host = dev_get_drvdata(&pdev->dev);
> +
> +       if (WARN_ON(!host))
> +               return 0;
> +
> +       if (host->bounce_buf)
> +               dma_free_coherent(host->dev, host->bounce_buf_size,
> +                                 host->bounce_buf, host->bounce_dma_addr);
> +
> +       clk_disable_unprepare(host->cfg_div_clk);
> +       clk_disable_unprepare(host->core_clk);
> +
> +       mmc_free_host(host->mmc);
> +       return 0;
> +}
> +
> +static const struct of_device_id meson_mmc_of_match[] = {
> +       { .compatible = "amlogic,meson-gx-mmc", },
> +       { .compatible = "amlogic,meson-gxbb-mmc", },
> +       { .compatible = "amlogic,meson-gxl-mmc", },
> +       { .compatible = "amlogic,meson-gxm-mmc", },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(of, meson_mmc_of_match);
> +
> +static struct platform_driver meson_mmc_driver = {
> +       .probe          = meson_mmc_probe,
> +       .remove         = meson_mmc_remove,
> +       .driver         = {
> +               .name = DRIVER_NAME,
> +               .of_match_table = of_match_ptr(meson_mmc_of_match),
> +       },
> +};
> +
> +module_platform_driver(meson_mmc_driver);
> +
> +MODULE_DESCRIPTION("Amlogic S905*/GX* SD/eMMC driver");
> +MODULE_AUTHOR("Kevin Hilman <khilman@baylibre.com>");
> +MODULE_LICENSE("GPL v2");
> +
> --
> 2.9.3
>

^ permalink raw reply

* [PATCH v6 2/2] Documentation: DT: MMC: meson-gx: new bindings doc
From: Ulf Hansson @ 2016-10-27  7:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161019181825.2186-2-khilman@baylibre.com>

On 19 October 2016 at 20:18, Kevin Hilman <khilman@baylibre.com> wrote:
> Signed-off-by: Kevin Hilman <khilman@baylibre.com>

Thanks, applied for next!

Kind regards
Uffe

> ---
>  .../devicetree/bindings/mmc/amlogic,meson-gx.txt   | 33 ++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt
>
> diff --git a/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt b/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt
> new file mode 100644
> index 000000000000..a2fa9a1c26ae
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt
> @@ -0,0 +1,33 @@
> +Amlogic SD / eMMC controller for S905/GXBB family SoCs
> +
> +The MMC 5.1 compliant host controller on Amlogic provides the
> +interface for SD, eMMC and SDIO devices.
> +
> +This file documents the properties in addition to those available in
> +the MMC core bindings, documented by mmc.txt.
> +
> +Required properties:
> +- compatible : contains one of:
> +  - "amlogic,meson-gx-mmc"
> +  - "amlogic,meson-gxbb-mmc"
> +  - "amlogic,meson-gxl-mmc"
> +  - "amlogic,meson-gxm-mmc"
> +- clocks     : A list of phandle + clock-specifier pairs for the clocks listed in clock-names.
> +- clock-names: Should contain the following:
> +       "core" - Main peripheral bus clock
> +       "clkin0" - Parent clock of internal mux
> +       "clkin1" - Other parent clock of internal mux
> +  The driver has an interal mux clock which switches between clkin0 and clkin1 depending on the
> +  clock rate requested by the MMC core.
> +
> +Example:
> +
> +       sd_emmc_a: mmc at 70000 {
> +               compatible = "amlogic,meson-gxbb-mmc";
> +               reg = <0x0 0x70000 0x0 0x2000>;
> +                interrupts = < GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
> +               clocks = <&clkc CLKID_SD_EMMC_A>, <&xtal>, <&clkc CLKID_FCLK_DIV2>;
> +               clock-names = "core", "clkin0", "clkin1";
> +               pinctrl-0 = <&emmc_pins>;
> +       };
> +
> --
> 2.9.3
>

^ permalink raw reply

* Add Allwinner Q8 tablets hardware manager
From: Pierre-Hugues Husson @ 2016-10-27  8:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161026205451.cgk5xam334ncg6op@rob-hp-laptop>

Hi,

(mail resent, because it had been filtered out by linux-arm-kernel and
and devicetree because it contained an HTML part, sorry about that)

2016-10-26 13:46 GMT+02:00 Hans de Goede <hdegoede@redhat.com>:

> And as I tried to explain before, for this specific use-case describing
> all this board specific knowledge in a generic manner in dt is simply
> impossible, unless we add a turing complete language to dt aka aml.


You keep saying this is a "specific use-case", but I don't agree.
Most of cheap phone and tablets SoC manufacturer's Linux variant that
I know of have (rather stupid) auto-detection methods.
Not every phone manufacturer use it, because some have proper and
constant supply chain, but still, that's not always the case.
For instance you might look at this dts:
https://github.com/Dee-UK/RK3288_Lollipop_Kernel/commit/9e056a10b0a773d285e8d2ae819e7c2451816492#diff-b25e1abc92522c85e9ef28704bf9284aR410
This DTS is meant, like what you do, to be compatible with as many
devices as possible at once.
So it declares 4 different PMICs (and no they will never all be there
at the same time), and two different accelerometers, 3 audio codecs,
and two touchscreens.
Or you can look at CodeAurora (Qualcomm public opensource tree) DTSs
and see that a standard DTS support at least three different panels (
see https://github.com/omnirom/android_kernel_oppo_msm8974/blob/27080b724f4cf281d598e7830abc5fc1292b5803/arch/arm/boot/dts/msm8974-mtp.dtsi#L15
)
And that's the fairly clean examples. Some SoC kernels are still using
good old platform_data detection methods.

Thus I believe that having a board-specific driver is not a good
thing, because we would get many of those.

When it comes to detection, I've witnessed various things.
It can be kernel-side or bootloader-side "global setting" reading
(like an ADC/resistor value, or an OTP), it can be bootloader doing
the "brute-force", or it can be the kernel doing all the probes.

For instance, as of today, on a Spreadtrum ODM tree, the bootloader
will detect the screen by testing all knowns screens, the
screen-drivers declare a get_id function, and the bootloader probes
until the get_id matches the id declared by the screen driver.
And then the bootloader tells the kernel, via cmdline, which screen is
actually there (but auto-detection is also coded in kernel).
Finally all possible sensors/touchscreen/camera are declared in DTS,
and probe will filter-out N/C ones in the kernel.

Now the big difference between my experience and what Hans is trying
to do, is that I've always worked with devices with "safely" queriable
IDs, either on i2c or dsi. I've never encountered SPI. This makes
probing inherently more dangerous, but I believe the question roughly
remains the same.

I understand Mark's will of taking care of this "earlier" (either
bootloader or a later kernel-loader (pxa-impedance-matcher)), but I
feel like this is only giving the problem to someone else.
I think that those auto-detection methods should be declared in a
device-tree, though as Hans noted, this might end to be a
turing-complete language.
In my experience, I have never encountered a device requiring more
than ordered probes, but backward compatibility was expected. (i.e. if
IDs couldn't help distinguish two devices, the manufacturer would add
another way to identify)

As to whether this is bootloader's job or kernel's job, I don't have a
really strong opinion.
On one side, the kernel has all the drivers and probe functions, this
would need little work to make this work.
On the other side, if the "rules" are something like "read bus XXX,
address YYY, expect ZZZ", the bootloader can handle it as well. But I
don't think it is a good idea to have the bootloader know all the
gsensor/screen/camera/... drivers (even if they are partial drivers
dedicated to detection only)

Regards,

2016-10-26 22:54 GMT+02:00 Rob Herring <robh@kernel.org>:
> On Mon, Oct 24, 2016 at 06:39:01PM +0100, Mark Rutland wrote:
>> On Fri, Oct 14, 2016 at 09:53:31AM +0200, Hans de Goede wrote:
>> > Hi Rob, Mark, et al.,
>>
>> Hi Hans,
>>
>> Apologies for the delay in replying to this.
>>
>> I'd like to be clear that I do understand that there is a problem that
>> needs to be addressed here. However, I do not believe that the *current*
>> in-kernel approach is correct. More on that below.
>>
>> > Mark, I know that we discussed this at ELCE and you clearly indicated
>> > that according to you this does not belong in the kernel. I was a bit
>> > surprised by this part of the discussion.
>> >
>> > I had posted a RFC earlier and Rob had indicated that given that the q8
>> > tablets are a special case, as my code uses actual probing rather then some
>> > pre-arranged id mechanism with say an eeprom, that doing this in a
>> > non-generic manner would be ok for my special case.
>>
>> To some extent, Rob and I may have differing views here; I'm not
>> entirely sure what Rob's view is, and I cannot talk on his behalf. I
>> certainly must apologise for having not commented on said RFC, however.
>
> I've focused mainly on the bindings which I certainly had issues with
> how the RFC was done. As to where this should be done, keeping all the
> dirty bits in firmware/bootloader is certainly appealing. However, there
> are cases where data alone can't abstract out board differences and we
> need board code. Whether this is one of them, well, that is Hans' job to
> convince Mark.
>
> Rob
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 1/2] mm/memblock: prepare a capability to support memblock near alloc
From: Leizhen (ThunderTown) @ 2016-10-27  8:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161027072235.GB6454@dhcp22.suse.cz>



On 2016/10/27 15:22, Michal Hocko wrote:
> On Thu 27-10-16 10:41:24, Leizhen (ThunderTown) wrote:
>>
>>
>> On 2016/10/26 17:31, Michal Hocko wrote:
>>> On Wed 26-10-16 11:10:44, Leizhen (ThunderTown) wrote:
>>>>
>>>>
>>>> On 2016/10/25 21:23, Michal Hocko wrote:
>>>>> On Tue 25-10-16 10:59:17, Zhen Lei wrote:
>>>>>> If HAVE_MEMORYLESS_NODES is selected, and some memoryless numa nodes are
>>>>>> actually exist. The percpu variable areas and numa control blocks of that
>>>>>> memoryless numa nodes need to be allocated from the nearest available
>>>>>> node to improve performance.
>>>>>>
>>>>>> Although memblock_alloc_try_nid and memblock_virt_alloc_try_nid try the
>>>>>> specified nid at the first time, but if that allocation failed it will
>>>>>> directly drop to use NUMA_NO_NODE. This mean any nodes maybe possible at
>>>>>> the second time.
>>>>>>
>>>>>> To compatible the above old scene, I use a marco node_distance_ready to
>>>>>> control it. By default, the marco node_distance_ready is not defined in
>>>>>> any platforms, the above mentioned functions will work as normal as
>>>>>> before. Otherwise, they will try the nearest node first.
>>>>>
>>>>> I am sorry but it is absolutely unclear to me _what_ is the motivation
>>>>> of the patch. Is this a performance optimization, correctness issue or
>>>>> something else? Could you please restate what is the problem, why do you
>>>>> think it has to be fixed at memblock layer and describe what the actual
>>>>> fix is please?
>>>>
>>>> This is a performance optimization.
>>>
>>> Do you have any numbers to back the improvements?
>>
>> I have not collected any performance data, but at least in theory,
>> it's beneficial and harmless, except make code looks a bit
>> urly.
> 
> The whole memoryless area is cluttered with hacks because everybody just
> adds pieces here and there to make his particular usecase work IMHO.
> Adding more on top for performance reasons which are even not measured
OK, I will ask my colleagues for help, whether some APPs can be used or not.

> to prove a clear win is a no go. Please step back try to think how this
> could be done with an existing infrastructure we have (some cleanups
OK, I will try to do it. But some infrastructures maybe only restricted in the
theoretical analysis, I don't have the related testing environment, so there is
no way to verify.


> while doing that would be hugely appreciated) and if that is not
> possible then explain why and why it is not feasible to fix that before
I think it will be feasible.

> you start adding a new API.
> 
> Thanks!
> 

^ permalink raw reply

* [PATCH V3 0/8] IOMMU probe deferral support
From: Sricharan @ 2016-10-27  8:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <421e2b14-0231-d376-02a0-097423120b3d@arm.com>

Hi Robin,

>>
>>
>>
>>> [   39.901592] iommu: Removing device 0000:08:00.0 from group 0
>
>Yikes, on second look, that definitely shouldn't be happening.
>Everything below is probably the resulting fallout.

[   40.206703] vfio-pci 0000:08:00.0: Failed to setup iommu ops

I think the above print which says "failed to setup iommu_ops"
because the call ops->add_device failed in of_pci_iommu_configure
is the reason for the failure, in my case i simply do not get this even with
your scripts. ops->add_device succeeds in the rebind as well. So still
checking what could be happening in your case.


Regards,
  Sricharan

    
>
>Robin.
>
>>> [   39.907383] ------------[ cut here ]------------
>>> [   39.911969] WARNING: CPU: 0 PID: 174 at
>>> arch/arm64/mm/dma-mapping.c:856 arch_teardown_dma_ops+0x48/0x68
>>> [   39.921266] Modules linked in:
>>> [   39.924290]
>>> [   39.925766] CPU: 0 PID: 174 Comm: vfio Not tainted 4.9.0-rc2+ #1249
>>> [   39.931967] Hardware name: ARM Juno development board (r1) (DT)
>>> [   39.937826] task: ffffffc975ee9900 task.stack: ffffffc974d60000
>>> [   39.943687] PC is at arch_teardown_dma_ops+0x48/0x68
>>> [   39.948603] LR is at arch_teardown_dma_ops+0x34/0x68
>>> [   39.953516] pc : [<ffffff80080948f8>] lr : [<ffffff80080948e4>]
>>> pstate: 60000145
>>> [   39.960834] sp : ffffffc974d63ca0
>>> [   39.964112] x29: ffffffc974d63ca0 x28: ffffffc974d60000
>>> [   39.969377] x27: ffffff80088a2000 x26: 0000000000000040
>>> [   39.974642] x25: 0000000000000123 x24: ffffffc976a48918
>>> [   39.979907] x23: ffffffc974d63eb8 x22: ffffff8008db7550
>>> [   39.985171] x21: 000000000000000d x20: ffffffc9763e9b50
>>> [   39.990435] x19: ffffffc9763f20a0 x18: 0000000000000010
>>> [   39.995699] x17: 0000007f99c18018 x16: ffffff80080c0580
>>> [   40.000964] x15: ffffff8008bb7000 x14: 000137c100013798
>>> [   40.006228] x13: ffffffffff000000 x12: ffffffffffffffff
>>> [   40.011492] x11: 0000000000000018 x10: 000000000000000d
>>> [   40.016757] x9 : 0000000040000000 x8 : 0000000000210d00
>>> [   40.022021] x7 : 00000049771bc000 x6 : 00000000001f17ed
>>> [   40.027286] x5 : ffffff80084c4208 x4 : 0000000000000080
>>> [   40.032551] x3 : ffffffc975ea9800 x2 : ffffffbf25d7aa50
>>> [   40.037815] x1 : 0000000000000000 x0 : 0000000000000080
>>> [   40.043078]
>>> [   40.044549] ---[ end trace 35c1e743d6e6c035 ]---
>>> [   40.049117] Call trace:
>>> [   40.051537] Exception stack(0xffffffc974d63ad0 to 0xffffffc974d63c00)
>>> [   40.057914] 3ac0:                                   ffffffc9763f20a0
>>> 0000008000000000
>>> [   40.065668] 3ae0: ffffffc974d63ca0 ffffff80080948f8 ffffffbf25d7aa40
>>> ffffffc975ea9800
>>> [   40.073421] 3b00: ffffffc974d60000 000000000002fc80 ffffffc976801e00
>>> ffffffc974d60000
>>> [   40.081175] 3b20: ffffff80084c4208 0000000000000040 ffffff80088a2000
>>> ffffffc974d60000
>>> [   40.088928] 3b40: ffffff80084caf78 ffffffc974d60000 ffffffc974d60000
>>> ffffffc974d60000
>>> [   40.096682] 3b60: ffffffc975ea9800 ffffffc974d60000 0000000000000080
>>> 0000000000000000
>>> [   40.104435] 3b80: ffffffbf25d7aa50 ffffffc975ea9800 0000000000000080
>>> ffffff80084c4208
>>> [   40.112188] 3ba0: 00000000001f17ed 00000049771bc000 0000000000210d00
>>> 0000000040000000
>>> [   40.119941] 3bc0: 000000000000000d 0000000000000018 ffffffffffffffff
>>> ffffffffff000000
>>> [   40.127695] 3be0: 000137c100013798 ffffff8008bb7000 ffffff80080c0580
>>> 0000007f99c18018
>>> [   40.135450] [<ffffff80080948f8>] arch_teardown_dma_ops+0x48/0x68
>>> [   40.141400] [<ffffff8008764a14>] of_dma_deconfigure+0xc/0x18
>>> [   40.147005] [<ffffff8008552804>] dma_deconfigure+0xc/0x18
>>> [   40.152353] [<ffffff800853ba10>] __device_release_driver+0x88/0x120
>>> [   40.158560] [<ffffff800853bacc>] device_release_driver+0x24/0x38
>>> [   40.164507] [<ffffff800853a868>] unbind_store+0xe8/0x110
>>> [   40.169767] [<ffffff8008539c70>] drv_attr_store+0x20/0x30
>>> [   40.175113] [<ffffff800823ab18>] sysfs_kf_write+0x48/0x58
>>> [   40.180458] [<ffffff8008239ea8>] kernfs_fop_write+0xb0/0x1d8
>>> [   40.186063] [<ffffff80081c507c>] __vfs_write+0x1c/0x100
>>> [   40.191237] [<ffffff80081c5e80>] vfs_write+0xa0/0x1b8
>>> [   40.196239] [<ffffff80081c7274>] SyS_write+0x44/0xa0
>>> [   40.201155] [<ffffff8008082ef0>] el0_svc_naked+0x24/0x28
>>> [   40.206703] vfio-pci 0000:08:00.0: Failed to setup iommu ops
>>> [   40.212382] vfio-pci: probe of 0000:08:00.0 failed with error -22
>>> [   40.228075] ------------[ cut here ]------------
>>> [   40.235263] WARNING: CPU: 1 PID: 174 at ./include/linux/kref.h:46
>>> kobject_get+0x64/0x88
>>> [   40.243181] Modules linked in:
>>> [   40.246201]
>>> [   40.247673] CPU: 1 PID: 174 Comm: vfio Tainted: G        W
>>> 4.9.0-rc2+ #1249
>>> [   40.255076] Hardware name: ARM Juno development board (r1) (DT)
>>> [   40.260932] task: ffffffc975ee9900 task.stack: ffffffc974d60000
>>> [   40.266787] PC is at kobject_get+0x64/0x88
>>> [   40.270840] LR is at iommu_bus_notifier+0x40/0x110
>>> [   40.275577] pc : [<ffffff800834d20c>] lr : [<ffffff80084c3fd0>]
>>> pstate: 80000145
>>> [   40.282894] sp : ffffffc974d63c00
>>> [   40.286169] x29: ffffffc974d63c00 x28: ffffffc974d60000
>>> [   40.291431] x27: ffffff80088a2000 x26: 0000000000000040
>>> [   40.296692] x25: 0000000000000123 x24: ffffffc974c8f418
>>> [   40.301953] x23: 0000000000000006 x22: ffffffc9763f10a0
>>> [   40.307214] x21: ffffffc9763e9a00 x20: ffffffc9763f10a0
>>> [   40.312474] x19: ffffffc9763ebc80 x18: 0000007fd65069e0
>>> [   40.317734] x17: 0000007f8d0ae3c0 x16: ffffff80081c7230
>>> [   40.322995] x15: 0000007f8d136588 x14: ffffffffffffffff
>>> [   40.328255] x13: 0000000000000004 x12: 0000000000000030
>>> [   40.333515] x11: 0000000000000030 x10: 0101010101010101
>>> [   40.338775] x9 : feff716475687163 x8 : 7f7f7f7f7f7f7f7f
>>> [   40.344035] x7 : feff716475687163 x6 : ffffffc976abf400
>>> [   40.349295] x5 : ffffffc976abf400 x4 : 0000000000000000
>>> [   40.354555] x3 : ffffff80084c3f90 x2 : ffffffc9763ebcb8
>>> [   40.359814] x1 : 0000000000000001 x0 : ffffff8008d4f000
>>> [   40.365074]
>>> [   40.366542] ---[ end trace 35c1e743d6e6c036 ]---
>>> [   40.371107] Call trace:
>>> [   40.373523] Exception stack(0xffffffc974d63a30 to 0xffffffc974d63b60)
>>> [   40.379895] 3a20:                                   ffffffc9763ebc80
>>> 0000008000000000
>>> [   40.387643] 3a40: ffffffc974d63c00 ffffff800834d20c ffffffc976812400
>>> ffffff8008237d94
>>> [   40.395391] 3a60: ffffffbf25d78940 ffffffc974d60000 ffffffc975e259d8
>>> 0000000000005b81
>>> [   40.403139] 3a80: ffffffc974d60000 ffffff8008d4b31f ffffff8008b0f000
>>> ffffffc976811c80
>>> [   40.410887] 3aa0: ffffffc974d60000 ffffffc974d60000 ffffffc974d60000
>>> ffffff8008237000
>>> [   40.418634] 3ac0: ffffffc975e259d8 ffffff8008b1b9a8 ffffff8008d4f000
>>> 0000000000000001
>>> [   40.426382] 3ae0: ffffffc9763ebcb8 ffffff80084c3f90 0000000000000000
>>> ffffffc976abf400
>>> [   40.434130] 3b00: ffffffc976abf400 feff716475687163 7f7f7f7f7f7f7f7f
>>> feff716475687163
>>> [   40.441877] 3b20: 0101010101010101 0000000000000030 0000000000000030
>>> 0000000000000004
>>> [   40.449625] 3b40: ffffffffffffffff 0000007f8d136588 ffffff80081c7230
>>> 0000007f8d0ae3c0
>>> [   40.457372] [<ffffff800834d20c>] kobject_get+0x64/0x88
>>> [   40.462455] [<ffffff80084c3fd0>] iommu_bus_notifier+0x40/0x110
>>> [   40.468227] [<ffffff80080da288>] notifier_call_chain+0x50/0x90
>>> [   40.473997] [<ffffff80080da694>] __blocking_notifier_call_chain+0x4c/0x90
>>> [   40.480713] [<ffffff80080da6ec>] blocking_notifier_call_chain+0x14/0x20
>>> [   40.487259] [<ffffff800853b9e4>] __device_release_driver+0x5c/0x120
>>> [   40.493460] [<ffffff800853bacc>] device_release_driver+0x24/0x38
>>> [   40.499402] [<ffffff800853a868>] unbind_store+0xe8/0x110
>>> [   40.504656] [<ffffff8008539c70>] drv_attr_store+0x20/0x30
>>> [   40.509997] [<ffffff800823ab18>] sysfs_kf_write+0x48/0x58
>>> [   40.515337] [<ffffff8008239ea8>] kernfs_fop_write+0xb0/0x1d8
>>> [   40.520936] [<ffffff80081c507c>] __vfs_write+0x1c/0x100
>>> [   40.526104] [<ffffff80081c5e80>] vfs_write+0xa0/0x1b8
>>> [   40.531100] [<ffffff80081c7274>] SyS_write+0x44/0xa0
>>> [   40.536011] [<ffffff8008082ef0>] el0_svc_naked+0x24/0x28
>>> [   40.541324] ata1.00: disabled
>>> [   40.544878] sd 0:0:0:0: [sda] Synchronizing SCSI cache
>>> [   40.550062] sd 0:0:0:0: [sda] Synchronize Cache(10) failed: Result:
>>> hostbyte=0x04 driverbyte=0x00
>>> [   40.558871] sd 0:0:0:0: [sda] Stopping disk
>>> [   40.563037] sd 0:0:0:0: [sda] Start/Stop Unit failed: Result:
>>> hostbyte=0x04 driverbyte=0x00
>>> [   40.586990] Unable to handle kernel paging request at virtual address
>>> 0002003e
>>> [   40.594702] pgd = ffffffc974c80000
>>> [   40.598165] [0002003e] *pgd=00000009f5102003[   40.602241] ,
>>> *pud=00000009f5102003
>>> , *pmd=0000000000000000[   40.607694]
>>> [   40.609171] Internal error: Oops: 96000006 [#1] PREEMPT SMP
>>> [   40.614684] Modules linked in:
>>> [   40.617712] CPU: 3 PID: 174 Comm: vfio Tainted: G        W
>>> 4.9.0-rc2+ #1249
>>> [   40.625118] Hardware name: ARM Juno development board (r1) (DT)
>>> [   40.630977] task: ffffffc975ee9900 task.stack: ffffffc974d60000
>>> [   40.636841] PC is at kobject_get+0x14/0x88
>>> [   40.640897] LR is at iommu_get_domain_for_dev+0x1c/0x48
>>> [   40.646068] pc : [<ffffff800834d1bc>] lr : [<ffffff80084c3dec>]
>>> pstate: 60000145
>>> [   40.653387] sp : ffffffc974d63c60
>>> [   40.656664] x29: ffffffc974d63c60 x28: ffffffc974d60000
>>> [   40.661928] x27: ffffff80088a2000 x26: 0000000000000040
>>> [   40.667193] x25: 0000000000000123 x24: ffffffc974c8f418
>>> [   40.672457] x23: ffffffc974d63eb8 x22: ffffff8008dab568
>>> [   40.677720] x21: 000000000000000d x20: ffffff8008dab568
>>> [   40.682984] x19: 0000000000020002 x18: 0000000000000000
>>> [   40.688246] x17: 0000000000000007 x16: 0000000000000001
>>> [   40.693509] x15: ffffffc974cd091c x14: ffffffffffffffff
>>> [   40.698773] x13: ffffffc974cd01cd x12: 0000000000000030
>>> [   40.704036] x11: 0101010101010101 x10: 7f7f7f7f7f7f7f7f
>>> [   40.709300] x9 : 0000000040000000 x8 : 0000000000210d00
>>> [   40.714563] x7 : ffffffc975f95018 x6 : 0000000000000000
>>> [   40.719826] x5 : 0000000000000000 x4 : ffffffc9763f1210
>>> [   40.725088] x3 : 0000000000000000 x2 : ffffffc9763f10e8
>>> [   40.730351] x1 : 0000000000000000 x0 : 0000000000020002
>>> [   40.735613]
>>> [   40.737085] Process vfio (pid: 174, stack limit = 0xffffffc974d60020)
>>> [   40.743460] Stack: (0xffffffc974d63c60 to 0xffffffc974d64000)
>>> [   40.749150] 3c60: ffffffc974d63c80 ffffff80084c3dec ffffffc9763e9a00
>>> ffffff80085377a4
>>> [   40.756904] 3c80: ffffffc974d63ca0 ffffff80080948c4 ffffffc9763f10a0
>>> ffffff8008dab568
>>> [   40.764658] 3ca0: ffffffc974d63cc0 ffffff8008764a14 ffffffc9763f10a0
>>> ffffff8008dab568
>>> [   40.772411] 3cc0: ffffffc974d63cd0 ffffff8008552804 ffffffc974d63ce0
>>> ffffff800853ba10
>>> [   40.780165] 3ce0: ffffffc974d63d00 ffffff800853bacc ffffffc9763f1100
>>> ffffffc9763f10a0
>>> [   40.787918] 3d00: ffffffc974d63d20 ffffff800853a868 ffffff8008d68f18
>>> ffffffc9763f10a0
>>> [   40.795672] 3d20: ffffffc974d63d50 ffffff8008539c70 000000000000000d
>>> ffffffc974c8f400
>>> [   40.803425] 3d40: ffffffc9757d5880 0000000000000000 ffffffc974d63d60
>>> ffffff800823ab18
>>> [   40.811178] 3d60: ffffffc974d63d70 ffffff8008239ea8 ffffffc974d63dc0
>>> ffffff80081c507c
>>> [   40.818931] 3d80: 000000000000000d 0000000000000000 ffffffc974c8f100
>>> ffffffc974d63eb8
>>> [   40.826684] 3da0: 000000001285f6a0 0000000000000015 0000000000000123
>>> ffffff80080bf6ac
>>> [   40.834437] 3dc0: ffffffc974d63e40 ffffff80081c5e80 000000000000000d
>>> 0000000000000000
>>> [   40.842190] 3de0: ffffffc974d63e30 ffffff80080c087c ffffffc974d63e20
>>> ffffff80081c5c0c
>>> [   40.849943] 3e00: ffffffc974c8f100 0000000000000001 ffffffc974c8f100
>>> ffffffc974d63eb8
>>> [   40.857696] 3e20: ffffffc974d63e40 ffffff80081c5f48 000000000000000d
>>> ffffffc974c8f100
>>> [   40.865450] 3e40: ffffffc974d63e80 ffffff80081c7274 ffffffc974c8f100
>>> ffffffc974c8f100
>>> [   40.873203] 3e60: 000000001285f6a0 000000000000000d 0000000060000000
>>> 0000000000000000
>>> [   40.880956] 3e80: 0000000000000000 ffffff8008082ef0 0000000000000000
>>> 0000000000000001
>>> [   40.888709] 3ea0: ffffffffffffffff 0000007f8d0ae3dc 0000000000000000
>>> 0000000000000000
>>> [   40.896461] 3ec0: 0000000000000001 000000001285f6a0 000000000000000d
>>> 0000000000000000
>>> [   40.904215] 3ee0: ae2e2e2e3f464b49 0000000000000000 000000001285f6b0
>>> 39322f392f2f2f2f
>>> [   40.911968] 3f00: 0000000000000040 fefefeff2f2d2f2f 7f7f7f7f7f7f7f7f
>>> 0101010101010101
>>> [   40.919721] 3f20: 0000000000000002 0000000000000004 ffffffffffffffff
>>> 0000007f8d136588
>>> [   40.927474] 3f40: 0000000000000000 0000007f8d0ae3c0 0000007fd65069e0
>>> 00000000004ee000
>>> [   40.935226] 3f60: 0000000000000001 000000001285f6a0 000000000000000d
>>> 0000000000000001
>>> [   40.942980] 3f80: 0000000000000020 000000001285eed8 00000000004ba158
>>> 0000000000000000
>>> [   40.950732] 3fa0: 0000000000000000 0000007fd6507f30 000000000040e74c
>>> 0000007fd6507130
>>> [   40.958485] 3fc0: 0000007f8d0ae3dc 0000000060000000 0000000000000001
>>> 0000000000000040
>>> [   40.966238] 3fe0: 0000000000000000 0000000000000000 0000002000103a00
>>> 4000000010000000
>>> [   40.973986] Call trace:
>>> [   40.976405] Exception stack(0xffffffc974d63a90 to 0xffffffc974d63bc0)
>>> [   40.982780] 3a80:                                   0000000000020002
>>> 0000008000000000
>>> [   40.990533] 3aa0: ffffffc974d63c60 ffffff800834d1bc ffffffc974d63ae0
>>> ffffff80085377a4
>>> [   40.998287] 3ac0: ffffffc974d63b10 ffffff8008537424 ffffffc975e3ac28
>>> ffffffc975e3ac38
>>> [   41.006041] 3ae0: ffffffc974d63b30 ffffff80081737cc ffffffc975e3ac38
>>> ffffff8008da62c0
>>> [   41.013794] 3b00: ffffffc975e98100 ffffff80085401b0 0000000000000001
>>> ffffff8008540a08
>>> [   41.021547] 3b20: 00000000000036b8 0000000000000040 0000000000020002
>>> 0000000000000000
>>> [   41.029300] 3b40: ffffffc9763f10e8 0000000000000000 ffffffc9763f1210
>>> 0000000000000000
>>> [   41.037053] 3b60: 0000000000000000 ffffffc975f95018 0000000000210d00
>>> 0000000040000000
>>> [   41.044805] 3b80: 7f7f7f7f7f7f7f7f 0101010101010101 0000000000000030
>>> ffffffc974cd01cd
>>> [   41.052558] 3ba0: ffffffffffffffff ffffffc974cd091c 0000000000000001
>>> 0000000000000007
>>> [   41.060311] [<ffffff800834d1bc>] kobject_get+0x14/0x88
>>> [   41.065398] [<ffffff80084c3dec>] iommu_get_domain_for_dev+0x1c/0x48
>>> [   41.071607] [<ffffff80080948c4>] arch_teardown_dma_ops+0x14/0x68
>>> [   41.077556] [<ffffff8008764a14>] of_dma_deconfigure+0xc/0x18
>>> [   41.083161] [<ffffff8008552804>] dma_deconfigure+0xc/0x18
>>> [   41.088509] [<ffffff800853ba10>] __device_release_driver+0x88/0x120
>>> [   41.094715] [<ffffff800853bacc>] device_release_driver+0x24/0x38
>>> [   41.100663] [<ffffff800853a868>] unbind_store+0xe8/0x110
>>> [   41.105922] [<ffffff8008539c70>] drv_attr_store+0x20/0x30
>>> [   41.111268] [<ffffff800823ab18>] sysfs_kf_write+0x48/0x58
>>> [   41.116612] [<ffffff8008239ea8>] kernfs_fop_write+0xb0/0x1d8
>>> [   41.122216] [<ffffff80081c507c>] __vfs_write+0x1c/0x100
>>> [   41.127390] [<ffffff80081c5e80>] vfs_write+0xa0/0x1b8
>>> [   41.132391] [<ffffff80081c7274>] SyS_write+0x44/0xa0
>>> [   41.137307] [<ffffff8008082ef0>] el0_svc_naked+0x24/0x28
>>> [   41.142567] Code: 910003fd f9000bf3 aa0003f3 b4000180 (3940f000)
>>> [   41.148667] ---[ end trace 35c1e743d6e6c037 ]---
>>> Segmentation fault
>>> / #
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
>
>_______________________________________________
>linux-arm-kernel mailing list
>linux-arm-kernel at lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 4/9] ASoC: wm9713: add ac97 new bus support
From: Charles Keepax @ 2016-10-27  8:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477510907-23495-5-git-send-email-robert.jarzmik@free.fr>

On Wed, Oct 26, 2016 at 09:41:42PM +0200, Robert Jarzmik wrote:
> Add support for the new ac97 bus model, where devices are automatically
> discovered on AC-Links.
> 
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> ---

Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>

Thanks,
Charles

^ permalink raw reply

* [PATCH 6/9] power_supply: wm97xx_battery: use power_supply_get_drvdata
From: Charles Keepax @ 2016-10-27  8:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477510907-23495-7-git-send-email-robert.jarzmik@free.fr>

On Wed, Oct 26, 2016 at 09:41:44PM +0200, Robert Jarzmik wrote:
> As the power supply framework provides a way to store and retrieve
> private supply data, use it.
> 
> In the process, change the platform data for wm97xx_battery from a
> container of a single struct wm97xx_batt_pdata to the direct point to wm97xx_batt_pdata.
> 
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> ---

Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>

Thanks,
Charles

^ permalink raw reply

* [PATCH v8 0/3] ARM: dts: imx6q: Add Engicam i.CoreM6 dts
From: Jagan Teki @ 2016-10-27  8:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477037153-20484-1-git-send-email-jteki@openedev.com>

Hi Shawn,

On Fri, Oct 21, 2016 at 1:35 PM, Jagan Teki <jteki@openedev.com> wrote:
> From: Jagan Teki <jagan@amarulasolutions.com>
>
> This is series add dts support for Engicam I.Core M6 qdl modules. just
> rebased on top of linux-next.
>
> Jagan Teki (3):
>   ARM: dts: imx6q: Add Engicam i.CoreM6 Quad/Dual initial support
>   ARM: dts: imx6q: Add Engicam i.CoreM6 DualLite/Solo initial support
>   ARM: dts: imx6qdl-icore: Add FEC support
>
>  arch/arm/boot/dts/Makefile           |   2 +
>  arch/arm/boot/dts/imx6dl-icore.dts   |  59 ++++++++
>  arch/arm/boot/dts/imx6q-icore.dts    |  59 ++++++++
>  arch/arm/boot/dts/imx6qdl-icore.dtsi | 265 +++++++++++++++++++++++++++++++++++
>  4 files changed, 385 insertions(+)
>  create mode 100644 arch/arm/boot/dts/imx6dl-icore.dts
>  create mode 100644 arch/arm/boot/dts/imx6q-icore.dts
>  create mode 100644 arch/arm/boot/dts/imx6qdl-icore.dtsi

Please let me know if you have any inputs on this?

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

^ permalink raw reply

* [PATCH] ARM: imx: gpc: Initialize all power domains
From: Lucas Stach @ 2016-10-27  8:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161019141556.GA18806@tiger>

Am Mittwoch, den 19.10.2016, 22:15 +0800 schrieb Shawn Guo:
> On Tue, Oct 11, 2016 at 02:53:33PM -0300, Fabio Estevam wrote:
> > When booting a kernel built with multi_v7_defconfig the following
> > probe error is seen:
> > 
> > imx-gpc: probe of 20dc000.gpc failed with error -22
> > 
> > Later on the kernel crashes like this:
> > 
> > [    1.723358] Unable to handle kernel NULL pointer dereference at virtual address 00000040
> > [    1.731500] pgd = c0204000
> > [    1.731863] hctosys: unable to open rtc device (rtc0)
> > [    1.739301] [00000040] *pgd=00000000
> > [    1.739310] Internal error: Oops: 5 [#1] SMP ARM
> > [    1.739319] Modules linked in:
> > [    1.739328] CPU: 1 PID: 95 Comm: kworker/1:4 Not tainted 4.8.0-11897-g6b5e09a #1
> > [    1.739331] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
> > [    1.739352] Workqueue: pm genpd_power_off_work_fn
> > [    1.739356] task: ee63d400 task.stack: ee70a000
> > [    1.739365] PC is at mutex_lock+0xc/0x4c
> > [    1.739374] LR is at regulator_disable+0x2c/0x60
> > [    1.739379] pc : [<c0bc0da0>]    lr : [<c06e4b10>]    psr: 60000013
> > [    1.739379] sp : ee70beb0  ip : 10624dd3  fp : ee6e6280
> > [    1.739382] r10: eefb0900  r9 : 00000000  r8 : c1309918
> > [    1.739385] r7 : 00000000  r6 : 00000040  r5 : 00000000  r4 : 00000040
> > [    1.739390] r3 : 0000004c  r2 : 7fffd540  r1 : 000001e4  r0 : 00000040
> > 
> > The gpc probe fails because of_genpd_add_provider_onecell() checks
> > if all the domains are initialized via pm_genpd_present() function
> > and it returns an error on the multi_v7_defconfig case.
> 
> It's not clear to me why this is only with multi_v7_defconfig, not
> imx_v6_v7_defconfig.  Also, is it a regression or long-standing issue?

It's a regression in v4.9 and should be applied as a fix.

I don't see the crash on imx_v6_v7_defconfig, but without this patch the
GPC no longer probes correctly on v4.9 and other dependent devices will
not show up at all.

Regards,
Lucas

^ permalink raw reply

* [PATCH] fpga zynq: Check the bitstream for validity
From: Matthias Brugger @ 2016-10-27  8:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161026225413.GA6220@obsidianresearch.com>



On 10/27/2016 12:54 AM, Jason Gunthorpe wrote:
> There is no sense in sending a bitstream we know will not work, and
> with the variety of options for bitstream generation in Xilinx tools
> it is not terribly clear or very well documented what the correct
> input should be, especially since auto-detection was removed from this
> driver.
>
> All Zynq full configuration bitstreams must start with the sync word in
> the correct byte order.
>
> Zynq is also only able to DMA dword quantities, so bitstreams must be
> a multiple of 4 bytes. This also fixes a DMA-past the end bug.
>
> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> ---
>  drivers/fpga/zynq-fpga.c | 25 ++++++++++++++++---------
>  1 file changed, 16 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
> index c2fb4120bd62..46a38772e7ee 100644
> --- a/drivers/fpga/zynq-fpga.c
> +++ b/drivers/fpga/zynq-fpga.c
> @@ -184,12 +184,26 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
>
>  	priv = mgr->priv;
>
> +	/* All valid bitstreams are multiples of 32 bits */
> +	if ((count % 4) != 0)
> +		return -EINVAL;
> +
>  	err = clk_enable(priv->clk);
>  	if (err)
>  		return err;
>
>  	/* don't globally reset PL if we're doing partial reconfig */
>  	if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) {
> +		/* Sanity check the proposed bitstream. It must start with the
> +		 * sync word in the correct byte order and be a multiple of 4
> +		 * bytes.
> +		 */
> +		if (count <= 4 || buf[0] != 0x66 || buf[1] != 0x55 ||
> +		    buf[2] != 0x99 || buf[3] != 0xaa) {

This checks if the bit stream is bigger then 4 bytes. We error out 
before, if it is smaller. So you should fix the wording in the comment 
and check for count == 4.

Regards,
Matthias

^ permalink raw reply

* [PATCH 7/9] Input: wm97xx: split out touchscreen registering
From: Charles Keepax @ 2016-10-27  9:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477510907-23495-8-git-send-email-robert.jarzmik@free.fr>

On Wed, Oct 26, 2016 at 09:41:45PM +0200, Robert Jarzmik wrote:
> wm97xx-core does several things in it initialization :
>  - touchscreen input device setup
>  - battery device creation
> 
> As the wm97xx is actually a multi-function device handling an audio
> codec, a touchscreen, a gpio block and an ADC, reshape the probing to
> isolate what is truly input/touchscreen specific from the remaining
> part.
> 
> This is only code shuffling, there is no functional change.
> 
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> ---
>  drivers/input/touchscreen/wm97xx-core.c | 193 ++++++++++++++++++--------------
>  1 file changed, 112 insertions(+), 81 deletions(-)
> 
> diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
> index 83cf11312fd9..50a110e2988b 100644
<snip>
> +static void wm97xx_remove_battery(struct wm97xx *wm)
> +{
> +	platform_device_put(wm->battery_dev);
> +}
<snip>
> @@ -724,10 +757,8 @@ static int wm97xx_remove(struct device *dev)
>  {
>  	struct wm97xx *wm = dev_get_drvdata(dev);
>  
> -	platform_device_unregister(wm->battery_dev);
> -	platform_device_unregister(wm->touch_dev);
> -	input_unregister_device(wm->input_dev);
> -	kfree(wm);
> +	wm97xx_remove_battery(wm);

The commit message says this is just shifting code around but the
platform_device_unregister for the battery_dev seems to have
turned into a platform_device_put here.

Thanks,
Charles

^ permalink raw reply

* [PATCH v2 2/4] dt-bindings: Add TI SCI PM Domains
From: Tero Kristo @ 2016-10-27  9:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161026220457.kvbd4wgtizdbndf3@rob-hp-laptop>

On 27/10/16 01:04, Rob Herring wrote:
> On Wed, Oct 19, 2016 at 03:33:45PM -0500, Dave Gerlach wrote:
>> Add a generic power domain implementation, TI SCI PM Domains, that
>> will hook into the genpd framework and allow the TI SCI protocol to
>> control device power states.
>>
>> Also, provide macros representing each device index as understood
>> by TI SCI to be used in the device node power-domain references.
>> These are identifiers for the K2G devices managed by the PMMC.
>>
>> Signed-off-by: Nishanth Menon <nm@ti.com>
>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>> ---
>>  .../devicetree/bindings/soc/ti/sci-pm-domain.txt   | 54 +++++++++++++
>>  MAINTAINERS                                        |  2 +
>>  include/dt-bindings/genpd/k2g.h                    | 90 ++++++++++++++++++++++
>>  3 files changed, 146 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
>>  create mode 100644 include/dt-bindings/genpd/k2g.h
>>
>> diff --git a/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
>> new file mode 100644
>> index 000000000000..32f38a349656
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
>> @@ -0,0 +1,54 @@
>> +Texas Instruments TI-SCI Generic Power Domain
>> +---------------------------------------------
>> +
>> +Some TI SoCs contain a system controller (like the PMMC, etc...) that is
>> +responsible for controlling the state of the IPs that are present.
>> +Communication between the host processor running an OS and the system
>> +controller happens through a protocol known as TI-SCI [1]. This pm domain
>> +implementation plugs into the generic pm domain framework and makes use of
>> +the TI SCI protocol power on and off each device when needed.
>> +
>> +[1] Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
>> +
>> +PM Domain Node
>> +==============
>> +The PM domain node represents the global PM domain managed by the PMMC,
>> +which in this case is the single implementation as documented by the generic
>> +PM domain bindings in Documentation/devicetree/bindings/power/power_domain.txt.
>> +
>> +Required Properties:
>> +--------------------
>> +- compatible: should be "ti,sci-pm-domain"
>> +- #power-domain-cells: Must be 0.
>> +- ti,sci: Phandle to the TI SCI device to use for managing the devices.
>> +
>> +Example:
>> +--------------------
>> +k2g_pds: k2g_pds {
>> +        compatible = "ti,sci-pm-domain";
>> +        #power-domain-cells = <0>;
>> +        ti,sci = <&pmmc>;
>> +};
>
> Why not just make the PMMC node be the power-domain provider itself? If
> not that, then make this a child node of it. The same comment applies to
> all the SCI functions, but I guess I've already acked some of them.

This seems to be a bug in this documentation actually. ti,sci handle is 
no longer supported, and all the sci stuff must be under the parent sci 
node.

>
> I really don't like reviewing all these TI SCI bindings one by one. Each
> one on its own seems fine, but I don't see the full picture.

The full picture is represented under the documentation for the main 
protocol support itself. See this patch:

https://patchwork.kernel.org/patch/9383281/

Copy pasted here as ref:

Example (K2G):
-------------
         pmmc: pmmc {
                 compatible = "ti,k2g-sci";
                 ...

                 my_clk_node: clk_node {
                         ...
                         ...
                 };

                 my_pd_node: pd_node {
                         ...
                         ...
                 };
         };

^ permalink raw reply

* [RFC PATCH 1/5] of: introduce the overlay manager
From: Matthias Brugger @ 2016-10-27  9:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161026145756.21689-2-antoine.tenart@free-electrons.com>



On 10/26/2016 04:57 PM, Antoine Tenart wrote:
> The overlay manager is an in-kernel library helping to handle dt overlay
> loading when using capes.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
> ---
>  drivers/of/Kconfig                           |   2 +
>  drivers/of/Makefile                          |   1 +
>  drivers/of/overlay-manager/Kconfig           |   6 +
>  drivers/of/overlay-manager/Makefile          |   1 +
>  drivers/of/overlay-manager/overlay-manager.c | 199 +++++++++++++++++++++++++++
>  include/linux/overlay-manager.h              |  38 +++++
>  6 files changed, 247 insertions(+)
>  create mode 100644 drivers/of/overlay-manager/Kconfig
>  create mode 100644 drivers/of/overlay-manager/Makefile
>  create mode 100644 drivers/of/overlay-manager/overlay-manager.c
>  create mode 100644 include/linux/overlay-manager.h
>
> diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
> index bc07ad30c9bf..e57aeaf0bf4f 100644
> --- a/drivers/of/Kconfig
> +++ b/drivers/of/Kconfig
> @@ -116,4 +116,6 @@ config OF_OVERLAY
>  config OF_NUMA
>  	bool
>
> +source "drivers/of/overlay-manager/Kconfig"
> +
>  endif # OF
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index d7efd9d458aa..d738fd41271f 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -16,3 +16,4 @@ obj-$(CONFIG_OF_OVERLAY) += overlay.o
>  obj-$(CONFIG_OF_NUMA) += of_numa.o
>
>  obj-$(CONFIG_OF_UNITTEST) += unittest-data/
> +obj-y += overlay-manager/
> diff --git a/drivers/of/overlay-manager/Kconfig b/drivers/of/overlay-manager/Kconfig
> new file mode 100644
> index 000000000000..eeb76054dcb8
> --- /dev/null
> +++ b/drivers/of/overlay-manager/Kconfig
> @@ -0,0 +1,6 @@
> +config OF_OVERLAY_MGR
> +	bool "Device Tree Overlay Manager"
> +	depends on OF_OVERLAY
> +	help
> +	  Enable the overlay manager to handle automatic overlay loading when
> +	  devices are detected.
> diff --git a/drivers/of/overlay-manager/Makefile b/drivers/of/overlay-manager/Makefile
> new file mode 100644
> index 000000000000..86d2b53950e7
> --- /dev/null
> +++ b/drivers/of/overlay-manager/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_OF_OVERLAY_MGR)			+= overlay-manager.o
> diff --git a/drivers/of/overlay-manager/overlay-manager.c b/drivers/of/overlay-manager/overlay-manager.c
> new file mode 100644
> index 000000000000..a725d7e24d38
> --- /dev/null
> +++ b/drivers/of/overlay-manager/overlay-manager.c
> @@ -0,0 +1,199 @@
> +/*
> + * Copyright (C) 2016 - Antoine Tenart <antoine.tenart@free-electrons.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/firmware.h>
> +#include <linux/list.h>
> +#include <linux/of.h>
> +#include <linux/of_fdt.h>
> +#include <linux/overlay-manager.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +
> +struct overlay_mgr_overlay {
> +	struct list_head list;
> +	char *name;
> +};
> +
> +LIST_HEAD(overlay_mgr_overlays);
> +LIST_HEAD(overlay_mgr_formats);

Maybe you can find some better names for this, or rename the structs.
This will make the code more readable.

> +DEFINE_SPINLOCK(overlay_mgr_lock);
> +DEFINE_SPINLOCK(overlay_mgr_format_lock);

As Thomas already said, a mutex should be fine. We are not doing any 
time critical here, right?

> +
> +/*
> + * overlay_mgr_register_format()
> + *
> + * Adds a new format candidate to the list of supported formats. The registered
> + * formats are used to parse the headers stored on the dips.
> + */
> +int overlay_mgr_register_format(struct overlay_mgr_format *candidate)
> +{
> +	struct overlay_mgr_format *format;
> +	int err = 0;
> +
> +	spin_lock(&overlay_mgr_format_lock);
> +
> +	/* Check if the format is already registered */
> +	list_for_each_entry(format, &overlay_mgr_formats, list) {
> +		if (!strcpy(format->name, candidate->name)) {
> +			err = -EEXIST;
> +			goto err;
> +		}
> +	}
> +
> +	list_add_tail(&candidate->list, &overlay_mgr_formats);
> +
> +err:
> +	spin_unlock(&overlay_mgr_format_lock);
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(overlay_mgr_register_format);
> +
> +/*
> + * overlay_mgr_parse()
> + *
> + * Parse raw data with registered format parsers. Fills the candidate string if
> + * one parser understood the raw data format.
> + */
> +int overlay_mgr_parse(struct device *dev, void *data, char ***candidates,
> +		      unsigned *n)
> +{
> +	struct list_head *pos, *tmp;
> +	struct overlay_mgr_format *format;
> +
> +	list_for_each_safe(pos, tmp, &overlay_mgr_formats) {
> +		format = list_entry(pos, struct overlay_mgr_format, list);
> +
> +		format->parse(dev, data, candidates, n);
> +		if (n > 0)
> +			return 0;
> +	}
> +
> +	return -EINVAL;
> +}
> +EXPORT_SYMBOL_GPL(overlay_mgr_parse);
> +
> +static int overlay_mgr_check_overlay(struct device_node *node)
> +{
> +	struct property *p;
> +	const char *str = NULL;
> +
> +	p = of_find_property(node, "compatible", NULL);
> +	if (!p)
> +		return -EINVAL;
> +
> +	do {
> +		str = of_prop_next_string(p, str);
> +		if (of_machine_is_compatible(str))
> +			return 0;
> +	} while (str);
> +
> +	return -EINVAL;
> +}
> +
> +/*
> + * _overlay_mgr_insert()
> + *
> + * Try to request and apply an overlay given a candidate name.
> + */
> +static int _overlay_mgr_apply(struct device *dev, char *candidate)

Should be __overlay_mgr_apply(...)

Cheers,
Matthias

^ permalink raw reply

* [PATCH 8/9] mfd: wm97xx-core: core support for wm97xx Codec
From: Charles Keepax @ 2016-10-27  9:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477510907-23495-9-git-send-email-robert.jarzmik@free.fr>

On Wed, Oct 26, 2016 at 09:41:46PM +0200, Robert Jarzmik wrote:
> The WM9705, WM9712 and WM9713 are highly integrated codecs, with an
> audio codec, DAC and ADC, GPIO unit and a touchscreen interface.
> 
> Historically the support was spread across drivers/input/touchscreen and
> sound/soc/codecs. The sharing was done through ac97 bus sharing. This
> model will not withstand the new AC97 bus model, where codecs are
> discovered on runtime.
> 
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> ---

Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>

Thanks,
Charles

^ permalink raw reply

* [PATCH 9/9] Input: wm97xx: add new AC97 bus support
From: Charles Keepax @ 2016-10-27  9:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477510907-23495-10-git-send-email-robert.jarzmik@free.fr>

On Wed, Oct 26, 2016 at 09:41:47PM +0200, Robert Jarzmik wrote:
> This adds support for the new AC97 bus code, which discovers the devices
> rather than uses platform data.
> 
> As part of this discovery, it enables a multi-function device wm97xx,
> which supports touchscreen, battery, ADC and an audio codec. This patch
> adds the code to bind the touchscreen "cell" as the touchscreen driver.
> 
> This was tested on the pxa architecture with a pxa270 + wm9713 + the
> mioa701 touchscreen.
> 
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> ---

Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>

Thanks,
Charles

^ permalink raw reply

* [PATCH v3] drivers: psci: PSCI checker module
From: Lorenzo Pieralisi @ 2016-10-27  9:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161026181148.GW3716@linux.vnet.ibm.com>

On Wed, Oct 26, 2016 at 11:11:48AM -0700, Paul E. McKenney wrote:
> On Wed, Oct 26, 2016 at 06:35:34PM +0100, Lorenzo Pieralisi wrote:
> > On Wed, Oct 26, 2016 at 10:22:52AM -0700, Paul E. McKenney wrote:
> > > On Wed, Oct 26, 2016 at 06:10:06PM +0100, Lorenzo Pieralisi wrote:
> 
> [ . . . ]
> 
> > > > Thanks a lot for your feedback, thoughts appreciated.
> > > 
> > > Let me ask the question more directly.
> > > 
> > > Why on earth are we trying to run these tests concurrently?
> > 
> > We must prevent that, no question about that, that's why I started
> > this discussion. It is not fine to enable this checker and the
> > RCU/LOCK torture hotplug tests at the same time.
> > 
> > > After all, if we just run one at a time in isolation, there is no
> > > problem.
> > 
> > Fine by me, it was to understand if the current assumptions we made
> > are correct and they are definitely not. If we enable the PSCI checker
> > we must disable the torture rcu/lock hotplug tests either statically or
> > dynamically.
> 
> What rcutorture, locktorture, and rcuperf do is to invoke
> torture_init_begin(), which returns false if one of these tests
> is already running.
> 
> Perhaps we should extract this torture-test-exclusion and require
> than conflicting torture tests invoke it?

Yes if it can be extracted as a check (but it should also prevent the
torture tests from running and vice versa), either that or Kconfig
dependency (which we could do as a first step, waiting to add the
required interface to the torture test code ?).

Thanks !
Lorenzo

^ permalink raw reply

* Add Allwinner Q8 tablets hardware manager
From: Hans de Goede @ 2016-10-27  9:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAJ-oXjQbOkrkNToEXYmPUZOgYBGbxQREZ4NL4bMcZmG=KP2vQQ@mail.gmail.com>

Hi,

On 27-10-16 01:45, Pierre-Hugues Husson wrote:
> Hi,
>
> 2016-10-26 13:46 GMT+02:00 Hans de Goede <hdegoede at redhat.com <mailto:hdegoede@redhat.com>>:
>
>> And as I tried to explain before, for this specific use-case describing
>> all this board specific knowledge in a generic manner in dt is simply
>> impossible, unless we add a turing complete language to dt aka aml.
>
>
> You keep saying this is a "specific use-case", but I don't agree.
> Most of cheap phone and tablets SoC manufacturer's Linux variant that I know of have (rather stupid) auto-detection methods.

True.

> Not every phone manufacturer use it, because some have proper and constant supply chain, but still, that's not always the case.
> For instance you might look at this dts: https://github.com/Dee-UK/RK3288_Lollipop_Kernel/commit/9e056a10b0a773d285e8d2ae819e7c2451816492#diff-b25e1abc92522c85e9ef28704bf9284aR410
> This DTS is meant, like what you do, to be compatible with as many devices as possible at once.
> So it declares 4 different PMICs (and no they will never all be there at the same time), and two different accelerometers, 3 audio codecs, and two touchscreens.
> Or you can look at CodeAurora (Qualcomm public opensource tree) DTSs and see that a standard DTS support at least three different panels ( see https://github.com/omnirom/android_kernel_oppo_msm8974/blob/27080b724f4cf281d598e7830abc5fc1292b5803/arch/arm/boot/dts/msm8974-mtp.dtsi#L15 )
> And that's the fairly clean examples. Some SoC kernels are still using good old platform_data detection methods.
>
> Thus I believe that having a board-specific driver is not a good thing, because we would get many of those.

In my experience with these cheap boards, there is a mix of auto-probing +
device / revision specific os-image modifications. I keep coming back to
the touchscreen controller firmware (but also the orientation), for the
gsl1680 controller I need at least 2 different firmware files (per gsl1680
revision) to make all q8 tablets I have working. This is simply not solved
by the vendor android code, they just shove the right firmware into the
os-image. Likewise for the touchscreen orientation (x-mirored, y-mirored,
etc) too is just a hard-coded setting in the os-image.

Thinking more about this, we may be able to come up with a generic way to
deal with i2c device detection, just like many vendor os-images are doing.

The kernel actually already has a detect() method in struct i2c_driver,
we could use that (we would need to implement it in drivers which do not
have it yet). Note on second thought it seems it may be better to use
probe() for this, see below.

Then we could have something like this in dt:

&i2c0 {
	touchscreen1: gsl1680 at 40 {
		reg = <0x40>;
		compatible = "silead,gsl1680";
		enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
		status = "disabled";
	};

	touchscreen2: ektf2127 at 15 {
		reg = <0x15>;
		compatible = "elan,ektf2127";
		enable-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
		status = "disabled";
	};

	i2c-probe-stop-at-first-match = <&touchscreen1>, <&touchscreen2>;
}

Which would make the i2c subsys call detect (*) on each device, until
a device is found. Likewise we could have a "i2c-probe-all" property
which also walks a list of phandles but does not stop on the first
match.

Mark would something like this scheme work for you ?

Note that things are not this simple though, there are multiple challenges
with this approach:

1) pinctrl, even the detect() method of the driver may need to use
e.g. some gpios so we would need to activate pinctrl as normally the
kernel device core would do this before calling probe(). This is solvable,
but I wonder if we need to mention anything about this in the bindings
docs ? Note this would be solved by just instantiating the client / device
and then try probe().

2) Note the enable-gpios, those will need to be handled in the detect()
method, but this requires a device to be instantiated to call devm_get_...
on, likewise for other resources.

Alternatively the probe code could know about this (as part of the
i2c-probe-stop-at-first-match binding) and enable it before probing ?

3) Optional regulators, I've one q8 tablet where the touchscreen is
powered by a separate regulator, currently my hardware-mgr simply
first tries to probe all possible models with the regulator disabled
(and stops at -ETIMEDOUT which means the i2c bus is stuck and further
  probing without enabling the regulator is useless).

How do we deal with this? This is a tricky one do we do this in
the code which walks over the i2c-probe-stop-at-first-match list,
or do we punt this to the driver?

Sofar I've only seen this with one type of touchscreen so an easy cop-out
would be to add an "optional-vddio-supply" to the the bindings for the
specific touchscreen use and put all the necessary logic in the driver.

This does require propagating the learned need for the regulator
from the drivers detect() callback to probe() or alternatively I'm
thinking we should just use probe() instead of detect()to begin with,
that will save a lot of duplication with things
like code for enable gpio-s and regulators.

So assuming we go for the cop-out option for 3. (I'm ok with that),
this would be a pretty clean solution adding just the 2 new:
i2c-probe-stop-at-first-match and i2c-probe-all properties to
the i2c-bus bindings. One problem here is that we may want to have
multiple i2c-probe-stop-at-first-match phandle lists on a single bus
(e.g. try 3 touchscreens + 6 accelerometers on the same bus, stop at
first touchscreen / first accelerometer), anyone have any ideas for
that?


*) Yes this sounds Linux specific, but it really is just "execute to-be-probed
device compatible specific detection method"


> When it comes to detection, I've witnessed various things.
> It can be kernel-side or bootloader-side "global setting" reading (like an ADC/resistor value, or an OTP), it can be bootloader doing the "brute-force", or it can be the kernel doing all the probes.
>
> For instance, as of today, on a Spreadtrum ODM tree, the bootloader will detect the screen by testing all knowns screens, the screen-drivers declare a get_id function, and the bootloader probes until the get_id matches the id declared by the screen driver.
> And then the bootloader tells the kernel, via cmdline, which screen is actually there (but auto-detection is also coded in kernel).
> Finally all possible sensors/touchscreen/camera are declared in DTS, and probe will filter-out N/C ones in the kernel.
>
> Now the big difference between my experience and what Hans is trying to do, is that I've always worked with devices with "safely" queriable IDs, either on i2c or dsi. I've never encountered SPI. This makes probing inherently more dangerous, but I believe the question roughly remains the same.

I'm dealing with i2c too, Mark mistakenly used SPI in his reply,
which I think is what got you thinking I've SPI.

> I understand Mark's will of taking care of this "earlier" (either bootloader or a later kernel-loader (pxa-impedance-matcher)), but I feel like this is only giving the problem to someone else.

Big ack to this, moving this to the bootloader is not solving the
problem, it just moves the problem elsewhere.

> I think that those auto-detection methods should be declared in a device-tree, though as Hans noted, this might end to be a turing-complete language.

See above, I think that we can make this work by delegating the actual
detection to the driver (so each compatible can have a different detect method / code).

So with this we can remove a big part of drivers/misc/q8-hardwaremgr.c, but not all
of it. We still need board specific code somewhere to deal with things like picking
the right touchscreen firmware and touchscreen orientation. This is all somewhat
gsl1680 specific.

I actually have the same problem on x86 where the ACPI description of the device
basically says: "There is a gsl1680 at this bus at this address" and does not say
anything about firmware / orientation (again this is simply hardcoded
in the os-image these devices ship with).

For x86 my plan is to have an array of configs in the driver and select the right
one based on DMI strings, which is in essence putting board specific info in the
driver.

I can imagine mirroring this for ARM, and have an array of configs in the driver
there too (for cases where cannot simply hardcode everything in dt only) and have
some board specific code (activated by of_machine_is_compatible()) to select the
right config.

> In my experience, I have never encountered a device requiring more than ordered probes, but backward compatibility was expected. (i.e. if IDs couldn't help distinguish two devices, the manufacturer would add another way to identify)
>
> As to whether this is bootloader's job or kernel's job, I don't have a really strong opinion.
> On one side, the kernel has all the drivers and probe functions, this would need little work to make this work.
> On the other side, if the "rules" are something like "read bus XXX, address YYY, expect ZZZ", the bootloader can handle it as well. But I don't think it is a good idea to have the bootloader know all the gsensor/screen/camera/... drivers (even if they are partial drivers dedicated to detection only)

Ack I to really believe this belongs in the kernel. Thank you for your reply,
it has made me realized that there are 2 problems here:

1) auto-detect of i2c-devices from a fixed list of i2c devices the board may
have, for this we really need 2 bits: a) generic mechanism to describe this,
call the driver detect methods b) hardware (compatible) specific detection
routines. b) really belongs in the driver, and since things like sensor
drivers (another good example btw) do not belong in the bootloader we
really need this bit in the kernel.

If we can get some consensus on this I'm willing to work on this
(as time allows, this is a spare time project). At least up to feature parity
with my current hard-coded q8-hardwaremgr.c, which in hind-sight indeed is
ugly as the detect code really belongs in the driver (I've been copy and
pasting about 10 - 30 lines from each driver into q8-hardwaremgr.c).

2) miscellaneous extra config on top of figuring out which ICs are connected,
basically the kind of stuff many vendors simply hard-code in their device
specific os-image. This one is much more difficult to deal with and I think
we need to figure this out on a case by case basis. This will require board
specific code (just like the kernel has tons of DMI string activated board
specific code on x86) and what is the best code for this place to live will
be a case by case thing too.

Regards,

Hans

^ permalink raw reply

* [PATCH 1/5] net: phy: broadcom: Add BCM54810 phy entry
From: Andrew Lunn @ 2016-10-27  9:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477510561-17035-2-git-send-email-jon.mason@broadcom.com>

On Wed, Oct 26, 2016 at 03:35:57PM -0400, Jon Mason wrote:
> From: Vikas Soni <vsoni@broadcom.com>
> 
> Add BCM54810 phy entry

Hi Jon, Vikis

The subject line is a bit misleading. It does more than add a PHY ID
entry.

> Signed-off-by: Vikas Soni <vsoni@broadcom.com>
> Signed-off-by: Jon Mason <jon.mason@broadcom.com>
> ---
>  drivers/net/phy/Kconfig    |  2 +-
>  drivers/net/phy/broadcom.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/brcmphy.h    |  7 +++++
>  3 files changed, 73 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index 45f68ea..31967ca 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 870327e..cdce761 100644
> --- a/drivers/net/phy/broadcom.c
> +++ b/drivers/net/phy/broadcom.c
> @@ -35,6 +35,35 @@ 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;
> +
> +	/* Disable BroadR-Reach */
> +	rc = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL, 0);
> +	if (rc < 0)
> +		return rc;
> +
> +	/* SKEW DISABLE */
> +	rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
> +				  0xF0E0);
> +	if (rc < 0)
> +		return rc;
> +
> +	/* DELAY DISABLE */
> +	rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
> +				  0x7000);

This driver mostly uses symbolic names, not #defines. Please can you
use #defines here and else were in this patch.


> +	if (rc < 0)
> +		return rc;
> +
> +	/* DELAY DISABLE */
> +	rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, 0);
> +	if (rc < 0)
> +		return rc;

Twice the same comment?

> +
> +	return 0;
> +}
> +
>  /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
>  static int bcm50610_a0_workaround(struct phy_device *phydev)
>  {
> @@ -207,6 +236,20 @@ 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;
> +
> +		reg = phy_read(phydev, MII_BMCR);
> +		if (reg < 0)
> +			return reg;
> +
> +		err = phy_write(phydev, MII_BMCR, reg & ~BMCR_PDOWN);
> +		if (err)
> +			return err;

This seems a bit odd. I would expect the PHY core correctly handles
the PHY being powered down. Can you explain this a bit more, why it is
needed.

	Thanks
		Andrew

^ permalink raw reply

* [PATCH 2/5] Documentation: devicetree: net: add NS2 bindings to amac
From: Andrew Lunn @ 2016-10-27  9:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477510561-17035-3-git-send-email-jon.mason@broadcom.com>

On Wed, Oct 26, 2016 at 03:35:58PM -0400, Jon Mason wrote:
> Signed-off-by: Jon Mason <jon.mason@broadcom.com>
> ---
>  Documentation/devicetree/bindings/net/brcm,amac.txt | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/net/brcm,amac.txt b/Documentation/devicetree/bindings/net/brcm,amac.txt
> index ba5ecc1..f92caee 100644
> --- a/Documentation/devicetree/bindings/net/brcm,amac.txt
> +++ b/Documentation/devicetree/bindings/net/brcm,amac.txt
> @@ -2,15 +2,18 @@ Broadcom AMAC Ethernet Controller Device Tree Bindings
>  -------------------------------------------------------------
>  
>  Required properties:
> - - compatible:	"brcm,amac" or "brcm,nsp-amac"
> + - compatible:	"brcm,amac", "brcm,nsp-amac", or "brcm,ns2-amac"
>   - reg:		Address and length of the GMAC registers,
>  		Address and length of the GMAC IDM registers
> +		Address and length of the NIC Port Manager registers (optional)
>   - reg-names:	Names of the registers.  Must have both "amac_base" and
> -		"idm_base"
> +		"idm_base". "nicpm_base" is optional (required for NS2)
>   - interrupts:	Interrupt number
>  
>  Optional properties:
>  - mac-address:	See ethernet.txt file in the same directory
> +- brcm,enet-phy-lane-swap:
> +		boolean; Swap the PHY lanes (needed on some SKUs of NS2)

Maybe i'm missing something here, but the patch to the PHY swapped the
lanes. This seems to be a PHY property, not a MAC property. And it
swapped them unconditionally....

	Andrew

^ permalink raw reply

* [RFC PATCH 5/5] of: overlay-mgr: add a detector for headers stored on a ds2431 eeprom over w1
From: Matthias Brugger @ 2016-10-27  9:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161026145756.21689-6-antoine.tenart@free-electrons.com>



On 10/26/2016 04:57 PM, Antoine Tenart wrote:
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
> ---

Please provide a commit message.

>  drivers/of/overlay-manager/Kconfig | 10 ++++++++++
>  drivers/w1/slaves/w1_ds2431.c      | 39 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 49 insertions(+)
>
> diff --git a/drivers/of/overlay-manager/Kconfig b/drivers/of/overlay-manager/Kconfig
> index 1a36613c0c53..ad0a5b8e9e5e 100644
> --- a/drivers/of/overlay-manager/Kconfig
> +++ b/drivers/of/overlay-manager/Kconfig
> @@ -16,4 +16,14 @@ config OF_OVERLAY_MGR_FORMAT_CHIP
>
>  endmenu
>
> +menu "Overlay Manager detectors"
> +
> +config OF_OVERLAY_MGR_DETECTOR_DS2431
> +	bool "Dip header on a DS2431 EEPROM"
> +	depends on W1_SLAVE_DS2431
> +	help
> +	  Enable dip header DS2431 EEPROM support.
> +
> +endmenu
> +
>  endif
> diff --git a/drivers/w1/slaves/w1_ds2431.c b/drivers/w1/slaves/w1_ds2431.c
> index 80572cb63ba8..760325f9a2bd 100644
> --- a/drivers/w1/slaves/w1_ds2431.c
> +++ b/drivers/w1/slaves/w1_ds2431.c
> @@ -15,6 +15,9 @@
>  #include <linux/device.h>
>  #include <linux/types.h>
>  #include <linux/delay.h>
> +#include <linux/slab.h>
> +
> +#include <linux/overlay-manager.h>
>
>  #include "../w1.h"
>  #include "../w1_int.h"
> @@ -280,7 +283,43 @@ static const struct attribute_group *w1_f2d_groups[] = {
>  	NULL,
>  };
>
> +#if IS_ENABLED(CONFIG_OF_OVERLAY_MGR_DETECTOR_DS2431)
> +static int chip_dip_callback(struct w1_slave *sl)
> +{
> +	char **candidates = NULL;
> +	int i, n, err = 0;
> +	u8 *data;
> +
> +	data = kzalloc(OVERLAY_MGR_DIP_MAX_SZ, GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	/* sizeof(struct chip_header) is a mulitple of 8 */
> +	for (i = 0; i < OVERLAY_MGR_DIP_MAX_SZ; i += 8) {
> +		if (w1_f2d_readblock(sl, i, 8, &data[i])) {
> +			err = -EIO;
> +			goto end;
> +		}
> +	}
> +
> +	overlay_mgr_parse(&sl->dev, data, &candidates, &n);
> +	if (!n) {
> +		err = -EINVAL;
> +		goto end;
> +	}
> +
> +	err = overlay_mgr_apply(&sl->dev, candidates, n);
> +
> +end:
> +	kfree(data);
> +	return err;
> +}
> +#endif
> +
>  static struct w1_family_ops w1_f2d_fops = {
> +#if IS_ENABLED(CONFIG_OF_OVERLAY_MGR_DETECTOR_DS2431)
> +	.callback	= chip_dip_callback,
> +#endif
>  	.groups		= w1_f2d_groups,
>  };
>
>

^ permalink raw reply

* [PATCH] arm/arm64: KVM: Perform local TLB invalidation when multiplexing vcpus on a single CPU
From: Christoffer Dall @ 2016-10-27  9:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477323088-18768-1-git-send-email-marc.zyngier@arm.com>

On Mon, Oct 24, 2016 at 04:31:28PM +0100, Marc Zyngier wrote:
> Architecturally, TLBs are private to the (physical) CPU they're
> associated with. But when multiple vcpus from the same VM are
> being multiplexed on the same CPU, the TLBs are not private
> to the vcpus (and are actually shared across the VMID).
> 
> Let's consider the following scenario:
> 
> - vcpu-0 maps PA to VA
> - vcpu-1 maps PA' to VA
> 
> If run on the same physical CPU, vcpu-1 can hit TLB entries generated
> by vcpu-0 accesses, and access the wrong physical page.
> 
> The solution to this is to keep a per-VM map of which vcpu ran last
> on each given physical CPU, and invalidate local TLBs when switching
> to a different vcpu from the same VM.

Just making sure I understand this:  The reason you cannot rely on the
guest doing the necessary distinction with ASIDs or invalidating the TLB
is that a guest (which assumes it's running on hardware) can validly
defer any neccessary invalidation until it starts running on other
physical CPUs, but we do this transparently in KVM?

Thanks,
-Christoffer

> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/include/asm/kvm_host.h   |  5 +++++
>  arch/arm/include/asm/kvm_hyp.h    |  1 +
>  arch/arm/kvm/arm.c                | 35 ++++++++++++++++++++++++++++++++++-
>  arch/arm/kvm/hyp/switch.c         |  9 +++++++++
>  arch/arm64/include/asm/kvm_host.h |  6 +++++-
>  arch/arm64/kvm/hyp/switch.c       |  8 ++++++++
>  6 files changed, 62 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> index 2d19e02..035e744 100644
> --- a/arch/arm/include/asm/kvm_host.h
> +++ b/arch/arm/include/asm/kvm_host.h
> @@ -57,6 +57,8 @@ struct kvm_arch {
>  	/* VTTBR value associated with below pgd and vmid */
>  	u64    vttbr;
>  
> +	int __percpu *last_vcpu_ran;
> +
>  	/* Timer */
>  	struct arch_timer_kvm	timer;
>  
> @@ -174,6 +176,9 @@ struct kvm_vcpu_arch {
>  	/* vcpu power-off state */
>  	bool power_off;
>  
> +	/* TLBI required */
> +	bool requires_tlbi;
> +
>  	 /* Don't run the guest (internal implementation need) */
>  	bool pause;
>  
> diff --git a/arch/arm/include/asm/kvm_hyp.h b/arch/arm/include/asm/kvm_hyp.h
> index 343135e..5850890 100644
> --- a/arch/arm/include/asm/kvm_hyp.h
> +++ b/arch/arm/include/asm/kvm_hyp.h
> @@ -71,6 +71,7 @@
>  #define ICIALLUIS	__ACCESS_CP15(c7, 0, c1, 0)
>  #define ATS1CPR		__ACCESS_CP15(c7, 0, c8, 0)
>  #define TLBIALLIS	__ACCESS_CP15(c8, 0, c3, 0)
> +#define TLBIALL		__ACCESS_CP15(c8, 0, c7, 0)
>  #define TLBIALLNSNHIS	__ACCESS_CP15(c8, 4, c3, 4)
>  #define PRRR		__ACCESS_CP15(c10, 0, c2, 0)
>  #define NMRR		__ACCESS_CP15(c10, 0, c2, 1)
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index 03e9273..09942f0 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -114,11 +114,18 @@ void kvm_arch_check_processor_compat(void *rtn)
>   */
>  int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
>  {
> -	int ret = 0;
> +	int ret, cpu;
>  
>  	if (type)
>  		return -EINVAL;
>  
> +	kvm->arch.last_vcpu_ran = alloc_percpu(typeof(*kvm->arch.last_vcpu_ran));
> +	if (!kvm->arch.last_vcpu_ran)
> +		return -ENOMEM;
> +
> +	for_each_possible_cpu(cpu)
> +		*per_cpu_ptr(kvm->arch.last_vcpu_ran, cpu) = -1;
> +
>  	ret = kvm_alloc_stage2_pgd(kvm);
>  	if (ret)
>  		goto out_fail_alloc;
> @@ -141,6 +148,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
>  out_free_stage2_pgd:
>  	kvm_free_stage2_pgd(kvm);
>  out_fail_alloc:
> +	free_percpu(kvm->arch.last_vcpu_ran);
> +	kvm->arch.last_vcpu_ran = NULL;
>  	return ret;
>  }
>  
> @@ -168,6 +177,9 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
>  {
>  	int i;
>  
> +	free_percpu(kvm->arch.last_vcpu_ran);
> +	kvm->arch.last_vcpu_ran = NULL;
> +
>  	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
>  		if (kvm->vcpus[i]) {
>  			kvm_arch_vcpu_free(kvm->vcpus[i]);
> @@ -310,6 +322,27 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
>  	return 0;
>  }
>  
> +void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu)
> +{
> +	int *last_ran;
> +
> +	last_ran = per_cpu_ptr(vcpu->kvm->arch.last_vcpu_ran, cpu);
> +
> +	/*
> +	 * If we're very unlucky and get preempted before having ran
> +	 * this vcpu for real, we'll end-up in a situation where any
> +	 * vcpu that gets scheduled will perform an invalidation (this
> +	 * vcpu explicitely requires it, and all the others will have
> +	 * a different vcpu_id).
> +	 */
> +	if (*last_ran != vcpu->vcpu_id) {
> +		if (*last_ran != -1)
> +			vcpu->arch.requires_tlbi = true;
> +
> +		*last_ran = vcpu->vcpu_id;
> +	}
> +}
> +
>  void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
>  {
>  	vcpu->cpu = cpu;
> diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c
> index 92678b7..ab8ee3b 100644
> --- a/arch/arm/kvm/hyp/switch.c
> +++ b/arch/arm/kvm/hyp/switch.c
> @@ -75,6 +75,15 @@ static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)
>  {
>  	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
>  	write_sysreg(kvm->arch.vttbr, VTTBR);
> +	if (vcpu->arch.requires_tlbi) {
> +		/* Force vttbr to be written */
> +		isb();
> +		/* Local invalidate only for this VMID */
> +		write_sysreg(0, TLBIALL);
> +		dsb(nsh);
> +		vcpu->arch.requires_tlbi = false;
> +	}
> +
>  	write_sysreg(vcpu->arch.midr, VPIDR);
>  }
>  
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index bd94e67..5b42010 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -62,6 +62,8 @@ struct kvm_arch {
>  	/* VTTBR value associated with above pgd and vmid */
>  	u64    vttbr;
>  
> +	int __percpu *last_vcpu_ran;
> +
>  	/* The maximum number of vCPUs depends on the used GIC model */
>  	int max_vcpus;
>  
> @@ -252,6 +254,9 @@ struct kvm_vcpu_arch {
>  	/* vcpu power-off state */
>  	bool power_off;
>  
> +	/* TLBI required */
> +	bool requires_tlbi;
> +
>  	/* Don't run the guest (internal implementation need) */
>  	bool pause;
>  
> @@ -368,7 +373,6 @@ static inline void __cpu_reset_hyp_mode(unsigned long vector_ptr,
>  static inline void kvm_arch_hardware_unsetup(void) {}
>  static inline void kvm_arch_sync_events(struct kvm *kvm) {}
>  static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) {}
> -static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
>  static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
>  
>  void kvm_arm_init_debug(void);
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index 83037cd..8d9c3eb 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -131,6 +131,14 @@ static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)
>  {
>  	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
>  	write_sysreg(kvm->arch.vttbr, vttbr_el2);
> +	if (vcpu->arch.requires_tlbi) {
> +		/* Force vttbr_el2 to be written */
> +		isb();
> +		/* Local invalidate only for this VMID */
> +		asm volatile("tlbi vmalle1" : : );
> +		dsb(nsh);
> +		vcpu->arch.requires_tlbi = false;
> +	}
>  }
>  
>  static void __hyp_text __deactivate_vm(struct kvm_vcpu *vcpu)
> -- 
> 2.1.4
> 

^ permalink raw reply

* [RFC PATCH 5/5] of: overlay-mgr: add a detector for headers stored on a ds2431 eeprom over w1
From: Matthias Brugger @ 2016-10-27  9:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161026145756.21689-6-antoine.tenart@free-electrons.com>



On 10/26/2016 04:57 PM, Antoine Tenart wrote:
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
> ---

Please provide a commit message.

Thanks,
Matthias

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox