* [PATCH 9/9] Input: wm97xx: add new AC97 bus support
From: Charles Keepax @ 2016-10-27 9:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477510907-23495-10-git-send-email-robert.jarzmik@free.fr>
On Wed, Oct 26, 2016 at 09:41:47PM +0200, Robert Jarzmik wrote:
> This adds support for the new AC97 bus code, which discovers the devices
> rather than uses platform data.
>
> As part of this discovery, it enables a multi-function device wm97xx,
> which supports touchscreen, battery, ADC and an audio codec. This patch
> adds the code to bind the touchscreen "cell" as the touchscreen driver.
>
> This was tested on the pxa architecture with a pxa270 + wm9713 + the
> mioa701 touchscreen.
>
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> ---
Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Thanks,
Charles
^ permalink raw reply
* [PATCH 8/9] mfd: wm97xx-core: core support for wm97xx Codec
From: Charles Keepax @ 2016-10-27 9:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477510907-23495-9-git-send-email-robert.jarzmik@free.fr>
On Wed, Oct 26, 2016 at 09:41:46PM +0200, Robert Jarzmik wrote:
> The WM9705, WM9712 and WM9713 are highly integrated codecs, with an
> audio codec, DAC and ADC, GPIO unit and a touchscreen interface.
>
> Historically the support was spread across drivers/input/touchscreen and
> sound/soc/codecs. The sharing was done through ac97 bus sharing. This
> model will not withstand the new AC97 bus model, where codecs are
> discovered on runtime.
>
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> ---
Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Thanks,
Charles
^ permalink raw reply
* [RFC PATCH 1/5] of: introduce the overlay manager
From: Matthias Brugger @ 2016-10-27 9:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161026145756.21689-2-antoine.tenart@free-electrons.com>
On 10/26/2016 04:57 PM, Antoine Tenart wrote:
> The overlay manager is an in-kernel library helping to handle dt overlay
> loading when using capes.
>
> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
> ---
> drivers/of/Kconfig | 2 +
> drivers/of/Makefile | 1 +
> drivers/of/overlay-manager/Kconfig | 6 +
> drivers/of/overlay-manager/Makefile | 1 +
> drivers/of/overlay-manager/overlay-manager.c | 199 +++++++++++++++++++++++++++
> include/linux/overlay-manager.h | 38 +++++
> 6 files changed, 247 insertions(+)
> create mode 100644 drivers/of/overlay-manager/Kconfig
> create mode 100644 drivers/of/overlay-manager/Makefile
> create mode 100644 drivers/of/overlay-manager/overlay-manager.c
> create mode 100644 include/linux/overlay-manager.h
>
> diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
> index bc07ad30c9bf..e57aeaf0bf4f 100644
> --- a/drivers/of/Kconfig
> +++ b/drivers/of/Kconfig
> @@ -116,4 +116,6 @@ config OF_OVERLAY
> config OF_NUMA
> bool
>
> +source "drivers/of/overlay-manager/Kconfig"
> +
> endif # OF
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index d7efd9d458aa..d738fd41271f 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -16,3 +16,4 @@ obj-$(CONFIG_OF_OVERLAY) += overlay.o
> obj-$(CONFIG_OF_NUMA) += of_numa.o
>
> obj-$(CONFIG_OF_UNITTEST) += unittest-data/
> +obj-y += overlay-manager/
> diff --git a/drivers/of/overlay-manager/Kconfig b/drivers/of/overlay-manager/Kconfig
> new file mode 100644
> index 000000000000..eeb76054dcb8
> --- /dev/null
> +++ b/drivers/of/overlay-manager/Kconfig
> @@ -0,0 +1,6 @@
> +config OF_OVERLAY_MGR
> + bool "Device Tree Overlay Manager"
> + depends on OF_OVERLAY
> + help
> + Enable the overlay manager to handle automatic overlay loading when
> + devices are detected.
> diff --git a/drivers/of/overlay-manager/Makefile b/drivers/of/overlay-manager/Makefile
> new file mode 100644
> index 000000000000..86d2b53950e7
> --- /dev/null
> +++ b/drivers/of/overlay-manager/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_OF_OVERLAY_MGR) += overlay-manager.o
> diff --git a/drivers/of/overlay-manager/overlay-manager.c b/drivers/of/overlay-manager/overlay-manager.c
> new file mode 100644
> index 000000000000..a725d7e24d38
> --- /dev/null
> +++ b/drivers/of/overlay-manager/overlay-manager.c
> @@ -0,0 +1,199 @@
> +/*
> + * Copyright (C) 2016 - Antoine Tenart <antoine.tenart@free-electrons.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/firmware.h>
> +#include <linux/list.h>
> +#include <linux/of.h>
> +#include <linux/of_fdt.h>
> +#include <linux/overlay-manager.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +
> +struct overlay_mgr_overlay {
> + struct list_head list;
> + char *name;
> +};
> +
> +LIST_HEAD(overlay_mgr_overlays);
> +LIST_HEAD(overlay_mgr_formats);
Maybe you can find some better names for this, or rename the structs.
This will make the code more readable.
> +DEFINE_SPINLOCK(overlay_mgr_lock);
> +DEFINE_SPINLOCK(overlay_mgr_format_lock);
As Thomas already said, a mutex should be fine. We are not doing any
time critical here, right?
> +
> +/*
> + * overlay_mgr_register_format()
> + *
> + * Adds a new format candidate to the list of supported formats. The registered
> + * formats are used to parse the headers stored on the dips.
> + */
> +int overlay_mgr_register_format(struct overlay_mgr_format *candidate)
> +{
> + struct overlay_mgr_format *format;
> + int err = 0;
> +
> + spin_lock(&overlay_mgr_format_lock);
> +
> + /* Check if the format is already registered */
> + list_for_each_entry(format, &overlay_mgr_formats, list) {
> + if (!strcpy(format->name, candidate->name)) {
> + err = -EEXIST;
> + goto err;
> + }
> + }
> +
> + list_add_tail(&candidate->list, &overlay_mgr_formats);
> +
> +err:
> + spin_unlock(&overlay_mgr_format_lock);
> + return err;
> +}
> +EXPORT_SYMBOL_GPL(overlay_mgr_register_format);
> +
> +/*
> + * overlay_mgr_parse()
> + *
> + * Parse raw data with registered format parsers. Fills the candidate string if
> + * one parser understood the raw data format.
> + */
> +int overlay_mgr_parse(struct device *dev, void *data, char ***candidates,
> + unsigned *n)
> +{
> + struct list_head *pos, *tmp;
> + struct overlay_mgr_format *format;
> +
> + list_for_each_safe(pos, tmp, &overlay_mgr_formats) {
> + format = list_entry(pos, struct overlay_mgr_format, list);
> +
> + format->parse(dev, data, candidates, n);
> + if (n > 0)
> + return 0;
> + }
> +
> + return -EINVAL;
> +}
> +EXPORT_SYMBOL_GPL(overlay_mgr_parse);
> +
> +static int overlay_mgr_check_overlay(struct device_node *node)
> +{
> + struct property *p;
> + const char *str = NULL;
> +
> + p = of_find_property(node, "compatible", NULL);
> + if (!p)
> + return -EINVAL;
> +
> + do {
> + str = of_prop_next_string(p, str);
> + if (of_machine_is_compatible(str))
> + return 0;
> + } while (str);
> +
> + return -EINVAL;
> +}
> +
> +/*
> + * _overlay_mgr_insert()
> + *
> + * Try to request and apply an overlay given a candidate name.
> + */
> +static int _overlay_mgr_apply(struct device *dev, char *candidate)
Should be __overlay_mgr_apply(...)
Cheers,
Matthias
^ permalink raw reply
* [PATCH v2 2/4] dt-bindings: Add TI SCI PM Domains
From: Tero Kristo @ 2016-10-27 9:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161026220457.kvbd4wgtizdbndf3@rob-hp-laptop>
On 27/10/16 01:04, Rob Herring wrote:
> On Wed, Oct 19, 2016 at 03:33:45PM -0500, Dave Gerlach wrote:
>> Add a generic power domain implementation, TI SCI PM Domains, that
>> will hook into the genpd framework and allow the TI SCI protocol to
>> control device power states.
>>
>> Also, provide macros representing each device index as understood
>> by TI SCI to be used in the device node power-domain references.
>> These are identifiers for the K2G devices managed by the PMMC.
>>
>> Signed-off-by: Nishanth Menon <nm@ti.com>
>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>> ---
>> .../devicetree/bindings/soc/ti/sci-pm-domain.txt | 54 +++++++++++++
>> MAINTAINERS | 2 +
>> include/dt-bindings/genpd/k2g.h | 90 ++++++++++++++++++++++
>> 3 files changed, 146 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
>> create mode 100644 include/dt-bindings/genpd/k2g.h
>>
>> diff --git a/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
>> new file mode 100644
>> index 000000000000..32f38a349656
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
>> @@ -0,0 +1,54 @@
>> +Texas Instruments TI-SCI Generic Power Domain
>> +---------------------------------------------
>> +
>> +Some TI SoCs contain a system controller (like the PMMC, etc...) that is
>> +responsible for controlling the state of the IPs that are present.
>> +Communication between the host processor running an OS and the system
>> +controller happens through a protocol known as TI-SCI [1]. This pm domain
>> +implementation plugs into the generic pm domain framework and makes use of
>> +the TI SCI protocol power on and off each device when needed.
>> +
>> +[1] Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
>> +
>> +PM Domain Node
>> +==============
>> +The PM domain node represents the global PM domain managed by the PMMC,
>> +which in this case is the single implementation as documented by the generic
>> +PM domain bindings in Documentation/devicetree/bindings/power/power_domain.txt.
>> +
>> +Required Properties:
>> +--------------------
>> +- compatible: should be "ti,sci-pm-domain"
>> +- #power-domain-cells: Must be 0.
>> +- ti,sci: Phandle to the TI SCI device to use for managing the devices.
>> +
>> +Example:
>> +--------------------
>> +k2g_pds: k2g_pds {
>> + compatible = "ti,sci-pm-domain";
>> + #power-domain-cells = <0>;
>> + ti,sci = <&pmmc>;
>> +};
>
> Why not just make the PMMC node be the power-domain provider itself? If
> not that, then make this a child node of it. The same comment applies to
> all the SCI functions, but I guess I've already acked some of them.
This seems to be a bug in this documentation actually. ti,sci handle is
no longer supported, and all the sci stuff must be under the parent sci
node.
>
> I really don't like reviewing all these TI SCI bindings one by one. Each
> one on its own seems fine, but I don't see the full picture.
The full picture is represented under the documentation for the main
protocol support itself. See this patch:
https://patchwork.kernel.org/patch/9383281/
Copy pasted here as ref:
Example (K2G):
-------------
pmmc: pmmc {
compatible = "ti,k2g-sci";
...
my_clk_node: clk_node {
...
...
};
my_pd_node: pd_node {
...
...
};
};
^ permalink raw reply
* [PATCH 7/9] Input: wm97xx: split out touchscreen registering
From: Charles Keepax @ 2016-10-27 9:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477510907-23495-8-git-send-email-robert.jarzmik@free.fr>
On Wed, Oct 26, 2016 at 09:41:45PM +0200, Robert Jarzmik wrote:
> wm97xx-core does several things in it initialization :
> - touchscreen input device setup
> - battery device creation
>
> As the wm97xx is actually a multi-function device handling an audio
> codec, a touchscreen, a gpio block and an ADC, reshape the probing to
> isolate what is truly input/touchscreen specific from the remaining
> part.
>
> This is only code shuffling, there is no functional change.
>
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> ---
> drivers/input/touchscreen/wm97xx-core.c | 193 ++++++++++++++++++--------------
> 1 file changed, 112 insertions(+), 81 deletions(-)
>
> diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
> index 83cf11312fd9..50a110e2988b 100644
<snip>
> +static void wm97xx_remove_battery(struct wm97xx *wm)
> +{
> + platform_device_put(wm->battery_dev);
> +}
<snip>
> @@ -724,10 +757,8 @@ static int wm97xx_remove(struct device *dev)
> {
> struct wm97xx *wm = dev_get_drvdata(dev);
>
> - platform_device_unregister(wm->battery_dev);
> - platform_device_unregister(wm->touch_dev);
> - input_unregister_device(wm->input_dev);
> - kfree(wm);
> + wm97xx_remove_battery(wm);
The commit message says this is just shifting code around but the
platform_device_unregister for the battery_dev seems to have
turned into a platform_device_put here.
Thanks,
Charles
^ permalink raw reply
* [PATCH] fpga zynq: Check the bitstream for validity
From: Matthias Brugger @ 2016-10-27 8:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161026225413.GA6220@obsidianresearch.com>
On 10/27/2016 12:54 AM, Jason Gunthorpe wrote:
> There is no sense in sending a bitstream we know will not work, and
> with the variety of options for bitstream generation in Xilinx tools
> it is not terribly clear or very well documented what the correct
> input should be, especially since auto-detection was removed from this
> driver.
>
> All Zynq full configuration bitstreams must start with the sync word in
> the correct byte order.
>
> Zynq is also only able to DMA dword quantities, so bitstreams must be
> a multiple of 4 bytes. This also fixes a DMA-past the end bug.
>
> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
> ---
> drivers/fpga/zynq-fpga.c | 25 ++++++++++++++++---------
> 1 file changed, 16 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
> index c2fb4120bd62..46a38772e7ee 100644
> --- a/drivers/fpga/zynq-fpga.c
> +++ b/drivers/fpga/zynq-fpga.c
> @@ -184,12 +184,26 @@ static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
>
> priv = mgr->priv;
>
> + /* All valid bitstreams are multiples of 32 bits */
> + if ((count % 4) != 0)
> + return -EINVAL;
> +
> err = clk_enable(priv->clk);
> if (err)
> return err;
>
> /* don't globally reset PL if we're doing partial reconfig */
> if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) {
> + /* Sanity check the proposed bitstream. It must start with the
> + * sync word in the correct byte order and be a multiple of 4
> + * bytes.
> + */
> + if (count <= 4 || buf[0] != 0x66 || buf[1] != 0x55 ||
> + buf[2] != 0x99 || buf[3] != 0xaa) {
This checks if the bit stream is bigger then 4 bytes. We error out
before, if it is smaller. So you should fix the wording in the comment
and check for count == 4.
Regards,
Matthias
^ permalink raw reply
* [PATCH] ARM: imx: gpc: Initialize all power domains
From: Lucas Stach @ 2016-10-27 8:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161019141556.GA18806@tiger>
Am Mittwoch, den 19.10.2016, 22:15 +0800 schrieb Shawn Guo:
> On Tue, Oct 11, 2016 at 02:53:33PM -0300, Fabio Estevam wrote:
> > When booting a kernel built with multi_v7_defconfig the following
> > probe error is seen:
> >
> > imx-gpc: probe of 20dc000.gpc failed with error -22
> >
> > Later on the kernel crashes like this:
> >
> > [ 1.723358] Unable to handle kernel NULL pointer dereference at virtual address 00000040
> > [ 1.731500] pgd = c0204000
> > [ 1.731863] hctosys: unable to open rtc device (rtc0)
> > [ 1.739301] [00000040] *pgd=00000000
> > [ 1.739310] Internal error: Oops: 5 [#1] SMP ARM
> > [ 1.739319] Modules linked in:
> > [ 1.739328] CPU: 1 PID: 95 Comm: kworker/1:4 Not tainted 4.8.0-11897-g6b5e09a #1
> > [ 1.739331] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
> > [ 1.739352] Workqueue: pm genpd_power_off_work_fn
> > [ 1.739356] task: ee63d400 task.stack: ee70a000
> > [ 1.739365] PC is at mutex_lock+0xc/0x4c
> > [ 1.739374] LR is at regulator_disable+0x2c/0x60
> > [ 1.739379] pc : [<c0bc0da0>] lr : [<c06e4b10>] psr: 60000013
> > [ 1.739379] sp : ee70beb0 ip : 10624dd3 fp : ee6e6280
> > [ 1.739382] r10: eefb0900 r9 : 00000000 r8 : c1309918
> > [ 1.739385] r7 : 00000000 r6 : 00000040 r5 : 00000000 r4 : 00000040
> > [ 1.739390] r3 : 0000004c r2 : 7fffd540 r1 : 000001e4 r0 : 00000040
> >
> > The gpc probe fails because of_genpd_add_provider_onecell() checks
> > if all the domains are initialized via pm_genpd_present() function
> > and it returns an error on the multi_v7_defconfig case.
>
> It's not clear to me why this is only with multi_v7_defconfig, not
> imx_v6_v7_defconfig. Also, is it a regression or long-standing issue?
It's a regression in v4.9 and should be applied as a fix.
I don't see the crash on imx_v6_v7_defconfig, but without this patch the
GPC no longer probes correctly on v4.9 and other dependent devices will
not show up at all.
Regards,
Lucas
^ permalink raw reply
* [PATCH v8 0/3] ARM: dts: imx6q: Add Engicam i.CoreM6 dts
From: Jagan Teki @ 2016-10-27 8:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477037153-20484-1-git-send-email-jteki@openedev.com>
Hi Shawn,
On Fri, Oct 21, 2016 at 1:35 PM, Jagan Teki <jteki@openedev.com> wrote:
> From: Jagan Teki <jagan@amarulasolutions.com>
>
> This is series add dts support for Engicam I.Core M6 qdl modules. just
> rebased on top of linux-next.
>
> Jagan Teki (3):
> ARM: dts: imx6q: Add Engicam i.CoreM6 Quad/Dual initial support
> ARM: dts: imx6q: Add Engicam i.CoreM6 DualLite/Solo initial support
> ARM: dts: imx6qdl-icore: Add FEC support
>
> arch/arm/boot/dts/Makefile | 2 +
> arch/arm/boot/dts/imx6dl-icore.dts | 59 ++++++++
> arch/arm/boot/dts/imx6q-icore.dts | 59 ++++++++
> arch/arm/boot/dts/imx6qdl-icore.dtsi | 265 +++++++++++++++++++++++++++++++++++
> 4 files changed, 385 insertions(+)
> create mode 100644 arch/arm/boot/dts/imx6dl-icore.dts
> create mode 100644 arch/arm/boot/dts/imx6q-icore.dts
> create mode 100644 arch/arm/boot/dts/imx6qdl-icore.dtsi
Please let me know if you have any inputs on this?
thanks!
--
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.
^ permalink raw reply
* [PATCH 6/9] power_supply: wm97xx_battery: use power_supply_get_drvdata
From: Charles Keepax @ 2016-10-27 8:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477510907-23495-7-git-send-email-robert.jarzmik@free.fr>
On Wed, Oct 26, 2016 at 09:41:44PM +0200, Robert Jarzmik wrote:
> As the power supply framework provides a way to store and retrieve
> private supply data, use it.
>
> In the process, change the platform data for wm97xx_battery from a
> container of a single struct wm97xx_batt_pdata to the direct point to wm97xx_batt_pdata.
>
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> ---
Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Thanks,
Charles
^ permalink raw reply
* [PATCH 4/9] ASoC: wm9713: add ac97 new bus support
From: Charles Keepax @ 2016-10-27 8:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477510907-23495-5-git-send-email-robert.jarzmik@free.fr>
On Wed, Oct 26, 2016 at 09:41:42PM +0200, Robert Jarzmik wrote:
> Add support for the new ac97 bus model, where devices are automatically
> discovered on AC-Links.
>
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
> ---
Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Thanks,
Charles
^ permalink raw reply
* [PATCH V3 0/8] IOMMU probe deferral support
From: Sricharan @ 2016-10-27 8:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <421e2b14-0231-d376-02a0-097423120b3d@arm.com>
Hi Robin,
>>
>>
>>
>>> [ 39.901592] iommu: Removing device 0000:08:00.0 from group 0
>
>Yikes, on second look, that definitely shouldn't be happening.
>Everything below is probably the resulting fallout.
[ 40.206703] vfio-pci 0000:08:00.0: Failed to setup iommu ops
I think the above print which says "failed to setup iommu_ops"
because the call ops->add_device failed in of_pci_iommu_configure
is the reason for the failure, in my case i simply do not get this even with
your scripts. ops->add_device succeeds in the rebind as well. So still
checking what could be happening in your case.
Regards,
Sricharan
>
>Robin.
>
>>> [ 39.907383] ------------[ cut here ]------------
>>> [ 39.911969] WARNING: CPU: 0 PID: 174 at
>>> arch/arm64/mm/dma-mapping.c:856 arch_teardown_dma_ops+0x48/0x68
>>> [ 39.921266] Modules linked in:
>>> [ 39.924290]
>>> [ 39.925766] CPU: 0 PID: 174 Comm: vfio Not tainted 4.9.0-rc2+ #1249
>>> [ 39.931967] Hardware name: ARM Juno development board (r1) (DT)
>>> [ 39.937826] task: ffffffc975ee9900 task.stack: ffffffc974d60000
>>> [ 39.943687] PC is at arch_teardown_dma_ops+0x48/0x68
>>> [ 39.948603] LR is at arch_teardown_dma_ops+0x34/0x68
>>> [ 39.953516] pc : [<ffffff80080948f8>] lr : [<ffffff80080948e4>]
>>> pstate: 60000145
>>> [ 39.960834] sp : ffffffc974d63ca0
>>> [ 39.964112] x29: ffffffc974d63ca0 x28: ffffffc974d60000
>>> [ 39.969377] x27: ffffff80088a2000 x26: 0000000000000040
>>> [ 39.974642] x25: 0000000000000123 x24: ffffffc976a48918
>>> [ 39.979907] x23: ffffffc974d63eb8 x22: ffffff8008db7550
>>> [ 39.985171] x21: 000000000000000d x20: ffffffc9763e9b50
>>> [ 39.990435] x19: ffffffc9763f20a0 x18: 0000000000000010
>>> [ 39.995699] x17: 0000007f99c18018 x16: ffffff80080c0580
>>> [ 40.000964] x15: ffffff8008bb7000 x14: 000137c100013798
>>> [ 40.006228] x13: ffffffffff000000 x12: ffffffffffffffff
>>> [ 40.011492] x11: 0000000000000018 x10: 000000000000000d
>>> [ 40.016757] x9 : 0000000040000000 x8 : 0000000000210d00
>>> [ 40.022021] x7 : 00000049771bc000 x6 : 00000000001f17ed
>>> [ 40.027286] x5 : ffffff80084c4208 x4 : 0000000000000080
>>> [ 40.032551] x3 : ffffffc975ea9800 x2 : ffffffbf25d7aa50
>>> [ 40.037815] x1 : 0000000000000000 x0 : 0000000000000080
>>> [ 40.043078]
>>> [ 40.044549] ---[ end trace 35c1e743d6e6c035 ]---
>>> [ 40.049117] Call trace:
>>> [ 40.051537] Exception stack(0xffffffc974d63ad0 to 0xffffffc974d63c00)
>>> [ 40.057914] 3ac0: ffffffc9763f20a0
>>> 0000008000000000
>>> [ 40.065668] 3ae0: ffffffc974d63ca0 ffffff80080948f8 ffffffbf25d7aa40
>>> ffffffc975ea9800
>>> [ 40.073421] 3b00: ffffffc974d60000 000000000002fc80 ffffffc976801e00
>>> ffffffc974d60000
>>> [ 40.081175] 3b20: ffffff80084c4208 0000000000000040 ffffff80088a2000
>>> ffffffc974d60000
>>> [ 40.088928] 3b40: ffffff80084caf78 ffffffc974d60000 ffffffc974d60000
>>> ffffffc974d60000
>>> [ 40.096682] 3b60: ffffffc975ea9800 ffffffc974d60000 0000000000000080
>>> 0000000000000000
>>> [ 40.104435] 3b80: ffffffbf25d7aa50 ffffffc975ea9800 0000000000000080
>>> ffffff80084c4208
>>> [ 40.112188] 3ba0: 00000000001f17ed 00000049771bc000 0000000000210d00
>>> 0000000040000000
>>> [ 40.119941] 3bc0: 000000000000000d 0000000000000018 ffffffffffffffff
>>> ffffffffff000000
>>> [ 40.127695] 3be0: 000137c100013798 ffffff8008bb7000 ffffff80080c0580
>>> 0000007f99c18018
>>> [ 40.135450] [<ffffff80080948f8>] arch_teardown_dma_ops+0x48/0x68
>>> [ 40.141400] [<ffffff8008764a14>] of_dma_deconfigure+0xc/0x18
>>> [ 40.147005] [<ffffff8008552804>] dma_deconfigure+0xc/0x18
>>> [ 40.152353] [<ffffff800853ba10>] __device_release_driver+0x88/0x120
>>> [ 40.158560] [<ffffff800853bacc>] device_release_driver+0x24/0x38
>>> [ 40.164507] [<ffffff800853a868>] unbind_store+0xe8/0x110
>>> [ 40.169767] [<ffffff8008539c70>] drv_attr_store+0x20/0x30
>>> [ 40.175113] [<ffffff800823ab18>] sysfs_kf_write+0x48/0x58
>>> [ 40.180458] [<ffffff8008239ea8>] kernfs_fop_write+0xb0/0x1d8
>>> [ 40.186063] [<ffffff80081c507c>] __vfs_write+0x1c/0x100
>>> [ 40.191237] [<ffffff80081c5e80>] vfs_write+0xa0/0x1b8
>>> [ 40.196239] [<ffffff80081c7274>] SyS_write+0x44/0xa0
>>> [ 40.201155] [<ffffff8008082ef0>] el0_svc_naked+0x24/0x28
>>> [ 40.206703] vfio-pci 0000:08:00.0: Failed to setup iommu ops
>>> [ 40.212382] vfio-pci: probe of 0000:08:00.0 failed with error -22
>>> [ 40.228075] ------------[ cut here ]------------
>>> [ 40.235263] WARNING: CPU: 1 PID: 174 at ./include/linux/kref.h:46
>>> kobject_get+0x64/0x88
>>> [ 40.243181] Modules linked in:
>>> [ 40.246201]
>>> [ 40.247673] CPU: 1 PID: 174 Comm: vfio Tainted: G W
>>> 4.9.0-rc2+ #1249
>>> [ 40.255076] Hardware name: ARM Juno development board (r1) (DT)
>>> [ 40.260932] task: ffffffc975ee9900 task.stack: ffffffc974d60000
>>> [ 40.266787] PC is at kobject_get+0x64/0x88
>>> [ 40.270840] LR is at iommu_bus_notifier+0x40/0x110
>>> [ 40.275577] pc : [<ffffff800834d20c>] lr : [<ffffff80084c3fd0>]
>>> pstate: 80000145
>>> [ 40.282894] sp : ffffffc974d63c00
>>> [ 40.286169] x29: ffffffc974d63c00 x28: ffffffc974d60000
>>> [ 40.291431] x27: ffffff80088a2000 x26: 0000000000000040
>>> [ 40.296692] x25: 0000000000000123 x24: ffffffc974c8f418
>>> [ 40.301953] x23: 0000000000000006 x22: ffffffc9763f10a0
>>> [ 40.307214] x21: ffffffc9763e9a00 x20: ffffffc9763f10a0
>>> [ 40.312474] x19: ffffffc9763ebc80 x18: 0000007fd65069e0
>>> [ 40.317734] x17: 0000007f8d0ae3c0 x16: ffffff80081c7230
>>> [ 40.322995] x15: 0000007f8d136588 x14: ffffffffffffffff
>>> [ 40.328255] x13: 0000000000000004 x12: 0000000000000030
>>> [ 40.333515] x11: 0000000000000030 x10: 0101010101010101
>>> [ 40.338775] x9 : feff716475687163 x8 : 7f7f7f7f7f7f7f7f
>>> [ 40.344035] x7 : feff716475687163 x6 : ffffffc976abf400
>>> [ 40.349295] x5 : ffffffc976abf400 x4 : 0000000000000000
>>> [ 40.354555] x3 : ffffff80084c3f90 x2 : ffffffc9763ebcb8
>>> [ 40.359814] x1 : 0000000000000001 x0 : ffffff8008d4f000
>>> [ 40.365074]
>>> [ 40.366542] ---[ end trace 35c1e743d6e6c036 ]---
>>> [ 40.371107] Call trace:
>>> [ 40.373523] Exception stack(0xffffffc974d63a30 to 0xffffffc974d63b60)
>>> [ 40.379895] 3a20: ffffffc9763ebc80
>>> 0000008000000000
>>> [ 40.387643] 3a40: ffffffc974d63c00 ffffff800834d20c ffffffc976812400
>>> ffffff8008237d94
>>> [ 40.395391] 3a60: ffffffbf25d78940 ffffffc974d60000 ffffffc975e259d8
>>> 0000000000005b81
>>> [ 40.403139] 3a80: ffffffc974d60000 ffffff8008d4b31f ffffff8008b0f000
>>> ffffffc976811c80
>>> [ 40.410887] 3aa0: ffffffc974d60000 ffffffc974d60000 ffffffc974d60000
>>> ffffff8008237000
>>> [ 40.418634] 3ac0: ffffffc975e259d8 ffffff8008b1b9a8 ffffff8008d4f000
>>> 0000000000000001
>>> [ 40.426382] 3ae0: ffffffc9763ebcb8 ffffff80084c3f90 0000000000000000
>>> ffffffc976abf400
>>> [ 40.434130] 3b00: ffffffc976abf400 feff716475687163 7f7f7f7f7f7f7f7f
>>> feff716475687163
>>> [ 40.441877] 3b20: 0101010101010101 0000000000000030 0000000000000030
>>> 0000000000000004
>>> [ 40.449625] 3b40: ffffffffffffffff 0000007f8d136588 ffffff80081c7230
>>> 0000007f8d0ae3c0
>>> [ 40.457372] [<ffffff800834d20c>] kobject_get+0x64/0x88
>>> [ 40.462455] [<ffffff80084c3fd0>] iommu_bus_notifier+0x40/0x110
>>> [ 40.468227] [<ffffff80080da288>] notifier_call_chain+0x50/0x90
>>> [ 40.473997] [<ffffff80080da694>] __blocking_notifier_call_chain+0x4c/0x90
>>> [ 40.480713] [<ffffff80080da6ec>] blocking_notifier_call_chain+0x14/0x20
>>> [ 40.487259] [<ffffff800853b9e4>] __device_release_driver+0x5c/0x120
>>> [ 40.493460] [<ffffff800853bacc>] device_release_driver+0x24/0x38
>>> [ 40.499402] [<ffffff800853a868>] unbind_store+0xe8/0x110
>>> [ 40.504656] [<ffffff8008539c70>] drv_attr_store+0x20/0x30
>>> [ 40.509997] [<ffffff800823ab18>] sysfs_kf_write+0x48/0x58
>>> [ 40.515337] [<ffffff8008239ea8>] kernfs_fop_write+0xb0/0x1d8
>>> [ 40.520936] [<ffffff80081c507c>] __vfs_write+0x1c/0x100
>>> [ 40.526104] [<ffffff80081c5e80>] vfs_write+0xa0/0x1b8
>>> [ 40.531100] [<ffffff80081c7274>] SyS_write+0x44/0xa0
>>> [ 40.536011] [<ffffff8008082ef0>] el0_svc_naked+0x24/0x28
>>> [ 40.541324] ata1.00: disabled
>>> [ 40.544878] sd 0:0:0:0: [sda] Synchronizing SCSI cache
>>> [ 40.550062] sd 0:0:0:0: [sda] Synchronize Cache(10) failed: Result:
>>> hostbyte=0x04 driverbyte=0x00
>>> [ 40.558871] sd 0:0:0:0: [sda] Stopping disk
>>> [ 40.563037] sd 0:0:0:0: [sda] Start/Stop Unit failed: Result:
>>> hostbyte=0x04 driverbyte=0x00
>>> [ 40.586990] Unable to handle kernel paging request at virtual address
>>> 0002003e
>>> [ 40.594702] pgd = ffffffc974c80000
>>> [ 40.598165] [0002003e] *pgd=00000009f5102003[ 40.602241] ,
>>> *pud=00000009f5102003
>>> , *pmd=0000000000000000[ 40.607694]
>>> [ 40.609171] Internal error: Oops: 96000006 [#1] PREEMPT SMP
>>> [ 40.614684] Modules linked in:
>>> [ 40.617712] CPU: 3 PID: 174 Comm: vfio Tainted: G W
>>> 4.9.0-rc2+ #1249
>>> [ 40.625118] Hardware name: ARM Juno development board (r1) (DT)
>>> [ 40.630977] task: ffffffc975ee9900 task.stack: ffffffc974d60000
>>> [ 40.636841] PC is at kobject_get+0x14/0x88
>>> [ 40.640897] LR is at iommu_get_domain_for_dev+0x1c/0x48
>>> [ 40.646068] pc : [<ffffff800834d1bc>] lr : [<ffffff80084c3dec>]
>>> pstate: 60000145
>>> [ 40.653387] sp : ffffffc974d63c60
>>> [ 40.656664] x29: ffffffc974d63c60 x28: ffffffc974d60000
>>> [ 40.661928] x27: ffffff80088a2000 x26: 0000000000000040
>>> [ 40.667193] x25: 0000000000000123 x24: ffffffc974c8f418
>>> [ 40.672457] x23: ffffffc974d63eb8 x22: ffffff8008dab568
>>> [ 40.677720] x21: 000000000000000d x20: ffffff8008dab568
>>> [ 40.682984] x19: 0000000000020002 x18: 0000000000000000
>>> [ 40.688246] x17: 0000000000000007 x16: 0000000000000001
>>> [ 40.693509] x15: ffffffc974cd091c x14: ffffffffffffffff
>>> [ 40.698773] x13: ffffffc974cd01cd x12: 0000000000000030
>>> [ 40.704036] x11: 0101010101010101 x10: 7f7f7f7f7f7f7f7f
>>> [ 40.709300] x9 : 0000000040000000 x8 : 0000000000210d00
>>> [ 40.714563] x7 : ffffffc975f95018 x6 : 0000000000000000
>>> [ 40.719826] x5 : 0000000000000000 x4 : ffffffc9763f1210
>>> [ 40.725088] x3 : 0000000000000000 x2 : ffffffc9763f10e8
>>> [ 40.730351] x1 : 0000000000000000 x0 : 0000000000020002
>>> [ 40.735613]
>>> [ 40.737085] Process vfio (pid: 174, stack limit = 0xffffffc974d60020)
>>> [ 40.743460] Stack: (0xffffffc974d63c60 to 0xffffffc974d64000)
>>> [ 40.749150] 3c60: ffffffc974d63c80 ffffff80084c3dec ffffffc9763e9a00
>>> ffffff80085377a4
>>> [ 40.756904] 3c80: ffffffc974d63ca0 ffffff80080948c4 ffffffc9763f10a0
>>> ffffff8008dab568
>>> [ 40.764658] 3ca0: ffffffc974d63cc0 ffffff8008764a14 ffffffc9763f10a0
>>> ffffff8008dab568
>>> [ 40.772411] 3cc0: ffffffc974d63cd0 ffffff8008552804 ffffffc974d63ce0
>>> ffffff800853ba10
>>> [ 40.780165] 3ce0: ffffffc974d63d00 ffffff800853bacc ffffffc9763f1100
>>> ffffffc9763f10a0
>>> [ 40.787918] 3d00: ffffffc974d63d20 ffffff800853a868 ffffff8008d68f18
>>> ffffffc9763f10a0
>>> [ 40.795672] 3d20: ffffffc974d63d50 ffffff8008539c70 000000000000000d
>>> ffffffc974c8f400
>>> [ 40.803425] 3d40: ffffffc9757d5880 0000000000000000 ffffffc974d63d60
>>> ffffff800823ab18
>>> [ 40.811178] 3d60: ffffffc974d63d70 ffffff8008239ea8 ffffffc974d63dc0
>>> ffffff80081c507c
>>> [ 40.818931] 3d80: 000000000000000d 0000000000000000 ffffffc974c8f100
>>> ffffffc974d63eb8
>>> [ 40.826684] 3da0: 000000001285f6a0 0000000000000015 0000000000000123
>>> ffffff80080bf6ac
>>> [ 40.834437] 3dc0: ffffffc974d63e40 ffffff80081c5e80 000000000000000d
>>> 0000000000000000
>>> [ 40.842190] 3de0: ffffffc974d63e30 ffffff80080c087c ffffffc974d63e20
>>> ffffff80081c5c0c
>>> [ 40.849943] 3e00: ffffffc974c8f100 0000000000000001 ffffffc974c8f100
>>> ffffffc974d63eb8
>>> [ 40.857696] 3e20: ffffffc974d63e40 ffffff80081c5f48 000000000000000d
>>> ffffffc974c8f100
>>> [ 40.865450] 3e40: ffffffc974d63e80 ffffff80081c7274 ffffffc974c8f100
>>> ffffffc974c8f100
>>> [ 40.873203] 3e60: 000000001285f6a0 000000000000000d 0000000060000000
>>> 0000000000000000
>>> [ 40.880956] 3e80: 0000000000000000 ffffff8008082ef0 0000000000000000
>>> 0000000000000001
>>> [ 40.888709] 3ea0: ffffffffffffffff 0000007f8d0ae3dc 0000000000000000
>>> 0000000000000000
>>> [ 40.896461] 3ec0: 0000000000000001 000000001285f6a0 000000000000000d
>>> 0000000000000000
>>> [ 40.904215] 3ee0: ae2e2e2e3f464b49 0000000000000000 000000001285f6b0
>>> 39322f392f2f2f2f
>>> [ 40.911968] 3f00: 0000000000000040 fefefeff2f2d2f2f 7f7f7f7f7f7f7f7f
>>> 0101010101010101
>>> [ 40.919721] 3f20: 0000000000000002 0000000000000004 ffffffffffffffff
>>> 0000007f8d136588
>>> [ 40.927474] 3f40: 0000000000000000 0000007f8d0ae3c0 0000007fd65069e0
>>> 00000000004ee000
>>> [ 40.935226] 3f60: 0000000000000001 000000001285f6a0 000000000000000d
>>> 0000000000000001
>>> [ 40.942980] 3f80: 0000000000000020 000000001285eed8 00000000004ba158
>>> 0000000000000000
>>> [ 40.950732] 3fa0: 0000000000000000 0000007fd6507f30 000000000040e74c
>>> 0000007fd6507130
>>> [ 40.958485] 3fc0: 0000007f8d0ae3dc 0000000060000000 0000000000000001
>>> 0000000000000040
>>> [ 40.966238] 3fe0: 0000000000000000 0000000000000000 0000002000103a00
>>> 4000000010000000
>>> [ 40.973986] Call trace:
>>> [ 40.976405] Exception stack(0xffffffc974d63a90 to 0xffffffc974d63bc0)
>>> [ 40.982780] 3a80: 0000000000020002
>>> 0000008000000000
>>> [ 40.990533] 3aa0: ffffffc974d63c60 ffffff800834d1bc ffffffc974d63ae0
>>> ffffff80085377a4
>>> [ 40.998287] 3ac0: ffffffc974d63b10 ffffff8008537424 ffffffc975e3ac28
>>> ffffffc975e3ac38
>>> [ 41.006041] 3ae0: ffffffc974d63b30 ffffff80081737cc ffffffc975e3ac38
>>> ffffff8008da62c0
>>> [ 41.013794] 3b00: ffffffc975e98100 ffffff80085401b0 0000000000000001
>>> ffffff8008540a08
>>> [ 41.021547] 3b20: 00000000000036b8 0000000000000040 0000000000020002
>>> 0000000000000000
>>> [ 41.029300] 3b40: ffffffc9763f10e8 0000000000000000 ffffffc9763f1210
>>> 0000000000000000
>>> [ 41.037053] 3b60: 0000000000000000 ffffffc975f95018 0000000000210d00
>>> 0000000040000000
>>> [ 41.044805] 3b80: 7f7f7f7f7f7f7f7f 0101010101010101 0000000000000030
>>> ffffffc974cd01cd
>>> [ 41.052558] 3ba0: ffffffffffffffff ffffffc974cd091c 0000000000000001
>>> 0000000000000007
>>> [ 41.060311] [<ffffff800834d1bc>] kobject_get+0x14/0x88
>>> [ 41.065398] [<ffffff80084c3dec>] iommu_get_domain_for_dev+0x1c/0x48
>>> [ 41.071607] [<ffffff80080948c4>] arch_teardown_dma_ops+0x14/0x68
>>> [ 41.077556] [<ffffff8008764a14>] of_dma_deconfigure+0xc/0x18
>>> [ 41.083161] [<ffffff8008552804>] dma_deconfigure+0xc/0x18
>>> [ 41.088509] [<ffffff800853ba10>] __device_release_driver+0x88/0x120
>>> [ 41.094715] [<ffffff800853bacc>] device_release_driver+0x24/0x38
>>> [ 41.100663] [<ffffff800853a868>] unbind_store+0xe8/0x110
>>> [ 41.105922] [<ffffff8008539c70>] drv_attr_store+0x20/0x30
>>> [ 41.111268] [<ffffff800823ab18>] sysfs_kf_write+0x48/0x58
>>> [ 41.116612] [<ffffff8008239ea8>] kernfs_fop_write+0xb0/0x1d8
>>> [ 41.122216] [<ffffff80081c507c>] __vfs_write+0x1c/0x100
>>> [ 41.127390] [<ffffff80081c5e80>] vfs_write+0xa0/0x1b8
>>> [ 41.132391] [<ffffff80081c7274>] SyS_write+0x44/0xa0
>>> [ 41.137307] [<ffffff8008082ef0>] el0_svc_naked+0x24/0x28
>>> [ 41.142567] Code: 910003fd f9000bf3 aa0003f3 b4000180 (3940f000)
>>> [ 41.148667] ---[ end trace 35c1e743d6e6c037 ]---
>>> Segmentation fault
>>> / #
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
>
>_______________________________________________
>linux-arm-kernel mailing list
>linux-arm-kernel at lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox