Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [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

* 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 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

* [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 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] 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] 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] arm64: defconfig: Enable DRM DU and V4L2 FCP + VSP modules
From: Magnus Damm @ 2016-10-27  7:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161027071523.GD7706@verge.net.au>

Hi Simon,

On Thu, Oct 27, 2016 at 4:15 PM, Simon Horman <horms@verge.net.au> wrote:
> On Thu, Oct 27, 2016 at 09:08:01AM +0200, Simon Horman wrote:
>> On Wed, Oct 26, 2016 at 02:24:22PM +0900, Magnus Damm wrote:
>> > From: Magnus Damm <damm+renesas@opensource.se>
>> >
>> > Extend the ARM64 defconfig to enable the DU DRM device as module
>> > together with required dependencies of V4L2 FCP and VSP modules.
>> >
>> > This enables VGA output on the r8a7795 Salvator-X board.
>> >
>> > Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
>>
>> Thanks, I have queued this up.
>
> Given discussion elsewhere on enabling DU I am holding off on this for a
> little; it is not queued up for now.

Sure, thanks for holding off the DT integration patches for r8a7796.
Please note that as of mainline v4.9-rc2 the r8a7795 Salvator-X board
has thanks to DU, FCP and VSP a working VGA port. So enabling those
devices in the defconfig from now on makes sense to me.

Cheers,

/ magnus

^ permalink raw reply

* [PATCH v2 4/4] arm64: arch timer: Add timer erratum property for Hip05-d02 and Hip06-d03
From: Ding Tianhong @ 2016-10-27  7:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477553651-13428-1-git-send-email-dingtianhong@huawei.com>

Enable workaround for hisilicon erratum 161601 on Hip05-d02 and Hip06-d03 board.

Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
---
 arch/arm64/boot/dts/hisilicon/hip05.dtsi | 1 +
 arch/arm64/boot/dts/hisilicon/hip06.dtsi | 1 +
 2 files changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/hisilicon/hip05.dtsi b/arch/arm64/boot/dts/hisilicon/hip05.dtsi
index bf322ed..f815d94 100644
--- a/arch/arm64/boot/dts/hisilicon/hip05.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hip05.dtsi
@@ -281,6 +281,7 @@
 			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
 			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
 			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+		hisilicon,erratum-161601;
 	};
 
 	pmu {
diff --git a/arch/arm64/boot/dts/hisilicon/hip06.dtsi b/arch/arm64/boot/dts/hisilicon/hip06.dtsi
index 5927bc4..d63990b 100644
--- a/arch/arm64/boot/dts/hisilicon/hip06.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hip06.dtsi
@@ -260,6 +260,7 @@
 			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
 			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
 			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+		hisilicon,erratum-161601;
 	};
 
 	pmu {
-- 
1.9.0

^ permalink raw reply related

* [PATCH v2 3/4] arm64: arch_timer: Work around Erratum Hisilicon-161601
From: Ding Tianhong @ 2016-10-27  7:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477553651-13428-1-git-send-email-dingtianhong@huawei.com>

Erratum Hisilicon-161601 says that the ARM generic timer counter "has the
potential to contain an erroneous value when the timer value changes".
Accesses to TVAL (both read and write) are also affected due to the implicit counter
read.  Accesses to CVAL are not affected.

The workaround is to reread the system count registers until the value of the second
read is larger than the first one by less than 32, the system counter can be guaranteed
not to return wrong value twice by back-to-back read and the error value is always larger
than the correct one by 32. Writes to TVAL are replaced with an equivalent write to CVAL.

The workaround is enabled if the hisilicon,erratum-161601 property is found in
the timer node in the device tree.  This can be overridden with the
clocksource.arm_arch_timer.hisilicon-161601 boot parameter, which allows KVM
users to enable the workaround until a mechanism is implemented to
automatically communicate this information.

Fix some description for fsl erratum a008585.

v2: Significant rework based on feedback, including seperate the fsl erratum a008585
    to another patch, update the erratum name and remove unwanted code.

Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
---
 Documentation/arm64/silicon-errata.txt |  1 +
 Documentation/kernel-parameters.txt    |  9 ++++
 arch/arm64/include/asm/arch_timer.h    | 28 ++++++++++-
 drivers/clocksource/Kconfig            | 14 +++++-
 drivers/clocksource/arm_arch_timer.c   | 88 ++++++++++++++++++++++++++--------
 5 files changed, 118 insertions(+), 22 deletions(-)

diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
index 405da11..70c5d5e 100644
--- a/Documentation/arm64/silicon-errata.txt
+++ b/Documentation/arm64/silicon-errata.txt
@@ -63,3 +63,4 @@ stable kernels.
 | Cavium         | ThunderX SMMUv2 | #27704          | N/A		       |
 |                |                 |                 |                         |
 | Freescale/NXP  | LS2080A/LS1043A | A-008585        | FSL_ERRATUM_A008585     |
+| Hisilicon      | Hip05/Hip06/Hip07 | #161601       | HISILICON_ERRATUM_161601|
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 6fa1d8a..735b4b6 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -707,6 +707,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			erratum.  If unspecified, the workaround is
 			enabled based on the device tree.
 
+	clocksource.arm_arch_timer.hisilicon-161601=
+			[ARM64]
+			Format: <bool>
+			Enable/disable the workaround of Hisilicon
+			erratum 161601.  This can be useful for KVM
+			guests, if the guest device tree doesn't show the
+			erratum.  If unspecified, the workaround is
+			enabled based on the device tree.
+
 	clearcpuid=BITNUM [X86]
 			Disable CPUID feature X for the kernel. See
 			arch/x86/include/asm/cpufeatures.h for the valid bit
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index 118719d8..49b3041 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -29,7 +29,7 @@
 
 #include <clocksource/arm_arch_timer.h>
 
-#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585)
+#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585) || IS_ENABLED(CONFIG_HISILICON_ERRATUM_161601)
 extern struct static_key_false arch_timer_read_ool_enabled;
 #define needs_timer_erratum_workaround() \
 	static_branch_unlikely(&arch_timer_read_ool_enabled)
@@ -65,11 +65,35 @@ extern struct arch_timer_erratum_workaround *erratum_workaround;
 	_new;						\
 })
 
+
+
+/*
+ * The number of retries is an arbitrary value well beyond the highest number
+ * of iterations the loop has been observed to take.
+ * Verify whether the value of the second read is larger than the first by
+ * less than 32 is the only way to confirm the value is correct, the system
+ * counter can be guaranteed not to return wrong value twice by back-to-back read
+ * and the error value is always larger than the correct one by 32.
+ */
+#define __hisi_161601_read_reg(reg) ({				\
+	u64 _old, _new;						\
+	int _retries = 200;					\
+								\
+	do {							\
+		_old = read_sysreg(reg);			\
+		_new = read_sysreg(reg);			\
+		_retries--;					\
+	} while (unlikely((_new - _old) >> 5) && _retries);	\
+								\
+	WARN_ON_ONCE(!_retries);				\
+	_new;							\
+})
+
 #define arch_timer_reg_read_stable(reg) 		\
 ({							\
 	u64 _val;					\
 	if (needs_timer_erratum_workaround())		\
-		_val = erratum_workaround->read_##reg();	\
+		_val = erratum_workaround->read_##reg();\
 	else						\
 		_val = read_sysreg(reg);		\
 	_val;						\
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 8a753fd..4aafb6a 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -312,8 +312,20 @@ config FSL_ERRATUM_A008585
 	help
 	  This option enables a workaround for Freescale/NXP Erratum
 	  A-008585 ("ARM generic timer may contain an erroneous
-	  value").  The workaround will only be active if the
+	  value").  The workaround will be active if the
 	  fsl,erratum-a008585 property is found in the timer node.
+	  This can be overridden with the clocksource.arm_arch_timer.fsl-a008585
+	  boot parameter.
+
+config HISILICON_ERRATUM_161601
+	bool "Workaround for Hisilicon Erratum 161601"
+	default y
+	depends on ARM_ARCH_TIMER && ARM64
+	help
+	  This option enables a workaround for Hisilicon Erratum
+	  161601. The workaround will be active if the hisilicon,erratum-161601
+	  property is found in the timer node. This can be overridden with
+	  the clocksource.arm_arch_timer.hisilicon-161601 boot parameter.
 
 config ARM_GLOBAL_TIMER
 	bool "Support for the ARM global timer" if COMPILE_TEST
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index e4f7fa1..89f1895 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -94,13 +94,14 @@ early_param("clocksource.arm_arch_timer.evtstrm", early_evtstrm_cfg);
  * Architected system timer support.
  */
 
-#ifdef CONFIG_FSL_ERRATUM_A008585
+#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585) || IS_ENABLED(CONFIG_HISILICON_ERRATUM_161601)
 struct arch_timer_erratum_workaround *erratum_workaround = NULL;
 
 DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled);
 EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled);
+#endif
 
-
+#ifdef CONFIG_FSL_ERRATUM_A008585
 static u32 fsl_a008585_read_cntp_tval_el0(void)
 {
 	return __fsl_a008585_read_reg(cntp_tval_el0);
@@ -139,6 +140,45 @@ static int __init early_fsl_a008585_cfg(char *buf)
 early_param("clocksource.arm_arch_timer.fsl-a008585", early_fsl_a008585_cfg);
 #endif /* CONFIG_FSL_ERRATUM_A008585 */
 
+#ifdef CONFIG_HISILICON_ERRATUM_161601
+static u32 hisi_161601_read_cntp_tval_el0(void)
+{
+	return __hisi_161601_read_reg(cntp_tval_el0);
+}
+
+static  u32 hisi_161601_read_cntv_tval_el0(void)
+{
+	return __hisi_161601_read_reg(cntv_tval_el0);
+}
+
+static u64 hisi_161601_read_cntvct_el0(void)
+{
+	return __hisi_161601_read_reg(cntvct_el0);
+}
+
+static struct arch_timer_erratum_workaround arch_timer_hisi_161601 = {
+	.read_cntp_tval_el0 = hisi_161601_read_cntp_tval_el0,
+	.read_cntv_tval_el0 = hisi_161601_read_cntv_tval_el0,
+	.read_cntvct_el0 = hisi_161601_read_cntvct_el0,
+};
+
+static int __init early_hisi_161601_cfg(char *buf)
+{
+	int ret;
+	bool val;
+
+	ret = strtobool(buf, &val);
+	if (ret)
+		return ret;
+
+	if (val)
+		erratum_workaround = &arch_timer_hisi_161601;
+
+	return 0;
+}
+early_param("clocksource.arm_arch_timer.hisilicon-161601", early_hisi_161601_cfg);
+#endif /* CONFIG_HISILICON_ERRATUM_161601 */
+
 static __always_inline
 void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val,
 			  struct clock_event_device *clk)
@@ -288,8 +328,8 @@ static __always_inline void set_next_event(const int access, unsigned long evt,
 	arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
 }
 
-#ifdef CONFIG_FSL_ERRATUM_A008585
-static __always_inline void fsl_a008585_set_next_event(const int access,
+#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585) || IS_ENABLED(CONFIG_HISILICON_ERRATUM_161601)
+static __always_inline void erratum_set_next_event(const int access,
 		unsigned long evt, struct clock_event_device *clk)
 {
 	unsigned long ctrl;
@@ -307,20 +347,20 @@ static __always_inline void fsl_a008585_set_next_event(const int access,
 	arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
 }
 
-static int fsl_a008585_set_next_event_virt(unsigned long evt,
+static int erratum_set_next_event_virt(unsigned long evt,
 					   struct clock_event_device *clk)
 {
-	fsl_a008585_set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk);
+	erratum_set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk);
 	return 0;
 }
 
-static int fsl_a008585_set_next_event_phys(unsigned long evt,
+static int erratum_set_next_event_phys(unsigned long evt,
 					   struct clock_event_device *clk)
 {
-	fsl_a008585_set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk);
+	erratum_set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk);
 	return 0;
 }
-#endif /* CONFIG_FSL_ERRATUM_A008585 */
+#endif
 
 static int arch_timer_set_next_event_virt(unsigned long evt,
 					  struct clock_event_device *clk)
@@ -350,16 +390,16 @@ static int arch_timer_set_next_event_phys_mem(unsigned long evt,
 	return 0;
 }
 
-static void fsl_a008585_set_sne(struct clock_event_device *clk)
+static void erratum_set_sne(struct clock_event_device *clk)
 {
-#ifdef CONFIG_FSL_ERRATUM_A008585
+#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585) || IS_ENABLED(CONFIG_HISILICON_ERRATUM_161601)
 	if (!static_branch_unlikely(&arch_timer_read_ool_enabled))
 		return;
 
 	if (arch_timer_uses_ppi == VIRT_PPI)
-		clk->set_next_event = fsl_a008585_set_next_event_virt;
+		clk->set_next_event = erratum_set_next_event_virt;
 	else
-		clk->set_next_event = fsl_a008585_set_next_event_phys;
+		clk->set_next_event = erratum_set_next_event_phys;
 #endif
 }
 
@@ -392,7 +432,7 @@ static void __arch_timer_setup(unsigned type,
 			BUG();
 		}
 
-		fsl_a008585_set_sne(clk);
+		erratum_set_sne(clk);
 	} else {
 		clk->features |= CLOCK_EVT_FEAT_DYNIRQ;
 		clk->name = "arch_mem_timer";
@@ -612,7 +652,7 @@ static void __init arch_counter_register(unsigned type)
 
 		clocksource_counter.archdata.vdso_direct = true;
 
-#ifdef CONFIG_FSL_ERRATUM_A008585
+#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585) || IS_ENABLED(CONFIG_HISILICON_ERRATUM_161601)
 		/*
 		 * Don't use the vdso fastpath if errata require using
 		 * the out-of-line counter accessor.
@@ -899,12 +939,22 @@ static int __init arch_timer_of_init(struct device_node *np)
 	arch_timer_c3stop = !of_property_read_bool(np, "always-on");
 
 #ifdef CONFIG_FSL_ERRATUM_A008585
-	if (!erratum_workaround && of_property_read_bool(np, "fsl,erratum-a008585"))
+	if (!erratum_workaround && of_property_read_bool(np, "fsl,erratum-a008585")) {
 		erratum_workaround = &arch_timer_fsl_a008585;
+		if (erratum_workaround) {
+			static_branch_enable(&arch_timer_read_ool_enabled);
+			pr_info("Enabling workaround for FSL erratum A-008585\n");
+		}
+	}
+#endif
 
-	if (erratum_workaround) {
-		static_branch_enable(&arch_timer_read_ool_enabled);
-		pr_info("Enabling workaround for FSL erratum A-008585\n");
+#ifdef CONFIG_HISILICON_ERRATUM_161601
+	if (!erratum_workaround && of_property_read_bool(np, "hisilicon,erratum-161601")) {
+		erratum_workaround = &arch_timer_hisi_161601;
+		if (erratum_workaround) {
+			static_branch_enable(&arch_timer_read_ool_enabled);
+			pr_info("Enabling workaround for HISILICON erratum 161601\n");
+		}
 	}
 #endif
 
-- 
1.9.0

^ permalink raw reply related

* [PATCH v2 2/4] arm64: arch_timer: Introduce a generic erratum handing mechanism for fsl-a008585
From: Ding Tianhong @ 2016-10-27  7:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477553651-13428-1-git-send-email-dingtianhong@huawei.com>

The workaround for hisilicon,161601 will check the return value of the system counter
by different way, in order to distinguish with the fsl-a008585 workaround, introduce
a new generic erratum handing mechanism for fsl-a008585 and rename some functions. 

v2: Introducing a new generic erratum handling mechanism for fsl erratum a008585.

Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
---
 arch/arm64/include/asm/arch_timer.h  | 20 +++++++++-----
 drivers/clocksource/arm_arch_timer.c | 51 +++++++++++++++++++++---------------
 2 files changed, 43 insertions(+), 28 deletions(-)

diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index eaa5bbe..118719d8 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -31,15 +31,21 @@
 
 #if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585)
 extern struct static_key_false arch_timer_read_ool_enabled;
-#define needs_fsl_a008585_workaround() \
+#define needs_timer_erratum_workaround() \
 	static_branch_unlikely(&arch_timer_read_ool_enabled)
 #else
-#define needs_fsl_a008585_workaround()  false
+#define needs_timer_erratum_workaround()  false
 #endif
 
-u32 __fsl_a008585_read_cntp_tval_el0(void);
-u32 __fsl_a008585_read_cntv_tval_el0(void);
-u64 __fsl_a008585_read_cntvct_el0(void);
+
+struct arch_timer_erratum_workaround {
+	int erratum;
+	u32 (*read_cntp_tval_el0)(void);
+	u32 (*read_cntv_tval_el0)(void);
+	u64 (*read_cntvct_el0)(void);
+};
+
+extern struct arch_timer_erratum_workaround *erratum_workaround;
 
 /*
  * The number of retries is an arbitrary value well beyond the highest number
@@ -62,8 +68,8 @@ u64 __fsl_a008585_read_cntvct_el0(void);
 #define arch_timer_reg_read_stable(reg) 		\
 ({							\
 	u64 _val;					\
-	if (needs_fsl_a008585_workaround())		\
-		_val = __fsl_a008585_read_##reg();	\
+	if (needs_timer_erratum_workaround())		\
+		_val = erratum_workaround->read_##reg();	\
 	else						\
 		_val = read_sysreg(reg);		\
 	_val;						\
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 73c487d..e4f7fa1 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -95,10 +95,32 @@ early_param("clocksource.arm_arch_timer.evtstrm", early_evtstrm_cfg);
  */
 
 #ifdef CONFIG_FSL_ERRATUM_A008585
+struct arch_timer_erratum_workaround *erratum_workaround = NULL;
+
 DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled);
 EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled);
 
-static int fsl_a008585_enable = -1;
+
+static u32 fsl_a008585_read_cntp_tval_el0(void)
+{
+	return __fsl_a008585_read_reg(cntp_tval_el0);
+}
+
+static  u32 fsl_a008585_read_cntv_tval_el0(void)
+{
+	return __fsl_a008585_read_reg(cntv_tval_el0);
+}
+
+static u64 fsl_a008585_read_cntvct_el0(void)
+{
+	return __fsl_a008585_read_reg(cntvct_el0);
+}
+
+static struct arch_timer_erratum_workaround arch_timer_fsl_a008585 = {
+	.read_cntp_tval_el0 = fsl_a008585_read_cntp_tval_el0,
+	.read_cntv_tval_el0 = fsl_a008585_read_cntv_tval_el0,
+	.read_cntvct_el0 = fsl_a008585_read_cntvct_el0,
+};
 
 static int __init early_fsl_a008585_cfg(char *buf)
 {
@@ -109,26 +131,12 @@ static int __init early_fsl_a008585_cfg(char *buf)
 	if (ret)
 		return ret;
 
-	fsl_a008585_enable = val;
+	if (val)
+		erratum_workaround = &arch_timer_fsl_a008585;
+
 	return 0;
 }
 early_param("clocksource.arm_arch_timer.fsl-a008585", early_fsl_a008585_cfg);
-
-u32 __fsl_a008585_read_cntp_tval_el0(void)
-{
-	return __fsl_a008585_read_reg(cntp_tval_el0);
-}
-
-u32 __fsl_a008585_read_cntv_tval_el0(void)
-{
-	return __fsl_a008585_read_reg(cntv_tval_el0);
-}
-
-u64 __fsl_a008585_read_cntvct_el0(void)
-{
-	return __fsl_a008585_read_reg(cntvct_el0);
-}
-EXPORT_SYMBOL(__fsl_a008585_read_cntvct_el0);
 #endif /* CONFIG_FSL_ERRATUM_A008585 */
 
 static __always_inline
@@ -891,9 +899,10 @@ static int __init arch_timer_of_init(struct device_node *np)
 	arch_timer_c3stop = !of_property_read_bool(np, "always-on");
 
 #ifdef CONFIG_FSL_ERRATUM_A008585
-	if (fsl_a008585_enable < 0)
-		fsl_a008585_enable = of_property_read_bool(np, "fsl,erratum-a008585");
-	if (fsl_a008585_enable) {
+	if (!erratum_workaround && of_property_read_bool(np, "fsl,erratum-a008585"))
+		erratum_workaround = &arch_timer_fsl_a008585;
+
+	if (erratum_workaround) {
 		static_branch_enable(&arch_timer_read_ool_enabled);
 		pr_info("Enabling workaround for FSL erratum A-008585\n");
 	}
-- 
1.9.0

^ permalink raw reply related

* [PATCH v2 1/4] arm64: arch_timer: Add device tree binding for hisilicon-161601 erratum
From: Ding Tianhong @ 2016-10-27  7:34 UTC (permalink / raw)
  To: linux-arm-kernel

This erratum describes a bug in logic outside the core, so MIDR can't be
used to identify its presence, and reading an SoC-specific revision
register from common arch timer code would be awkward.  So, describe it
in the device tree.

v2: Use the new erratum name and update the description.

Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
---
 Documentation/devicetree/bindings/arm/arch_timer.txt | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
index ef5fbe9..c27b2c4 100644
--- a/Documentation/devicetree/bindings/arm/arch_timer.txt
+++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
@@ -31,6 +31,14 @@ to deliver its interrupts via SPIs.
   This also affects writes to the tval register, due to the implicit
   counter read.
 
+- hisilicon,erratum-161601 : A boolean property. Indicates the presence of
+  erratum 161601, which says that reading the counter is unreliable unless
+  reading twice on the register and the value of the second read is larger
+  than the first by less than 32. If the verification is unsuccessful, then
+  discard the value of this read and repeat this procedure until the verification
+  is successful.  This also affects writes to the tval register, due to the
+  implicit counter read.
+
 ** Optional properties:
 
 - arm,cpu-registers-not-fw-configured : Firmware does not initialize
-- 
1.9.0

^ permalink raw reply related

* [PATCH] ARM: shmobile: select errata 798181 for SoCs with CA15 cores
From: Geert Uytterhoeven @ 2016-10-27  7:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CANqRtoSsKTvMjATz89nEY06Fp-J20VqjDzW0JD1NDLqEJQPwsQ@mail.gmail.com>

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 ;-)

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [PATCH] Revert "gpio/mvebu: convert to use irq_domain_add_simple()"
From: Gregory CLEMENT @ 2016-10-27  7:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdatYim3=tKeO-E1GazB7RV9XPdE-EBQs+FW+DrryATzRA@mail.gmail.com>

Hi Linus,
 
 On lun., oct. 24 2016, Linus Walleij <linus.walleij@linaro.org> wrote:

> On Wed, Oct 19, 2016 at 11:03 PM, Jason Gunthorpe
> <jgunthorpe@obsidianresearch.com> wrote:
>
>> From 7566f05ac445b652ba7607cc1899fed10fea1c76 Mon Sep 17 00:00:00 2001
>> From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
>> Date: Wed, 19 Oct 2016 14:57:45 -0600
>> Subject: [PATCH] gpio/mvebu: Use irq_domain_add_linear
>>
>> This fixes the irq allocation in this driver to not print:
>>  irq: Cannot allocate irq_descs @ IRQ34, assuming pre-allocated
>>  irq: Cannot allocate irq_descs @ IRQ66, assuming pre-allocated
>>
>> Which happens because the driver already called irq_alloc_descs()
>> and so the change to use irq_domain_add_simple resulted in calling
>> irq_alloc_descs() twice.
>>
>> Modernize the irq allocation in this driver to use the
>> irq_domain_add_linear flow directly and eliminate the use of
>> irq_domain_add_simple/legacy
>>
>> Fixes: ce931f571b6d ("gpio/mvebu: convert to use irq_domain_add_simple()")
>> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
>
> So can I just apply this?
> Gregory?

For me it's OK.

Gregory

>
> Yours,
> Linus Walleij

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [PATCH] ARM: shmobile: select errata 798181 for SoCs with CA15 cores
From: Magnus Damm @ 2016-10-27  7:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477551606-6903-1-git-send-email-horms+renesas@verge.net.au>

Hi Simon,

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.

So either the commit message or the list of the SoCs need to be updated.

Thanks,

/ magnus

^ permalink raw reply

* [PATCH 1/2] mm/memblock: prepare a capability to support memblock near alloc
From: Michal Hocko @ 2016-10-27  7:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <58116954.8080908@huawei.com>

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
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
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
you start adding a new API.

Thanks!

-- 
Michal Hocko
SUSE Labs

^ permalink raw reply

* [PATCH] arm64: defconfig: Enable DRM DU and V4L2 FCP + VSP modules
From: Simon Horman @ 2016-10-27  7:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161027070801.GB7706@verge.net.au>

On Thu, Oct 27, 2016 at 09:08:01AM +0200, Simon Horman wrote:
> On Wed, Oct 26, 2016 at 02:24:22PM +0900, Magnus Damm wrote:
> > From: Magnus Damm <damm+renesas@opensource.se>
> > 
> > Extend the ARM64 defconfig to enable the DU DRM device as module
> > together with required dependencies of V4L2 FCP and VSP modules.
> > 
> > This enables VGA output on the r8a7795 Salvator-X board.
> > 
> > Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
> 
> Thanks, I have queued this up.

Given discussion elsewhere on enabling DU I am holding off on this for a
little; it is not queued up for now.

^ permalink raw reply

* [PATCH] arm64: defconfig: Enable DRM DU and V4L2 FCP + VSP modules
From: Simon Horman @ 2016-10-27  7:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161026052422.17283.57864.sendpatchset@little-apple>

On Wed, Oct 26, 2016 at 02:24:22PM +0900, Magnus Damm wrote:
> From: Magnus Damm <damm+renesas@opensource.se>
> 
> Extend the ARM64 defconfig to enable the DU DRM device as module
> together with required dependencies of V4L2 FCP and VSP modules.
> 
> This enables VGA output on the r8a7795 Salvator-X board.
> 
> Signed-off-by: Magnus Damm <damm+renesas@opensource.se>

Thanks, I have queued this up.

^ permalink raw reply

* [PATCH] ARM: shmobile: select errata 798181 for SoCs with CA15 cores
From: Geert Uytterhoeven @ 2016-10-27  7:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477551606-6903-1-git-send-email-horms+renesas@verge.net.au>

On Thu, Oct 27, 2016 at 9:00 AM, Simon Horman
<horms+renesas@verge.net.au> wrote:
> Select ARM errata 798181 on SoCs cores affected CA15 cores.

... cores with ...

> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [PATCHv2] ARM: dts: socfpga: Enable QSPI on the Cyclone5 sockit
From: Steffen Trumtrar @ 2016-10-27  7:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1477505112-26079-1-git-send-email-dinguyen@opensource.altera.com>

On Wed, Oct 26, 2016 at 01:05:12PM -0500, dinguyen at opensource.altera.com wrote:
> From: Dinh Nguyen <dinguyen@opensource.altera.com>
> 
> Enable the QSPI node and add the flash chip.
> 
> Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
> ---
> v2: Remove partition entries for the SoCKIT
> ---
>  arch/arm/boot/dts/socfpga_cyclone5_sockit.dts |   21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
> index 02e22f5..2ce6736 100644
> --- a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
> +++ b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
> @@ -175,6 +175,27 @@
>  	status = "okay";
>  };
>  
> +&qspi {
> +	status = "okay";
> +
> +	flash: flash at 0 {
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		compatible = "n25q256a";

Did you test if this works correctly? According to my datasheet (Rev. C)
the HPS qspi is a n25q00. The n25q256a is the other one.

Regards,
Steffen


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* [PATCH v4 0/7] Add R8A7743/SK-RZG1M board support
From: Simon Horman @ 2016-10-27  7:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMuHMdWQegsEf_C=UGXpQiEAX0YQqy335teuvCZxBY6C=7QozA@mail.gmail.com>

On Wed, Oct 26, 2016 at 03:27:14PM +0200, Geert Uytterhoeven wrote:
> On Wed, Oct 26, 2016 at 3:23 PM, Sergei Shtylyov
> <sergei.shtylyov@cogentembedded.com> wrote:
> > On 10/26/2016 03:08 PM, Geert Uytterhoeven wrote:
> >>>    Here's the set of 8 patches against Simon Horman's 'renesas.git'
> >>> repo's
> >>> 'renesas-devel-20161021-v4.9-rc1' tag. I'm adding the device tree support
> >>> for
> >>> the R8A7743-based SK-RZG1M board. The SoC is close to R8A7791 and the
> >>> board
> >>> seems identical to the R8A7791/Porter board. The device tree patches
> >>> depend on
> >>> the R8A7743 CPG/MSSR driver series just posted in order to compile and
> >>> work.
> >>
> >>
> >> They depend only on "[PATCH v3 1/2] ARM: shmobile: r8a7743: add CPG clock
> >> index macros" of that series, right?
> >>
> >> "[PATCH v3 2/2] clk: renesas: cpg-mssr: add R8A7743 support" is not
> >> needed,
> >
> >    How would "clocks" props _work_ without this patch?
> 
> Sorry, I was focusing too much on "compile"...
> 
> Got my coke, switching brain to overdrive mode...

As we are talking about adding support for a new SoC I would be happy
to queue up code in my tree that compiles under the assumption that
in v4.10 the bits to make it run will appear in other branches.

^ permalink raw reply

* [PATCH] ARM: shmobile: select errata 798181 for SoCs with CA15 cores
From: Simon Horman @ 2016-10-27  7:00 UTC (permalink / raw)
  To: linux-arm-kernel

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
 
 config ARCH_R8A7791
 	bool "R-Car M2-W (R8A77910)"
 	select ARCH_RCAR_GEN2
+	select ARM_ERRATA_798181 if SMP
 	select I2C
 
 config ARCH_R8A7792
 	bool "R-Car V2H (R8A77920)"
 	select ARCH_RCAR_GEN2
+	select ARM_ERRATA_798181 if SMP
 
 config ARCH_R8A7793
 	bool "R-Car M2-N (R8A7793)"
 	select ARCH_RCAR_GEN2
+	select ARM_ERRATA_798181 if SMP
 	select I2C
 
 config ARCH_R8A7794
-- 
2.7.0.rc3.207.g0ac5344

^ permalink raw reply related

* [PATCH v2 1/8] drm/bridge: rgb-to-vga: Support an enable GPIO
From: Chen-Yu Tsai @ 2016-10-27  6:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87ca071d-c396-25b3-aff4-c838c9003f94@codeaurora.org>

On Thu, Oct 27, 2016 at 2:40 PM, Archit Taneja <architt@codeaurora.org> wrote:
>
>
> On 10/25/2016 02:29 PM, Chen-Yu Tsai wrote:
>>
>> On Tue, Oct 25, 2016 at 4:09 PM, Archit Taneja <architt@codeaurora.org>
>> wrote:
>>>
>>> Hi,
>>>
>>> On 10/20/2016 09:13 AM, Chen-Yu Tsai wrote:
>>>>
>>>>
>>>> Some rgb-to-vga bridges have an enable GPIO, either directly tied to
>>>> an enable pin on the bridge IC, or indirectly controlling a power
>>>> switch.
>>>>
>>>> Add support for it.
>>>
>>>
>>>
>>> Does the bridge on your platform have an active/passive DAC, or is it a
>>> smarter encoder chip that is capable of doing more? If so, it might be
>>> good to have a separate DT compatible string to it, like what's done
>>> in the patch titled:
>>>
>>> drm: bridge: vga-dac: Add adi,adv7123 compatible string
>>>
>>> so that we can switch to a different driver later if needed.
>>
>>
>> The chip is GM7123. It is not configurable. It just takes the LCD RGB/SYNC
>> signals and converts them to analog. The only things you can change are
>> putting it into sleep mode and tweaking the output drive strength by
>
>
> Is sleep mode the thing that's controlled by this gpio?

Not on this particular board. The gpio controls the external LDO that
supplies 3.3V to VDD.

>
>> changing the external reference resistor. The latter would be a hardware
>> design decision. I would say this qualifies as "dumb".
>
>
> Yeah, I agree. I'd want feedback from Laurent too, since he had comments
> on the usage of the original dumb-vga-dac driver.
>
>>
>> I revisited the board schematics, and the enable GPIO actually toggles
>> an external LDO regulator. So this might be better modeled as a regulator
>> supply?
>
>
> If you model it as a regulator, how would you toggle the GPIO on your
> platform?
>
> Looking at the chip pin out, there is a 3.3V VDD supply needed for the
> chip, so it would be good to have an optional 'power' regulator supply
> anyway.

Yes, that it what I plan to do. I'll drop the enable-gpios property,
and add a power-supply property for the regulator.

Regards
ChenYu

>
> Archit
>
>
>>
>>
>> Thanks
>> ChenYu
>>
>>>
>>> Thanks,
>>> Archit
>>>
>>>
>>>>
>>>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>>>> ---
>>>>  .../bindings/display/bridge/dumb-vga-dac.txt       |  2 ++
>>>>  drivers/gpu/drm/bridge/dumb-vga-dac.c              | 28
>>>> ++++++++++++++++++++++
>>>>  2 files changed, 30 insertions(+)
>>>>
>>>> diff --git
>>>> a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>>> b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>>> index 003bc246a270..d3484822bf77 100644
>>>> --- a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>>> +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>>> @@ -16,6 +16,8 @@ graph bindings specified in
>>>> Documentation/devicetree/bindings/graph.txt.
>>>>  - Video port 0 for RGB input
>>>>  - Video port 1 for VGA output
>>>>
>>>> +Optional properties:
>>>> +- enable-gpios: GPIO pin to enable or disable the bridge
>>>>
>>>>  Example
>>>>  -------
>>>> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>>> b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>>> index afec232185a7..b487e5e9b56d 100644
>>>> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>>> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>>> @@ -10,6 +10,7 @@
>>>>   * the License, or (at your option) any later version.
>>>>   */
>>>>
>>>> +#include <linux/gpio/consumer.h>
>>>>  #include <linux/module.h>
>>>>  #include <linux/of_graph.h>
>>>>
>>>> @@ -23,6 +24,7 @@ struct dumb_vga {
>>>>         struct drm_connector    connector;
>>>>
>>>>         struct i2c_adapter      *ddc;
>>>> +       struct gpio_desc        *enable_gpio;
>>>>  };
>>>>
>>>>  static inline struct dumb_vga *
>>>> @@ -124,8 +126,26 @@ static int dumb_vga_attach(struct drm_bridge
>>>> *bridge)
>>>>         return 0;
>>>>  }
>>>>
>>>> +static void dumb_vga_enable(struct drm_bridge *bridge)
>>>> +{
>>>> +       struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
>>>> +
>>>> +       if (vga->enable_gpio)
>>>> +               gpiod_set_value_cansleep(vga->enable_gpio, 1);
>>>> +}
>>>> +
>>>> +static void dumb_vga_disable(struct drm_bridge *bridge)
>>>> +{
>>>> +       struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
>>>> +
>>>> +       if (vga->enable_gpio)
>>>> +               gpiod_set_value_cansleep(vga->enable_gpio, 0);
>>>> +}
>>>> +
>>>>  static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
>>>>         .attach         = dumb_vga_attach,
>>>> +       .enable         = dumb_vga_enable,
>>>> +       .disable        = dumb_vga_disable,
>>>>  };
>>>>
>>>>  static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
>>>> @@ -169,6 +189,14 @@ static int dumb_vga_probe(struct platform_device
>>>> *pdev)
>>>>                 return -ENOMEM;
>>>>         platform_set_drvdata(pdev, vga);
>>>>
>>>> +       vga->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
>>>> +                                                  GPIOD_OUT_LOW);
>>>> +       if (IS_ERR(vga->enable_gpio)) {
>>>> +               ret = PTR_ERR(vga->enable_gpio);
>>>> +               dev_err(&pdev->dev, "failed to request GPIO: %d\n",
>>>> ret);
>>>> +               return ret;
>>>> +       }
>>>> +
>>>>         vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
>>>>         if (IS_ERR(vga->ddc)) {
>>>>                 if (PTR_ERR(vga->ddc) == -ENODEV) {
>>>>
>>>
>>> --
>>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
>>> a Linux Foundation Collaborative Project
>
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH v2 1/8] drm/bridge: rgb-to-vga: Support an enable GPIO
From: Archit Taneja @ 2016-10-27  6:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAGb2v64=c5PFx+qJkfPeKYFQYLYoYfWgjg49O4Es5qVjuyf5gg@mail.gmail.com>



On 10/25/2016 02:29 PM, Chen-Yu Tsai wrote:
> On Tue, Oct 25, 2016 at 4:09 PM, Archit Taneja <architt@codeaurora.org> wrote:
>> Hi,
>>
>> On 10/20/2016 09:13 AM, Chen-Yu Tsai wrote:
>>>
>>> Some rgb-to-vga bridges have an enable GPIO, either directly tied to
>>> an enable pin on the bridge IC, or indirectly controlling a power
>>> switch.
>>>
>>> Add support for it.
>>
>>
>> Does the bridge on your platform have an active/passive DAC, or is it a
>> smarter encoder chip that is capable of doing more? If so, it might be
>> good to have a separate DT compatible string to it, like what's done
>> in the patch titled:
>>
>> drm: bridge: vga-dac: Add adi,adv7123 compatible string
>>
>> so that we can switch to a different driver later if needed.
>
> The chip is GM7123. It is not configurable. It just takes the LCD RGB/SYNC
> signals and converts them to analog. The only things you can change are
> putting it into sleep mode and tweaking the output drive strength by

Is sleep mode the thing that's controlled by this gpio?


> changing the external reference resistor. The latter would be a hardware
> design decision. I would say this qualifies as "dumb".

Yeah, I agree. I'd want feedback from Laurent too, since he had comments
on the usage of the original dumb-vga-dac driver.

>
> I revisited the board schematics, and the enable GPIO actually toggles
> an external LDO regulator. So this might be better modeled as a regulator
> supply?

If you model it as a regulator, how would you toggle the GPIO on your
platform?

Looking at the chip pin out, there is a 3.3V VDD supply needed for the
chip, so it would be good to have an optional 'power' regulator supply
anyway.

Archit

>
>
> Thanks
> ChenYu
>
>>
>> Thanks,
>> Archit
>>
>>
>>>
>>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>>> ---
>>>  .../bindings/display/bridge/dumb-vga-dac.txt       |  2 ++
>>>  drivers/gpu/drm/bridge/dumb-vga-dac.c              | 28
>>> ++++++++++++++++++++++
>>>  2 files changed, 30 insertions(+)
>>>
>>> diff --git
>>> a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>> b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>> index 003bc246a270..d3484822bf77 100644
>>> --- a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>> +++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
>>> @@ -16,6 +16,8 @@ graph bindings specified in
>>> Documentation/devicetree/bindings/graph.txt.
>>>  - Video port 0 for RGB input
>>>  - Video port 1 for VGA output
>>>
>>> +Optional properties:
>>> +- enable-gpios: GPIO pin to enable or disable the bridge
>>>
>>>  Example
>>>  -------
>>> diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>> b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>> index afec232185a7..b487e5e9b56d 100644
>>> --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>> +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
>>> @@ -10,6 +10,7 @@
>>>   * the License, or (at your option) any later version.
>>>   */
>>>
>>> +#include <linux/gpio/consumer.h>
>>>  #include <linux/module.h>
>>>  #include <linux/of_graph.h>
>>>
>>> @@ -23,6 +24,7 @@ struct dumb_vga {
>>>         struct drm_connector    connector;
>>>
>>>         struct i2c_adapter      *ddc;
>>> +       struct gpio_desc        *enable_gpio;
>>>  };
>>>
>>>  static inline struct dumb_vga *
>>> @@ -124,8 +126,26 @@ static int dumb_vga_attach(struct drm_bridge *bridge)
>>>         return 0;
>>>  }
>>>
>>> +static void dumb_vga_enable(struct drm_bridge *bridge)
>>> +{
>>> +       struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
>>> +
>>> +       if (vga->enable_gpio)
>>> +               gpiod_set_value_cansleep(vga->enable_gpio, 1);
>>> +}
>>> +
>>> +static void dumb_vga_disable(struct drm_bridge *bridge)
>>> +{
>>> +       struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
>>> +
>>> +       if (vga->enable_gpio)
>>> +               gpiod_set_value_cansleep(vga->enable_gpio, 0);
>>> +}
>>> +
>>>  static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
>>>         .attach         = dumb_vga_attach,
>>> +       .enable         = dumb_vga_enable,
>>> +       .disable        = dumb_vga_disable,
>>>  };
>>>
>>>  static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
>>> @@ -169,6 +189,14 @@ static int dumb_vga_probe(struct platform_device
>>> *pdev)
>>>                 return -ENOMEM;
>>>         platform_set_drvdata(pdev, vga);
>>>
>>> +       vga->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
>>> +                                                  GPIOD_OUT_LOW);
>>> +       if (IS_ERR(vga->enable_gpio)) {
>>> +               ret = PTR_ERR(vga->enable_gpio);
>>> +               dev_err(&pdev->dev, "failed to request GPIO: %d\n", ret);
>>> +               return ret;
>>> +       }
>>> +
>>>         vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
>>>         if (IS_ERR(vga->ddc)) {
>>>                 if (PTR_ERR(vga->ddc) == -ENODEV) {
>>>
>>
>> --
>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
>> a Linux Foundation Collaborative Project

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH V3 8/8] arm64: dma-mapping: Remove the notifier trick to handle early setting of dma_ops
From: Sricharan @ 2016-10-27  5:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <e4643826-3aa8-1e34-79a8-9e1fcf0fcb69@arm.com>

Hi Robin,

>On 04/10/16 18:03, Sricharan R wrote:
>> With arch_setup_dma_ops now being called late during device's probe after the
>> device's iommu is probed, the notifier trick required to handle the early
>> setup of dma_ops before the iommu group gets created is not required.
>> So removing the notifier's here.
>
>Hooray!
>
>> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
>> ---
>>  arch/arm64/mm/dma-mapping.c | 100 ++------------------------------------------
>>  1 file changed, 3 insertions(+), 97 deletions(-)
>>
>> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
>> index faf4b92..eb593af 100644
>> --- a/arch/arm64/mm/dma-mapping.c
>> +++ b/arch/arm64/mm/dma-mapping.c
>> @@ -799,24 +799,6 @@ static struct dma_map_ops iommu_dma_ops = {
>>  	.mapping_error = iommu_dma_mapping_error,
>>  };
>>
>> -/*
>> - * TODO: Right now __iommu_setup_dma_ops() gets called too early to do
>> - * everything it needs to - the device is only partially created and the
>> - * IOMMU driver hasn't seen it yet, so it can't have a group. Thus we
>> - * need this delayed attachment dance. Once IOMMU probe ordering is sorted
>> - * to move the arch_setup_dma_ops() call later, all the notifier bits below
>> - * become unnecessary, and will go away.
>> - */
>> -struct iommu_dma_notifier_data {
>> -	struct list_head list;
>> -	struct device *dev;
>> -	const struct iommu_ops *ops;
>> -	u64 dma_base;
>> -	u64 size;
>> -};
>> -static LIST_HEAD(iommu_dma_masters);
>> -static DEFINE_MUTEX(iommu_dma_notifier_lock);
>> -
>>  static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops,
>>  			   u64 dma_base, u64 size)
>
>This should go as well...

 ok.
>
>>  {
>> @@ -837,79 +819,9 @@ static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops,
>>  	return true;
>>  }
>>
>> -static void queue_iommu_attach(struct device *dev, const struct iommu_ops *ops,
>> -			      u64 dma_base, u64 size)
>> -{
>> -	struct iommu_dma_notifier_data *iommudata;
>> -
>> -	iommudata = kzalloc(sizeof(*iommudata), GFP_KERNEL);
>> -	if (!iommudata)
>> -		return;
>> -
>> -	iommudata->dev = dev;
>> -	iommudata->ops = ops;
>> -	iommudata->dma_base = dma_base;
>> -	iommudata->size = size;
>> -
>> -	mutex_lock(&iommu_dma_notifier_lock);
>> -	list_add(&iommudata->list, &iommu_dma_masters);
>> -	mutex_unlock(&iommu_dma_notifier_lock);
>> -}
>> -
>> -static int __iommu_attach_notifier(struct notifier_block *nb,
>> -				   unsigned long action, void *data)
>> -{
>> -	struct iommu_dma_notifier_data *master, *tmp;
>> -
>> -	if (action != BUS_NOTIFY_BIND_DRIVER)
>> -		return 0;
>> -
>> -	mutex_lock(&iommu_dma_notifier_lock);
>> -	list_for_each_entry_safe(master, tmp, &iommu_dma_masters, list) {
>> -		if (data == master->dev && do_iommu_attach(master->dev,
>> -				master->ops, master->dma_base, master->size)) {
>> -			list_del(&master->list);
>> -			kfree(master);
>> -			break;
>> -		}
>> -	}
>> -	mutex_unlock(&iommu_dma_notifier_lock);
>> -	return 0;
>> -}
>> -
>> -static int __init register_iommu_dma_ops_notifier(struct bus_type *bus)
>> -{
>> -	struct notifier_block *nb = kzalloc(sizeof(*nb), GFP_KERNEL);
>> -	int ret;
>> -
>> -	if (!nb)
>> -		return -ENOMEM;
>> -
>> -	nb->notifier_call = __iommu_attach_notifier;
>> -
>> -	ret = bus_register_notifier(bus, nb);
>> -	if (ret) {
>> -		pr_warn("Failed to register DMA domain notifier; IOMMU DMA ops unavailable on bus '%s'\n",
>> -			bus->name);
>> -		kfree(nb);
>> -	}
>> -	return ret;
>> -}
>> -
>>  static int __init __iommu_dma_init(void)
>>  {
>> -	int ret;
>> -
>> -	ret = iommu_dma_init();
>> -	if (!ret)
>> -		ret = register_iommu_dma_ops_notifier(&platform_bus_type);
>> -	if (!ret)
>> -		ret = register_iommu_dma_ops_notifier(&amba_bustype);
>> -#ifdef CONFIG_PCI
>> -	if (!ret)
>> -		ret = register_iommu_dma_ops_notifier(&pci_bus_type);
>> -#endif
>> -	return ret;
>> +	return iommu_dma_init();
>>  }
>>  arch_initcall(__iommu_dma_init);
>>
>> @@ -920,18 +832,12 @@ static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
>>
>>  	if (!ops)
>>  		return;
>> -	/*
>> -	 * TODO: As a concession to the future, we're ready to handle being
>> -	 * called both early and late (i.e. after bus_add_device). Once all
>> -	 * the platform bus code is reworked to call us late and the notifier
>> -	 * junk above goes away, move the body of do_iommu_attach here.
>
>...per this commment. It has no need to be a separate function once this
>is the only call site (plus it has a misleadingly inaccurate name anyway).

 ya, missed to remove that function as well. Will do it in the next.

Regards,
 Sricharan

^ 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