* [PATCH] ARM: sunxi: Add driver for sunxi usb phy
From: Hans de Goede @ 2014-01-14 22:58 UTC (permalink / raw)
To: linux-arm-kernel
The Allwinner A1x / A2x SoCs have 2 or 3 usb phys which are all accessed
through a single set of registers. Besides this there are also some other
phy related bits which need poking, which are per phy, but shared between the
ohci and ehci controllers, so these are also controlled from this new phy
driver.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
.../devicetree/bindings/phy/sun4i-usb-phy.txt | 26 ++
drivers/phy/Kconfig | 11 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-sun4i-usb.c | 318 +++++++++++++++++++++
4 files changed, 356 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
create mode 100644 drivers/phy/phy-sun4i-usb.c
diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
new file mode 100644
index 0000000..6c54b3b
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
@@ -0,0 +1,26 @@
+Allwinner sun4i USB PHY
+-----------------------
+
+Required properties:
+- compatible : should be one of "allwinner,sun4i-a10-usb-phy",
+ "allwinner,sun5i-a13-usb-phy" or "allwinner,sun7i-a20-usb-phy"
+- reg : 2 or 3 register offset + length pairs, 1 phy base reg pair +
+ 1 pair for the pmu-irq register of each hcd
+- #phy-cells : from the generic phy bindings, must be 1
+
+Optional properties:
+- clocks : phandle + clock specifier for the phy clock
+- clock-names : "usb_phy"
+- resets : a list of phandle + reset specifier pairs
+- reset-names : "usb0_reset", "usb1_reset", and / or "usb2_reset"
+
+Example:
+ usbphy: phy at 0x01c13400 {
+ #phy-cells = <1>;
+ compatible = "allwinner,sun4i-a10-usb-phy";
+ reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>;
+ clocks = <&usb_clk 8>;
+ clock-names = "usb_phy";
+ resets = <&usb_clk 1>, <&usb_clk 2>;
+ reset-names = "usb1_reset", "usb2_reset";
+ };
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 330ef2d..dcce4cf 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -51,4 +51,15 @@ config PHY_EXYNOS_DP_VIDEO
help
Support for Display Port PHY found on Samsung EXYNOS SoCs.
+config PHY_SUN4I_USB
+ tristate "Allwinner sunxi SoC USB PHY driver"
+ depends on ARCH_SUNXI
+ select GENERIC_PHY
+ help
+ Enable this to support the transceiver that is part of Allwinner
+ sunxi SoCs.
+
+ This driver controls the entire USB PHY block, both the USB OTG
+ parts, as well as the 2 regular USB 2 host PHYs.
+
endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index d0caae9..e9e82f0 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
+obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
new file mode 100644
index 0000000..a15ecc1
--- /dev/null
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -0,0 +1,318 @@
+/*
+ * Allwinner sun4i USB phy driver
+ *
+ * Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on code from
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ *
+ * Modelled after: Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+
+#define REG_ISCR 0x00
+#define REG_PHYCTL 0x04
+#define REG_PHYBIST 0x08
+#define REG_PHYTUNE 0x0c
+
+#define SUNXI_AHB_ICHR8_EN BIT(10)
+#define SUNXI_AHB_INCR4_BURST_EN BIT(9)
+#define SUNXI_AHB_INCRX_ALIGN_EN BIT(8)
+#define SUNXI_ULPI_BYPASS_EN BIT(0)
+
+#define MAX_PHYS 3
+
+struct sun4i_usb_phy_data {
+ struct clk *clk;
+ void __iomem *base;
+ struct mutex mutex;
+ int num_phys;
+ u32 disc_thresh;
+ struct sun4i_usb_phy {
+ struct phy *phy;
+ void __iomem *pmu_irq;
+ struct regulator *vbus;
+ struct reset_control *reset;
+ int index;
+ } phys[MAX_PHYS];
+};
+
+#define to_sun4i_usb_phy_data(phy) \
+ container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index])
+
+static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
+ int len)
+{
+ struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
+ u32 temp, usbc_bit = BIT(phy->index * 2);
+ int i;
+
+ mutex_lock(&phy_data->mutex);
+
+ for (i = 0; i < len; i++) {
+ temp = readl(phy_data->base + REG_PHYCTL);
+
+ /* clear the address portion */
+ temp &= ~(0xff << 8);
+
+ /* set the address */
+ temp |= ((addr + i) << 8);
+ writel(temp, phy_data->base + REG_PHYCTL);
+
+ /* set the data bit and clear usbc bit*/
+ temp = readb(phy_data->base + REG_PHYCTL);
+ if (data & 0x1)
+ temp |= BIT(7);
+ else
+ temp &= ~BIT(7);
+ temp &= ~usbc_bit;
+ writeb(temp, phy_data->base + REG_PHYCTL);
+
+ /* pulse usbc_bit */
+ temp = readb(phy_data->base + REG_PHYCTL);
+ temp |= usbc_bit;
+ writeb(temp, phy_data->base + REG_PHYCTL);
+
+ temp = readb(phy_data->base + REG_PHYCTL);
+ temp &= ~usbc_bit;
+ writeb(temp, phy_data->base + REG_PHYCTL);
+
+ data >>= 1;
+ }
+ mutex_unlock(&phy_data->mutex);
+}
+
+static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable)
+{
+ u32 bits, reg_value;
+
+ if (!phy->pmu_irq)
+ return;
+
+ bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
+ SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN;
+
+ reg_value = readl(phy->pmu_irq);
+
+ if (enable)
+ reg_value |= bits;
+ else
+ reg_value &= ~bits;
+
+ writel(reg_value, phy->pmu_irq);
+}
+
+static int sun4i_usb_phy_init(struct phy *_phy)
+{
+ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+ struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+ int ret;
+
+ ret = clk_prepare_enable(data->clk);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(phy->reset);
+ if (ret) {
+ clk_disable_unprepare(data->clk);
+ return ret;
+ }
+
+ /* Adjust PHY's magnitude and rate */
+ sun4i_usb_phy_write(phy, 0x20, 0x14, 5);
+
+ /* Disconnect threshold adjustment */
+ sun4i_usb_phy_write(phy, 0x2a, data->disc_thresh, 2);
+
+ sun4i_usb_phy_passby(phy, 1);
+
+ return 0;
+}
+
+static int sun4i_usb_phy_exit(struct phy *_phy)
+{
+ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+ struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+
+ sun4i_usb_phy_passby(phy, 0);
+ reset_control_assert(phy->reset);
+ clk_disable_unprepare(data->clk);
+
+ return 0;
+}
+
+static int sun4i_usb_phy_power_on(struct phy *_phy)
+{
+ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+ int ret;
+
+ if (phy->vbus) {
+ ret = regulator_enable(phy->vbus);
+ if (ret)
+ return ret;
+
+ }
+
+ return 0;
+}
+
+static int sun4i_usb_phy_power_off(struct phy *_phy)
+{
+ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+
+ if (phy->vbus)
+ regulator_disable(phy->vbus);
+
+ return 0;
+}
+
+static struct phy_ops sun4i_usb_phy_ops = {
+ .init = sun4i_usb_phy_init,
+ .exit = sun4i_usb_phy_exit,
+ .power_on = sun4i_usb_phy_power_on,
+ .power_off = sun4i_usb_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static struct phy *sun4i_usb_phy_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
+
+ if (WARN_ON(args->args[0] == 0 || args->args[0] >= data->num_phys))
+ return ERR_PTR(-ENODEV);
+
+ return data->phys[args->args[0]].phy;
+}
+
+static int sun4i_usb_phy_probe(struct platform_device *pdev)
+{
+ struct sun4i_usb_phy_data *data;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ void __iomem *pmu_irq = NULL;
+ struct phy_provider *phy_provider;
+ struct reset_control *reset;
+ struct regulator *vbus;
+ struct phy *phy;
+ char name[16];
+ int i;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ mutex_init(&data->mutex);
+ if (of_device_is_compatible(np, "allwinner,sun4i-a10-usb-phy")) {
+ data->num_phys = 3;
+ data->disc_thresh = 3;
+ } else if (of_device_is_compatible(np,
+ "allwinner,sun5i-a13-usb-phy")) {
+ data->num_phys = 2;
+ data->disc_thresh = 2;
+ } else { /* allwinner,sun7i-a20-usb-phy */
+ data->num_phys = 3;
+ data->disc_thresh = 2;
+ }
+
+ data->clk = devm_clk_get(dev, "usb_phy");
+ if (IS_ERR(data->clk)) {
+ dev_err(dev, "could not get usb_phy clock\n");
+ return PTR_ERR(data->clk);
+ }
+
+ /* Skip 0, 0 is the phy for otg which is not yet supported. */
+ for (i = 1; i < data->num_phys; i++) {
+ snprintf(name, sizeof(name), "usb%d_vbus", i);
+ vbus = devm_regulator_get_optional(dev, name);
+ if (IS_ERR(vbus)) {
+ if (PTR_ERR(vbus) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ vbus = NULL;
+ }
+
+ snprintf(name, sizeof(name), "usb%d_reset", i);
+ reset = devm_reset_control_get(dev, name);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "failed to get reset %s\n", name);
+ return PTR_ERR(phy);
+ }
+
+ if (i) { /* No pmu_irq for usbc0 */
+ pmu_irq = devm_ioremap_resource(dev,
+ platform_get_resource(pdev, IORESOURCE_MEM, i));
+ if (IS_ERR(pmu_irq))
+ return PTR_ERR(pmu_irq);
+ }
+
+ phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "failed to create PHY %d\n", i);
+ return PTR_ERR(phy);
+ }
+
+ data->phys[i].phy = phy;
+ data->phys[i].pmu_irq = pmu_irq;
+ data->phys[i].vbus = vbus;
+ data->phys[i].reset = reset;
+ data->phys[i].index = i;
+ phy_set_drvdata(phy, &data->phys[i]);
+ }
+
+ data->base = devm_ioremap_resource(dev,
+ platform_get_resource(pdev, IORESOURCE_MEM, 0));
+ if (IS_ERR(data->base))
+ return PTR_ERR(data->base);
+
+ dev_set_drvdata(dev, data);
+ phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
+ return 0;
+}
+
+static const struct of_device_id sun4i_usb_phy_of_match[] = {
+ { .compatible = "allwinner,sun4i-a10-usb-phy" },
+ { .compatible = "allwinner,sun5i-a13-usb-phy" },
+ { .compatible = "allwinner,sun7i-a20-usb-phy" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
+
+static struct platform_driver sun4i_usb_phy_driver = {
+ .probe = sun4i_usb_phy_probe,
+ .driver = {
+ .of_match_table = sun4i_usb_phy_of_match,
+ .name = "sun4i-usb-phy",
+ .owner = THIS_MODULE,
+ }
+};
+module_platform_driver(sun4i_usb_phy_driver);
+
+MODULE_DESCRIPTION("Allwinner sun4i USB phy driver");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");
--
1.8.4.2
^ permalink raw reply related
* [PATCH] ARM: dts: imx6qdl-sabreauto: Add LVDS support
From: Fabio Estevam @ 2014-01-14 22:51 UTC (permalink / raw)
To: linux-arm-kernel
From: Fabio Estevam <fabio.estevam@freescale.com>
Add LVDS support for mx6 sabreauto boards.
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
---
arch/arm/boot/dts/imx6qdl-sabreauto.dtsi | 43 ++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 088b0d2..47c5a3f 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -22,6 +22,14 @@
spdif-controller = <&spdif>;
spdif-in;
};
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm3 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <7>;
+ status = "okay";
+ };
};
&ecspi1 {
@@ -86,6 +94,10 @@
fsl,pins = <MX6QDL_GPMI_NAND_PINGRP1>;
};
+ pinctrl_pwm3: pwm1grp {
+ fsl,pins = <MX6QDL_PWM3_PINGRP1>;
+ };
+
pinctrl_spdif: spdifgrp {
fsl,pins = <
MX6QDL_PAD_KEY_COL3__SPDIF_IN 0x1b0b0
@@ -118,6 +130,37 @@
};
};
+&ldb {
+ status = "okay";
+
+ lvds-channel@0 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <18>;
+ status = "okay";
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: hsd100pxn1 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <220>;
+ hfront-porch = <40>;
+ vback-porch = <21>;
+ vfront-porch = <7>;
+ hsync-len = <60>;
+ vsync-len = <10>;
+ };
+ };
+ };
+};
+
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm3>;
+ status = "okay";
+};
+
&spdif {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spdif>;
--
1.8.1.2
^ permalink raw reply related
* [PATCH] ARM: OMAP4: sleep: byteswap data for big-endian
From: Taras Kondratiuk @ 2014-01-14 22:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAGo_u6oGDK5s0SeE6Z7UFM6eYdgoy-E+Tj67+pBWP-wQ3r9=QA@mail.gmail.com>
On 14 January 2014 23:13, Nishanth Menon <nm@ti.com> wrote:
> On Tue, Jan 14, 2014 at 3:03 PM, Santosh Shilimkar
> <santosh.shilimkar@ti.com> wrote:
>>
>>> ok.. some sort of Linaro thing about which I have no background about
>>> - but dont really care in this context.
>>>
>> Nothing related Linaro. Its just that platforms are supporting ARM BE
>> mode and Linaro folks had working patches for Panda. So I suggested
>> to get them on the lists.
>
> I tend to think -> is this with OFF mode and CPUidle completely
> working? All context save and restore works with this? on HS and GP
> devices with BE mode builds? works on SDP4430,60 variations,
> considered reuse with AM43xx which could use parts of that logic?
>
> I mean to indicate that terms like "works on panda" tends always to be relative.
Nishanth, let's be objective here.
CPUidle on 4460 does *not* work in mainline for at least two kernel releases
even for LE [1]. That fix exists because that "one group of folks"
faced the issue
during BE testing. Looks like not much people care about CPUIdle on OMAP4.
> It is nice to see it as a proof of concept, but I'd hate to see some
> dead code lying around in kernel and folks blindly following suit and
> introducing macros for new assembly for a feature that in practice
> just one group of folks care about and creates additional burden for
> rest of folks trying to keep that functionality going as we jump from
> one "device tree" style churn to another "framework"? Not to mean that
> good features should be kept away.. but personally, I could not find
> convincing arguments in this case..
In general I understand your concerns from previous e-mails, but I don't
see a point to spend time for a generic solution for a single user.
If there will be other platforms which need similar changes, then we can
think of some generic solution. Let's drop this patch for now.
We can just disable CPUidle for BE tasks or keep this patch forked.
[1] https://lkml.org/lkml/2013/10/22/401
--
Regards,
Taras Kondratiuk
^ permalink raw reply
* [GIT PULL 4/4] GIC crossbar support for v3.14 merge window
From: Kevin Hilman @ 2014-01-14 22:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140109012215.GL31323@atomide.com>
Tony Lindgren <tony@atomide.com> writes:
> The following changes since commit 413541dd66d51f791a0b169d9b9014e4f56be13c:
>
> Linux 3.13-rc5 (2013-12-22 13:08:32 -0800)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.14/crossbar-signed
>
> for you to fetch changes up to 70d4545544853e2d95909b919d4565ff32c3e3c5:
>
> ARM: DRA: Enable Crossbar IP support for DRA7XX (2014-01-08 09:21:42 -0800)
>
> ----------------------------------------------------------------
> Add support for GIC crossbar that routes interrupts on newer omaps.
>
> ----------------------------------------------------------------
I think this one is a little late for v3.14 also, and should spend some
more time in -next before v3.15. Also...
> Sricharan R (4):
> irqchip: irq-gic: Add support for routable irqs
... I see a Reviewed-by from tglx on this one...
> irqchip: crossbar: Add support for Crossbar IP
...but no signs of irqchip mainainer review/ack on this one.
Ideally, these two irqchip ones would be merged through the irqchip
maintainers...
> ARM: OMAP4+: Correct Wakeup-gen code to use physical irq number
> ARM: DRA: Enable Crossbar IP support for DRA7XX
.. and then we'd take these two through arm-soc.
If there are strong dependencies, we can take them all through arm-soc,
but I'd like to see the tags from the irqchip maintainers first.
Kevin
^ permalink raw reply
* [GIT PULL 3/4] trivial omap big endian changes for v3.14 merge window
From: Tony Lindgren @ 2014-01-14 22:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <871u0a6vqf.fsf@linaro.org>
* Kevin Hilman <khilman@linaro.org> [140114 14:33]:
> Tony Lindgren <tony@atomide.com> writes:
>
> > The following changes since commit 413541dd66d51f791a0b169d9b9014e4f56be13c:
> >
> > Linux 3.13-rc5 (2013-12-22 13:08:32 -0800)
> >
> > are available in the git repository at:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.14/be-signed
> >
> > for you to fetch changes up to fc6ca98c81bf0ea8b46064915b5947b971594101:
> >
> > ARM: OMAP: debug-leds: raw read and write endian fix (2014-01-07 16:09:45 -0800)
> >
> > ----------------------------------------------------------------
> > Trivial search and replace of read and write functions to allow
> > further patches to make omaps work also in big endian mode.
> >
> > ----------------------------------------------------------------
>
> I think this one should wait for v3.15. While a trivial rename, it's a
> pretty broad change and risks having conflicts and fallouts with other
> changes (thinking especially of ongoing clock changes.)
Sure no problem.
Tony
^ permalink raw reply
* [PATCH 4/7] drivers/pci/host: don't check resource with devm_ioremap_resource
From: Jingoo Han @ 2014-01-14 22:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201401141417.03349.marex@denx.de>
On Tuesday, January 14, 2014 10:17 PM, Marek Vasut wrote:
> On Tuesday, January 14, 2014 at 12:58:55 PM, Wolfram Sang wrote:
> > devm_ioremap_resource does sanity checks on the given resource. No need to
> > duplicate this in the driver.
> >
> > Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
>
> True that,
>
> Acked-by: Marek Vasut <marex@denx.de>
(+cc Fabio Estevam)
Hi all,
The same patch was already sent by Fabio Estevam a month ago.[1]
Also, it was applied to pci/next tree.[2]
[1] http://www.spinics.net/lists/linux-pci/msg26873.html
[2] http://git.kernel.org/cgit/linux/kernel/git/helgaas/pci.git/commit/?h=next&id=ebb034a4ce9fc37877b3df2b85b9c33d43349586
Best regards,
Jingoo Han
>
> > ---
> >
> > Should go via subsystem tree
> >
> > drivers/pci/host/pci-imx6.c | 5 -----
> > 1 file changed, 5 deletions(-)
> >
> > diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> > index bd70af8..5002e23 100644
> > --- a/drivers/pci/host/pci-imx6.c
> > +++ b/drivers/pci/host/pci-imx6.c
> > @@ -426,11 +426,6 @@ static int __init imx6_pcie_probe(struct
> > platform_device *pdev) "imprecise external abort");
> >
> > dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > - if (!dbi_base) {
> > - dev_err(&pdev->dev, "dbi_base memory resource not found\n");
> > - return -ENODEV;
> > - }
> > -
> > pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
> > if (IS_ERR(pp->dbi_base)) {
> > ret = PTR_ERR(pp->dbi_base);
>
> Best regards,
> Marek Vasut
^ permalink raw reply
* [GIT PULL 3/4] trivial omap big endian changes for v3.14 merge window
From: Kevin Hilman @ 2014-01-14 22:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140109012139.GK31323@atomide.com>
Tony Lindgren <tony@atomide.com> writes:
> The following changes since commit 413541dd66d51f791a0b169d9b9014e4f56be13c:
>
> Linux 3.13-rc5 (2013-12-22 13:08:32 -0800)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.14/be-signed
>
> for you to fetch changes up to fc6ca98c81bf0ea8b46064915b5947b971594101:
>
> ARM: OMAP: debug-leds: raw read and write endian fix (2014-01-07 16:09:45 -0800)
>
> ----------------------------------------------------------------
> Trivial search and replace of read and write functions to allow
> further patches to make omaps work also in big endian mode.
>
> ----------------------------------------------------------------
I think this one should wait for v3.15. While a trivial rename, it's a
pretty broad change and risks having conflicts and fallouts with other
changes (thinking especially of ongoing clock changes.)
Kevin
^ permalink raw reply
* [GIT PULL 2/4] omap device tree fixes for v3.14 merge window
From: Kevin Hilman @ 2014-01-14 22:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140109012053.GJ31323@atomide.com>
Tony Lindgren <tony@atomide.com> writes:
> The following changes since commit adfe9361b236154215d4b0fc8b6d79995394b15c:
>
> ARM: dts: Add basic devices on am3517-evm (2013-12-08 14:15:46 -0800)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.14/dt-signed
>
> for you to fetch changes up to e37e1cb0ee231ffdc9b5ef1da63a0c7e1077c603:
>
> ARM: dts: OMAP2: fix interrupt number for rng (2014-01-08 10:24:44 -0800)
>
> ----------------------------------------------------------------
> Split omap3 core padconf area into two as some of the registers in
> the padconf area are not accessible and used for other devices.
> Also fix the interrupt number for omap2 RNG, and add basic support
> for sbc-3xxx with cm-t3730.
>
> Note that the minor merge conflicts for omap_hwmod_2xxx_ipblock_data.c
> can be solved by just dropping the legacy hwmod data for interrupts
> for v3.14.
>
> ----------------------------------------------------------------
Applying to next/fixes-non-critical.
Kevin
^ permalink raw reply
* [PATCH v2 1/2] spi: spi-imx: enable dma support for escpi controller
From: Marek Vasut @ 2014-01-14 22:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140114221315.GE15567@sirena.org.uk>
On Tuesday, January 14, 2014 at 11:13:15 PM, Mark Brown wrote:
> On Tue, Jan 14, 2014 at 11:02:31PM +0100, Marek Vasut wrote:
> > On Tuesday, January 14, 2014 at 10:55:48 PM, Mark Brown wrote:
> > > Or try to - the other trick here is getting 4MB of contiguous memory in
> > > the first place (unless there's an IOMMU making everything pretty).
> >
> > Oh, but what if I want to make a really looong transfer ? Say, read
> > entire SPI NOR of 128MB in size ... Spansion has such big SPI NORs in
> > their new portfolio.
>
> Use scatter/gather - to the SPI controller and the outside world it
> still looks like one big transfer (I'm missing a way to go from a
> virtual address to a sg_list, that'd be handy). It's an issue if the
> DMA controller doesn't support it but but that's rare.
OK, yep, indeed.
Best regards,
Marek Vasut
^ permalink raw reply
* [GIT PULL 1/4] non-urgent omap fixes for v3.14 merge window
From: Kevin Hilman @ 2014-01-14 22:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52cde11d.a179420a.3652.ffffd40fSMTPIN_ADDED_BROKEN@mx.google.com>
Tony Lindgren <tony@atomide.com> writes:
> The following changes since commit 413541dd66d51f791a0b169d9b9014e4f56be13c:
>
> Linux 3.13-rc5 (2013-12-22 13:08:32 -0800)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-for-v3.14/fixes-not-urgent-signed
>
> for you to fetch changes up to bbc28cdbd003be5ceeaf644be3533e898c25da2b:
>
> ARM: OMAP2+: gpmc: Move legacy GPMC width setting (2014-01-08 09:49:47 -0800)
>
> ----------------------------------------------------------------
> Some non-urgent fixes to enable am335x features, update documentation,
> and to remove unnecessary double initialization for the GPMC code.
>
> ----------------------------------------------------------------
Thanks, adding to next/fixes-non-critical.
Kevin
^ permalink raw reply
* [PATCH v2 1/2] spi: spi-imx: enable dma support for escpi controller
From: Mark Brown @ 2014-01-14 22:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201401142302.31434.marex@denx.de>
On Tue, Jan 14, 2014 at 11:02:31PM +0100, Marek Vasut wrote:
> On Tuesday, January 14, 2014 at 10:55:48 PM, Mark Brown wrote:
> > Or try to - the other trick here is getting 4MB of contiguous memory in
> > the first place (unless there's an IOMMU making everything pretty).
> Oh, but what if I want to make a really looong transfer ? Say, read entire SPI
> NOR of 128MB in size ... Spansion has such big SPI NORs in their new portfolio.
Use scatter/gather - to the SPI controller and the outside world it
still looks like one big transfer (I'm missing a way to go from a
virtual address to a sg_list, that'd be handy). It's an issue if the
DMA controller doesn't support it but but that's rare.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140114/5a63d036/attachment.sig>
^ permalink raw reply
* [PATCH v2 1/2] spi: spi-imx: enable dma support for escpi controller
From: Marek Vasut @ 2014-01-14 22:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140114215548.GD15567@sirena.org.uk>
On Tuesday, January 14, 2014 at 10:55:48 PM, Mark Brown wrote:
> On Tue, Jan 14, 2014 at 10:38:32PM +0100, Marek Vasut wrote:
> > I know the MXC SPI controller works in full-duplex mode, thus must have
> > two equally big buffers (one for RX and one for TX) even if used in
> > half-duplex mode, right?
>
> We should factor this stuff out into the core, a bunch of controllers
> have that limitation.
>
> > The problem I perceive here is that when I do for example 4 MB long
> > continuous half-duplex transfer with the IMX SPI, your code will happily
> > allocate 4MB big buffer, right ?
>
> Or try to - the other trick here is getting 4MB of contiguous memory in
> the first place (unless there's an IOMMU making everything pretty).
Oh, but what if I want to make a really looong transfer ? Say, read entire SPI
NOR of 128MB in size ... Spansion has such big SPI NORs in their new portfolio.
> > Hence my suggestion, won't it be better to split such long transfers into
> > a chain of DMA descriptors AND use a small (say, 16KiB) buffer for the
> > unwanted direction ? This way, you would allocate the small 16KiB block
> > only once (heck, you can even allocate it in probe() ), and each
> > descriptor would point to this block, overwriting it or sourcing zeroes
> > from it .
>
> Yes, indeed. I've half started working on some dmaengine code and was
> going to do something like this as part of it - the idea was to have the
> core generate a sg_list to pass to devices with DMAable transfers which
> would enable this sort of rewriting and would also mean we could do
> things like scatter/gather more effectively. Not got as far as actually
> getting things into a nice shape for that though. There's a lot of
> common patterns here which we shouldn't be open coding.
Indeed, full ACK on this.
Best regards,
Marek Vasut
^ permalink raw reply
* [PATCH v2 1/2] spi: spi-imx: enable dma support for escpi controller
From: Mark Brown @ 2014-01-14 21:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201401142238.32262.marex@denx.de>
On Tue, Jan 14, 2014 at 10:38:32PM +0100, Marek Vasut wrote:
> I know the MXC SPI controller works in full-duplex mode, thus must have two
> equally big buffers (one for RX and one for TX) even if used in half-duplex
> mode, right?
We should factor this stuff out into the core, a bunch of controllers
have that limitation.
> The problem I perceive here is that when I do for example 4 MB long continuous
> half-duplex transfer with the IMX SPI, your code will happily allocate 4MB big
> buffer, right ?
Or try to - the other trick here is getting 4MB of contiguous memory in
the first place (unless there's an IOMMU making everything pretty).
> Hence my suggestion, won't it be better to split such long transfers into a
> chain of DMA descriptors AND use a small (say, 16KiB) buffer for the unwanted
> direction ? This way, you would allocate the small 16KiB block only once (heck,
> you can even allocate it in probe() ), and each descriptor would point to this
> block, overwriting it or sourcing zeroes from it .
Yes, indeed. I've half started working on some dmaengine code and was
going to do something like this as part of it - the idea was to have the
core generate a sg_list to pass to devices with DMAable transfers which
would enable this sort of rewriting and would also mean we could do
things like scatter/gather more effectively. Not got as far as actually
getting things into a nice shape for that though. There's a lot of
common patterns here which we shouldn't be open coding.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140114/8e412fb9/attachment.sig>
^ permalink raw reply
* [PATCH v5 0/4] Krait L1/L2 EDAC driver
From: Stephen Boyd @ 2014-01-14 21:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140114214850.GQ29865@pd.tnic>
On 01/14/14 13:48, Borislav Petkov wrote:
> On Tue, Jan 14, 2014 at 01:30:30PM -0800, Stephen Boyd wrote:
>> This patchset adds support for the Krait L1/L2 cache error detection
>> hardware. The first patch adds the Krait l2 indirection
>> register code. This patch is in need of an ACK from ARM folks.
>> The next two patches add the driver and the binding and
>> the final patch hooks it all up by adding the device tree node.
>>
>> I think Boris will pick up the first and third patches since they depend
>> on each other. The final dts change could go through arm-soc via davidb's tree
>> and the Documentation patch could go through the devicetree tree. Or patches 1
>> through 3 can go through Boris' tree.
>>
>> Changes since v4:
>> * Prefixed l2 accessors functions with krait_
>> * Dropped first two patches as Boris says he picked them up
> Hey Stephen,
>
> I'm going to send upstream only
>
> [PATCH v4 1/6] edac: Don't try to cancel workqueue when it's never setup
>
> as it is a clear bugfix.
>
> The second one
>
> [PATCH v4 2/6] genirq: export percpu irq functions for module usage
>
> will have to wait for when the driver goes in. But the driver depends on
> "ARM: Add Krait L2 register accessor functions" which still waits for
> ACKs, right?
>
Ok that sounds fine. The ARM patch is fairly minor so I'm not sure if
anyone is willing to ack it, but I'm willing to wait a little while to
see if anyone will.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* [BUG] FL1009: xHCI host not responding to stop endpoint command.
From: Arnaud Ebalard @ 2014-01-14 21:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140114170719.GA12126@xanatos>
Hi Sarah,
Sarah Sharp <sarah.a.sharp@linux.intel.com> writes:
>> I can add the following:
>>
>> 2) I just tested the copy of the small files using the ICY DOCK
>> MB981U3S-1S connected to my ReadyNAS 102 *on a 3.11.7 kernel*
>> and it completed successfully.
>
> Please try a 3.13-rc7 kernel after running `git revert 35773dac5f86`.
I tried current 3.13.0-rc8 w/ 35773dac5f86 reverted and the result is
the same:
Powering the dock station:
[ 70.530128] usb 3-1: new SuperSpeed USB device number 2 using xhci_hcd
[ 70.550649] usb 3-1: New USB device found, idVendor=174c, idProduct=5106
[ 70.557368] usb 3-1: New USB device strings: Mfr=2, Product=3, SerialNumber=1
[ 70.564529] usb 3-1: Product: AS2105
[ 70.568112] usb 3-1: Manufacturer: ASMedia
[ 70.572222] usb 3-1: SerialNumber: 00000000000000000000
[ 70.579174] usb-storage 3-1:1.0: USB Mass Storage device detected
[ 70.586379] scsi4 : usb-storage 3-1:1.0
[ 71.590415] scsi 4:0:0:0: Direct-Access ASMT 2105 0 PQ: 0 ANSI: 6
[ 71.601630] sd 4:0:0:0: Attached scsi generic sg2 type 0
[ 76.968663] sd 4:0:0:0: [sdc] 488281250 512-byte logical blocks: (250 GB/232 GiB)
[ 76.976800] sd 4:0:0:0: [sdc] Write Protect is off
[ 76.982190] sd 4:0:0:0: [sdc] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 77.028598] sdc: sdc1 sdc2
[ 77.035729] sd 4:0:0:0: [sdc] Attached SCSI disk
Starting the copy after mounting the disk and creating test/:
# cp -r /bin/ /lib /sbin /opt /etc /usr test/
[ 398.130048] xhci_hcd 0000:02:00.0: xHCI host not responding to stop endpoint command.
[ 398.137905] xhci_hcd 0000:02:00.0: Assuming host is dying, halting host.
[ 398.144650] xhci_hcd 0000:02:00.0: HC died; cleaning up
[ 398.150337] usb 3-1: USB disconnect, device number 2
[ 398.155472] sd 4:0:0:0: Device offlined - not ready after error recovery
[ 398.170111] sd 4:0:0:0: [sdc] Unhandled error code
[ 398.174923] sd 4:0:0:0: [sdc]
[ 398.178076] sd 4:0:0:0: [sdc] CDB:
[ 398.181606] end_request: I/O error, dev sdc, sector 235538432
[ 398.187367] EXT4-fs warning (device sdc1): ext4_end_bio:317: I/O error writing to inode 7347656 (offset 0 size 323584 starting block 29442334)
[ 398.200175] Buffer I/O error on device sdc1, logical block 29442048
[ 398.206457] Buffer I/O error on device sdc1, logical block 29442049
[ 398.212739] Buffer I/O error on device sdc1, logical block 29442050
[ 398.219016] Buffer I/O error on device sdc1, logical block 29442051
[ 398.225298] Buffer I/O error on device sdc1, logical block 29442052
[ 398.231579] Buffer I/O error on device sdc1, logical block 29442053
[ 398.237857] Buffer I/O error on device sdc1, logical block 29442054
[ 398.244137] Buffer I/O error on device sdc1, logical block 29442055
[ 398.250418] Buffer I/O error on device sdc1, logical block 29442056
[ 398.256696] Buffer I/O error on device sdc1, logical block 29442057
[ 398.264481] sd 4:0:0:0: [sdc] Unhandled error code
[ 398.269290] sd 4:0:0:0: [sdc]
[ 398.272466] sd 4:0:0:0: [sdc] CDB:
[ 398.275980] end_request: I/O error, dev sdc, sector 235538672
[ 398.281744] EXT4-fs warning (device sdc1): ext4_end_bio:317: I/O error writing to inode 7347656 (offset 0 size 323584 starting block 29442364)
[ 398.294606] EXT4-fs warning (device sdc1): ext4_end_bio:317: I/O error writing to inode 7347656 (offset 0 size 323584 starting block 29442383)
>> 2) on current 3.13.0-rc7 kernel (w/ Bj?rn patch applied just in case), I
>
> Which patch are you referring to?
This one:
Commit 60e453a940ac ("USBNET: fix handling padding packet")
added an extra SG entry in case padding is necessary, but
failed to update the initialisation of the list. This can
cause list traversal to fall off the end of the list,
resulting in an oops.
Fixes: 60e453a940ac ("USBNET: fix handling padding packet")
Reported-by: Thomas Kear <thomas@kear.co.nz>
Cc: Ming Lei <ming.lei@canonical.com>
Signed-off-by: Bj?rn Mork <bjorn@mork.no>
>> just transferred 40GB through a Logitec LAN-GT JU3H3 (it is based on an
>> ASIX AX88179) connected to my ReadyNAS Duo v2 (NEC XHCI controller) at
>> an average rate of 82MB/s. Bottom line: no issue. When I try to do the
>> same on my ReadyNAS 102, I immediately get complaints:
>
> Was the ReadyNAS 102 with the Fresco Logic host running 3.13.0-rc7 as
> well?
Yes. Summary is:
- RN102 w/ 3.11.7: OK
- RN102 w/ 3.13-rc7: KO
- Duo v2 w/ 3.13.0-rc7: OK
>> [ 383.280429] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20400 bytes untransferred
>> [ 383.280892] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20400 bytes untransferred
>> [ 411.620073] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20352 bytes untransferred
>> [ 411.620750] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20400 bytes untransferred
>> [ 411.621727] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20400 bytes untransferred
>> [ 412.066651] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20352 bytes untransferred
>> [ 412.067233] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20400 bytes untransferred
>> [ 412.068196] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20400 bytes untransferred
>> [ 412.242708] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20352 bytes untransferred
>> [ 412.243333] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20400 bytes untransferred
>> [ 412.244246] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20400 bytes untransferred
>> [ 412.417956] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20352 bytes untransferred
>> [ 412.418516] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20400 bytes untransferred
>> [ 412.419473] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20400 bytes untransferred
>> [ 412.545330] xhci_hcd 0000:02:00.0: ep 0x82 - asked for 20480 bytes, 20352 bytes untransferred
>
> Those messages are normal. It just means the device transferred less
> data than the host asked for, which is part of normal USB operation.
>
> Does the dock work despite the messages?
no
> Please send me the output of `sudo lspci -vvv -n` for the ReadyNAS 102
> Fresco Logic host.
# lspci -vvv -n
00:01.0 0604: 11ab:7846 (prog-if 00 [Normal decode])
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 64 bytes
Bus: primary=00, secondary=01, subordinate=01, sec-latency=0
I/O behind bridge: 00010000-00010fff
Memory behind bridge: e0000000-e00fffff
Prefetchable memory behind bridge: 00000000-000fffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity- SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
00:02.0 0604: 11ab:7846 (prog-if 00 [Normal decode])
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 64 bytes
Bus: primary=00, secondary=02, subordinate=02, sec-latency=0
I/O behind bridge: 0000f000-00000fff
Memory behind bridge: e0100000-e01fffff
Prefetchable memory behind bridge: 00000000-000fffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity- SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
01:00.0 0106: 1b4b:9170 (rev 12) (prog-if 01 [AHCI 1.0])
Subsystem: 1b4b:9170
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 64 bytes
Interrupt: pin A routed to IRQ 105
Region 0: I/O ports at 10010 [size=8]
Region 1: I/O ports at 10020 [size=4]
Region 2: I/O ports at 10018 [size=8]
Region 3: I/O ports at 10024 [size=4]
Region 4: I/O ports at 10000 [size=16]
Region 5: Memory at e0010000 (32-bit, non-prefetchable) [size=512]
Expansion ROM@e0000000 [disabled] [size=64K]
Capabilities: [40] Power Management version 3
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot+,D3cold-)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [50] MSI: Enable+ Count=1/1 Maskable- 64bit-
Address: d0020a04 Data: 0f10
Capabilities: [70] Express (v2) Legacy Endpoint, MSI 00
DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s <1us, L1 <8us
ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop-
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L0s L1, Latency L0 <512ns, L1 <64us
ClockPM- Surprise- LLActRep- BwNot-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
DevCap2: Completion Timeout: Not Supported, TimeoutDis+, LTR-, OBFF Not Supported
DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
Compliance De-emphasis: -6dB
LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
Capabilities: [100 v1] Advanced Error Reporting
UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
AERCap: First Error Pointer: 00, GenCap- CGenEn- ChkCap- ChkEn-
Kernel driver in use: ahci
02:00.0 0c03: 1b73:1009 (rev 02) (prog-if 30 [XHCI])
Subsystem: 1b73:0000
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 64 bytes
Interrupt: pin A routed to IRQ 104
Region 0: Memory at e0100000 (64-bit, non-prefetchable) [size=64K]
Region 2: Memory at e0110000 (64-bit, non-prefetchable) [size=4K]
Region 4: Memory@e0111000 (64-bit, non-prefetchable) [size=4K]
Capabilities: [40] Power Management version 3
Flags: PMEClk- DSI- D1+ D2- AuxCurrent=375mA PME(D0+,D1+,D2-,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [50] MSI: Enable- Count=1/8 Maskable- 64bit+
Address: 0000000000000000 Data: 0000
Capabilities: [70] Express (v2) Endpoint, MSI 00
DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s unlimited, L1 unlimited
ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr+ TransPend-
LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L0s L1, Latency L0 unlimited, L1 unlimited
ClockPM- Surprise- LLActRep- BwNot-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
DevCap2: Completion Timeout: Not Supported, TimeoutDis+, LTR-, OBFF Not Supported
DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
Compliance De-emphasis: -6dB
LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
Capabilities: [b0] MSI-X: Enable+ Count=8 Masked-
Vector table: BAR=2 offset=00000000
PBA: BAR=4 offset=00000000
Capabilities: [100 v1] Advanced Error Reporting
UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
AERCap: First Error Pointer: 00, GenCap+ CGenEn- ChkCap+ ChkEn-
Kernel driver in use: xhci_hcd
^ permalink raw reply
* [PATCH v2 1/2] spi: spi-imx: enable dma support for escpi controller
From: Frank Li @ 2014-01-14 21:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140114060254.GB1914@S2101-09.ap.freescale.net>
On Tue, Jan 14, 2014 at 12:02 AM, Shawn Guo <shawn.guo@linaro.org> wrote:
> The list linux-spi at vger.kernel.org should be copied.
>
> I also added Marek who has great experience of play DMA on SPI.
>
> On Sat, Jan 04, 2014 at 06:53:51AM +0800, Frank Li wrote:
>> After enable DMA
>>
>> spi-nor read speed is
>> dd if=/dev/mtd0 of=/dev/null bs=1M count=1
>> 1+0 records in
>> 1+0 records out
>> 1048576 bytes (1.0 MB) copied, 0.720402 s, 1.5 MB/s
>>
>> spi-nor write speed is
>> dd if=/dev/zero of=/dev/mtd0 bs=1M count=1
>> 1+0 records in
>> 1+0 records out
>> 1048576 bytes (1.0 MB) copied, 3.56044 s, 295 kB/s
>>
>> Before enable DMA
>>
>> spi-nor read speed is
>> dd if=/dev/mtd0 of=/dev/null bs=1M count=1
>> 1+0 records in
>> 1+0 records out
>> 1048576 bytes (1.0 MB) copied, 2.37717 s, 441 kB/s
>>
>> spi-nor write speed is
>>
>> dd if=/dev/zero of=/dev/mtd0 bs=1M count=1
>> 1+0 records in
>> 1+0 records out
>> 1048576 bytes (1.0 MB) copied, 4.83181 s, 217 kB/s
>>
>> Signed-off-by: Frank Li <Frank.Li@freescale.com>
>> ---
>> drivers/spi/spi-imx.c | 447 ++++++++++++++++++++++++++++++++++++++++++++++++-
>> 1 files changed, 441 insertions(+), 6 deletions(-)
>>
>> Change from v1.
>> 1. check if res is null at res = platform_get_resource(pdev, IORESOURCE_MEM, 0)
>> 2. fix failure transfer when len is not multiple watermark
>>
>> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
>> index b80f2f7..1a9099a 100644
>> --- a/drivers/spi/spi-imx.c
>> +++ b/drivers/spi/spi-imx.c
>> @@ -39,6 +39,10 @@
>> #include <linux/of_gpio.h>
>>
>> #include <linux/platform_data/spi-imx.h>
>> +#include <linux/dma-mapping.h>
>> +#include <linux/platform_data/dma-imx.h>
>> +#include <linux/dmaengine.h>
>> +
>
> Nit: we already have one blank in between.
>
>>
>> #define DRIVER_NAME "spi_imx"
>>
>> @@ -52,6 +56,9 @@
>> #define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */
>> #define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */
>>
>> +/* The maximum bytes that a sdma BD can transfer.*/
>> +#define MAX_SDMA_BD_BYTES (1 << 15)
>> +
>> struct spi_imx_config {
>> unsigned int speed_hz;
>> unsigned int bpw;
>> @@ -84,6 +91,7 @@ struct spi_imx_data {
>>
>> struct completion xfer_done;
>> void __iomem *base;
>> + resource_size_t mapbase;
>
> I think the following definition is more easy to understand.
>
> phys_addr_t pbase;
>
>> int irq;
>> struct clk *clk_per;
>> struct clk *clk_ipg;
>> @@ -92,6 +100,29 @@ struct spi_imx_data {
>> unsigned int count;
>> void (*tx)(struct spi_imx_data *);
>> void (*rx)(struct spi_imx_data *);
>> + int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);
>> + struct dma_chan *dma_chan_rx, *dma_chan_tx;
>
> Having them on two line fits better to the style used here.
>
>> + unsigned int dma_is_inited;
>
> All other lines use space in between. Why these two use tabs?
>
>> + struct device *dev;
>> +
>> + struct completion dma_rx_completion;
>> + struct completion dma_tx_completion;
>> +
>> + u8 *dma_rx_tmpbuf;
>> + unsigned int dma_rx_tmpbuf_size;
>> + unsigned int dma_rx_tmpbuf_phy_addr;
>
> Use type dma_addr_t for it?
>
>> +
>> + u8 *dma_tx_tmpbuf;
>> + unsigned int dma_tx_tmpbuf_size;
>> + unsigned int dma_tx_tmpbuf_phy_addr;
>> +
>> + unsigned int usedma;
>> + unsigned int dma_finished;
>> + /* SDMA wartermark */
>> + u32 rx_wml;
>> + u32 tx_wml;
>> + u32 rxt_wml;
>> +
>> void *rx_buf;
>> const void *tx_buf;
>> unsigned int txfifo; /* number of words pushed in tx FIFO */
>> @@ -185,6 +216,7 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
>> #define MX51_ECSPI_CTRL 0x08
>> #define MX51_ECSPI_CTRL_ENABLE (1 << 0)
>> #define MX51_ECSPI_CTRL_XCH (1 << 2)
>> +#define MX51_ECSPI_CTRL_SMC (1 << 3)
>
> You do not have to follow the wrong pattern. One space after '<<' is
> good enough.
>
>> #define MX51_ECSPI_CTRL_MODE_MASK (0xf << 4)
>> #define MX51_ECSPI_CTRL_POSTDIV_OFFSET 8
>> #define MX51_ECSPI_CTRL_PREDIV_OFFSET 12
>> @@ -202,9 +234,22 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
>> #define MX51_ECSPI_INT_TEEN (1 << 0)
>> #define MX51_ECSPI_INT_RREN (1 << 3)
>>
>> +#define MX51_ECSPI_DMA 0x14
>> +#define MX51_ECSPI_DMA_TX_WML_OFFSET 0
>> +#define MX51_ECSPI_DMA_TX_WML_MASK 0x3F
>
> It seems that the common pattern for hex value in this file is to use
> lowercase.
>
>> +#define MX51_ECSPI_DMA_RX_WML_OFFSET 16
>> +#define MX51_ECSPI_DMA_RX_WML_MASK (0x3F << 16)
>> +#define MX51_ECSPI_DMA_RXT_WML_OFFSET 24
>> +#define MX51_ECSPI_DMA_RXT_WML_MASK (0x3F << 16)
>
> Shouldn't it be (0x3F << 24)?
>
>> +
>> +#define MX51_ECSPI_DMA_TEDEN_OFFSET 7
>> +#define MX51_ECSPI_DMA_RXDEN_OFFSET 23
>> +#define MX51_ECSPI_DMA_RXTDEN_OFFSET 31
>
> Please use tabs to align these numbers in the same column.
>
>> +
>> #define MX51_ECSPI_STAT 0x18
>> #define MX51_ECSPI_STAT_RR (1 << 3)
>>
>> +#define MX51_ECSPI_TESTREG 0x20
>
> It's used nowhere?
>
>> /* MX51 eCSPI */
>> static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi)
>> {
>> @@ -255,16 +300,28 @@ static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
>> {
>> u32 reg;
>>
>> - reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
>> - reg |= MX51_ECSPI_CTRL_XCH;
>> - writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
>> + if (!spi_imx->usedma) {
>
> So the DMA support is added for imx51-ecspi type device only? If that's
> case, we should make it clear in commit log.
>
>> + reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
>> + reg |= MX51_ECSPI_CTRL_XCH;
>> + writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
>> + } else {
>> + if (!spi_imx->dma_finished) {
>> + reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
>> + reg |= MX51_ECSPI_CTRL_SMC;
>> + writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
>> + } else {
>> + reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
>> + reg &= (~MX51_ECSPI_CTRL_SMC);
>
> Unnecessary parentheses.
>
>> + writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
>> + }
>
> Wouldn't it make more sense to write it like below?
>
> reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
> if (!spi_imx->dma_finished)
> reg |= MX51_ECSPI_CTRL_SMC;
> else
> reg &= ~MX51_ECSPI_CTRL_SMC;
> writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
>
>> + }
>> }
>>
>> static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
>> struct spi_imx_config *config)
>> {
>> - u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0;
>> -
>> + u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;
>> + u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;
>> /*
>> * The hardware seems to have a race condition when changing modes. The
>> * current assumption is that the selection of the channel arrives
>> @@ -297,6 +354,30 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
>> writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
>> writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
>>
>> + /*
>> + * Configure the DMA register: setup the watermark
>> + * and enable DMA request.
>> + */
>> + if (spi_imx->dma_is_inited) {
>> + dma = readl(spi_imx->base + MX51_ECSPI_DMA);
>> +
>> + spi_imx->tx_wml = spi_imx_get_fifosize(spi_imx) / 2;
>> + spi_imx->rx_wml = spi_imx_get_fifosize(spi_imx) / 2;
>> + spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2;
>> + rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
>> + tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
>> + rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
>> + dma = (dma & (~MX51_ECSPI_DMA_TX_WML_MASK)
>> + & (~MX51_ECSPI_DMA_RX_WML_MASK)
>> + & (~MX51_ECSPI_DMA_RXT_WML_MASK))
>
> Unnecessary parentheses.
>
>> + | rx_wml_cfg | tx_wml_cfg | rxt_wml_cfg
>> + | (1 << MX51_ECSPI_DMA_TEDEN_OFFSET)
>> + | (1 << MX51_ECSPI_DMA_RXDEN_OFFSET)
>> + | (1 << MX51_ECSPI_DMA_RXTDEN_OFFSET);
>> +
>> + writel(dma, spi_imx->base + MX51_ECSPI_DMA);
>> + }
>> +
>> return 0;
>> }
>
> ... skip the dma code, and hope Marek can help review it ...
>
>> @@ -729,6 +1088,27 @@ static int spi_imx_transfer(struct spi_device *spi,
>> return transfer->len;
>> }
>>
>> +static int spi_imx_transfer(struct spi_device *spi,
>> + struct spi_transfer *transfer)
>> +{
>> + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
>> +
>> + if (spi_imx->dma_chan_tx && spi_imx->dma_chan_rx) {
>> + /*
>> + * Don't use sdma when the size of data to be transfered is
>> + * lower then SDMA wartermark.
>> + */
>> + if ((transfer->len >= spi_imx->rx_wml) &&
>> + (transfer->len > spi_imx->tx_wml)) {
>> + spi_imx->usedma = 1;
>> + return spi_imx_sdma_transfer(spi, transfer);
>> + }
>> + }
>> +
>> + spi_imx->usedma = 0;
>> + return spi_imx_pio_transfer(spi, transfer);
>> +}
>> +
>> static int spi_imx_setup(struct spi_device *spi)
>> {
>> struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
>> @@ -778,6 +1158,56 @@ spi_imx_unprepare_message(struct spi_master *master, struct spi_message *msg)
>> return 0;
>> }
>>
>> +static int spi_imx_sdma_init(struct spi_imx_data *spi_imx)
>> +{
>> + struct dma_slave_config slave_config = {};
>> + struct device *dev = spi_imx->dev;
>> + int ret;
>> +
>> +
>> + /* Prepare for TX : */
>> + spi_imx->dma_chan_tx = dma_request_slave_channel(dev, "tx");
>> + if (!spi_imx->dma_chan_tx) {
>> + dev_err(dev, "cannot get the TX DMA channel!\n");
>
> So we will see this error message for each type of imx spi device,
> though the driver only supports DMA for imx51-ecspi.
>
> Shawn
How to handle this one? change to devinfo? Or check check if imx51-ecspi?
>
>> + ret = -EINVAL;
>> + goto err;
>> + }
>> +
>> + slave_config.direction = DMA_MEM_TO_DEV;
>> + slave_config.dst_addr = spi_imx->mapbase + MXC_CSPITXDATA;
>> + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
>> + slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
>> + ret = dmaengine_slave_config(spi_imx->dma_chan_tx, &slave_config);
>> + if (ret) {
>> + dev_err(dev, "error in TX dma configuration.");
>> + goto err;
>> + }
>> +
>> + /* Prepare for RX : */
>> + spi_imx->dma_chan_rx = dma_request_slave_channel(dev, "rx");
>> + if (!spi_imx->dma_chan_rx) {
>> + dev_dbg(dev, "cannot get the DMA channel.\n");
>> + ret = -EINVAL;
>> + goto err;
>> + }
>> +
>> + slave_config.direction = DMA_DEV_TO_MEM;
>> + slave_config.src_addr = spi_imx->mapbase + MXC_CSPIRXDATA;
>> + slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
>> + slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
>> + ret = dmaengine_slave_config(spi_imx->dma_chan_rx, &slave_config);
>> + if (ret) {
>> + dev_err(dev, "error in RX dma configuration.\n");
>> + goto err;
>> + }
>> + spi_imx->dma_is_inited = 1;
>> +
>> + return 0;
>> +err:
>> + spi_imx_sdma_exit(spi_imx);
>> + return ret;
>> +}
>> +
>> static int spi_imx_probe(struct platform_device *pdev)
>> {
>> struct device_node *np = pdev->dev.of_node;
>> @@ -849,6 +1279,8 @@ static int spi_imx_probe(struct platform_device *pdev)
>> (struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
>>
>> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + if (res)
>> + spi_imx->mapbase = res->start;
>> spi_imx->base = devm_ioremap_resource(&pdev->dev, res);
>> if (IS_ERR(spi_imx->base)) {
>> ret = PTR_ERR(spi_imx->base);
>> @@ -890,6 +1322,9 @@ static int spi_imx_probe(struct platform_device *pdev)
>>
>> spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per);
>>
>> + spi_imx->dev = &pdev->dev;
>> + spi_imx_sdma_init(spi_imx);
>> +
>> spi_imx->devtype_data->reset(spi_imx);
>>
>> spi_imx->devtype_data->intctrl(spi_imx, 0);
>> --
>> 1.7.8
>>
>>
>>
>> _______________________________________________
>> 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 v2 1/2] spi: spi-imx: enable dma support for escpi controller
From: Mark Brown @ 2014-01-14 21:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAHrpEqS-_EBa2z+StMjk9upeyLWLff_p=bS+14TVMDQjoEHv+g@mail.gmail.com>
On Thu, Jan 09, 2014 at 04:56:02PM -0600, Frank Li wrote:
> > Signed-off-by: Frank Li <Frank.Li@freescale.com>
> ping!
Don't send contentless pings, either your mail has been lost (in which
case it'll need resending anyway) or this is just yet another mail to
read. You should also, as covered in SubmittingPatches, CC any patches
to both the maintainers (remembering to use the address in MAINTAINERS)
and the relevant mailing list. For SPI that's:
SPI SUBSYSTEM
M: Mark Brown <broonie@kernel.org>
L: linux-spi at vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
Q: http://patchwork.kernel.org/project/spi-devel-general/list/
S: Maintained
F: Documentation/spi/
F: drivers/spi/
F: include/linux/spi/
F: include/uapi/linux/spi/
It's OK to send to other places as well but don't rely on them, for
example my linux-arm-kernel folder currently has 1405 unread messages in
it.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140114/0446376b/attachment.sig>
^ permalink raw reply
* [PATCH v5 0/4] Krait L1/L2 EDAC driver
From: Borislav Petkov @ 2014-01-14 21:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389735034-21430-1-git-send-email-sboyd@codeaurora.org>
On Tue, Jan 14, 2014 at 01:30:30PM -0800, Stephen Boyd wrote:
> This patchset adds support for the Krait L1/L2 cache error detection
> hardware. The first patch adds the Krait l2 indirection
> register code. This patch is in need of an ACK from ARM folks.
> The next two patches add the driver and the binding and
> the final patch hooks it all up by adding the device tree node.
>
> I think Boris will pick up the first and third patches since they depend
> on each other. The final dts change could go through arm-soc via davidb's tree
> and the Documentation patch could go through the devicetree tree. Or patches 1
> through 3 can go through Boris' tree.
>
> Changes since v4:
> * Prefixed l2 accessors functions with krait_
> * Dropped first two patches as Boris says he picked them up
Hey Stephen,
I'm going to send upstream only
[PATCH v4 1/6] edac: Don't try to cancel workqueue when it's never setup
as it is a clear bugfix.
The second one
[PATCH v4 2/6] genirq: export percpu irq functions for module usage
will have to wait for when the driver goes in. But the driver depends on
"ARM: Add Krait L2 register accessor functions" which still waits for
ACKs, right?
--
Regards/Gruss,
Boris.
Sent from a fat crate under my desk. Formatting is fine.
--
^ permalink raw reply
* [PATCH v2 1/2] spi: spi-imx: enable dma support for escpi controller
From: Marek Vasut @ 2014-01-14 21:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140114060254.GB1914@S2101-09.ap.freescale.net>
On Tuesday, January 14, 2014 at 07:02:58 AM, Shawn Guo wrote:
> The list linux-spi at vger.kernel.org should be copied.
>
> I also added Marek who has great experience of play DMA on SPI.
I'm flattered, thanks ;-)
Best regards,
Marek Vasut
^ permalink raw reply
* [PATCH v2 1/2] spi: spi-imx: enable dma support for escpi controller
From: Marek Vasut @ 2014-01-14 21:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1388789632-12238-1-git-send-email-Frank.Li@freescale.com>
On Friday, January 03, 2014 at 11:53:51 PM, Frank Li wrote:
> After enable DMA
>
> spi-nor read speed is
> dd if=/dev/mtd0 of=/dev/null bs=1M count=1
> 1+0 records in
> 1+0 records out
> 1048576 bytes (1.0 MB) copied, 0.720402 s, 1.5 MB/s
>
> spi-nor write speed is
> dd if=/dev/zero of=/dev/mtd0 bs=1M count=1
> 1+0 records in
> 1+0 records out
> 1048576 bytes (1.0 MB) copied, 3.56044 s, 295 kB/s
>
> Before enable DMA
>
> spi-nor read speed is
> dd if=/dev/mtd0 of=/dev/null bs=1M count=1
> 1+0 records in
> 1+0 records out
> 1048576 bytes (1.0 MB) copied, 2.37717 s, 441 kB/s
>
> spi-nor write speed is
>
> dd if=/dev/zero of=/dev/mtd0 bs=1M count=1
> 1+0 records in
> 1+0 records out
> 1048576 bytes (1.0 MB) copied, 4.83181 s, 217 kB/s
>
> Signed-off-by: Frank Li <Frank.Li@freescale.com>
[...]
> +
> +static void spi_imx_dma_rx_callback(void *cookie)
> +{
> + struct spi_imx_data *spi_imx = (struct spi_imx_data *)cookie;
> +
> + complete(&spi_imx->dma_rx_completion);
> +
> +}
> +
> +static void spi_imx_dma_tx_callback(void *cookie)
> +{
> + struct spi_imx_data *spi_imx = (struct spi_imx_data *)cookie;
> +
> + complete(&spi_imx->dma_tx_completion);
> +}
> +
> +static int spi_imx_sdma_transfer(struct spi_device *spi,
> + struct spi_transfer *transfer)
> +{
This function needs splitting into multiple smaller ones, seriously. This
doesn't fit either on my rMBP's screen or on my desktop's _pivoted_ 27"
widescreen 2500x1400 LCD !
> + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
> + int ret = 0;
> + int sg_num;
> + int loop;
> + int left;
> + u32 dma;
> +
> + struct scatterlist *sg_rx, *sg_tx;
> + struct dma_async_tx_descriptor *txdesc;
> + struct dma_async_tx_descriptor *rxdesc;
> +
> + init_completion(&spi_imx->dma_rx_completion);
> + init_completion(&spi_imx->dma_tx_completion);
This should be reinit_completion(), the init_completion() should happen in the
probe function, CAREFUL about this !
> +
> + /*
> + * Get the valid physical address for the tx buf, if the rx buf address
> + * is null or it cannot be mapped, we should allocate memory for it.
> + */
I will skip this function until it's properly split. But anyway...
I know the MXC SPI controller works in full-duplex mode, thus must have two
equally big buffers (one for RX and one for TX) even if used in half-duplex
mode, right?
The problem I perceive here is that when I do for example 4 MB long continuous
half-duplex transfer with the IMX SPI, your code will happily allocate 4MB big
buffer, right ?
Hence my suggestion, won't it be better to split such long transfers into a
chain of DMA descriptors AND use a small (say, 16KiB) buffer for the unwanted
direction ? This way, you would allocate the small 16KiB block only once (heck,
you can even allocate it in probe() ), and each descriptor would point to this
block, overwriting it or sourcing zeroes from it .
But please, correct me if I misunderstood your code.
[...]
> +
> +static int spi_imx_pio_transfer(struct spi_device *spi,
> struct spi_transfer *transfer)
> {
> struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
> @@ -729,6 +1088,27 @@ static int spi_imx_transfer(struct spi_device *spi,
> return transfer->len;
> }
>
> +static int spi_imx_transfer(struct spi_device *spi,
> + struct spi_transfer *transfer)
> +{
> + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
> +
> + if (spi_imx->dma_chan_tx && spi_imx->dma_chan_rx) {
You do have spi_imx->dma_is_inited variable , so use it here.
> + /*
> + * Don't use sdma when the size of data to be transfered is
> + * lower then SDMA wartermark.
> + */
> + if ((transfer->len >= spi_imx->rx_wml) &&
> + (transfer->len > spi_imx->tx_wml)) {
Why do you use -ge in the first test and -gt in the second ? Besides, the
formating of the condition is really weird.
> + spi_imx->usedma = 1;
Don't you need to do some kind of locking here so that spi_imx->usedma won't be
overwritten if multiple users enter the spi_imx_transfer() function ? I am not
sure if this is called from a context already protected by the SPI framework's
mutex or not.
> + return spi_imx_sdma_transfer(spi, transfer);
> + }
> + }
> +
> + spi_imx->usedma = 0;
> + return spi_imx_pio_transfer(spi, transfer);
> +}
> +
> static int spi_imx_setup(struct spi_device *spi)
> {
> struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
> @@ -778,6 +1158,56 @@ spi_imx_unprepare_message(struct spi_master *master,
> struct spi_message *msg) return 0;
> }
>
> +static int spi_imx_sdma_init(struct spi_imx_data *spi_imx)
> +{
> + struct dma_slave_config slave_config = {};
> + struct device *dev = spi_imx->dev;
> + int ret;
> +
> +
One newline too much here.
> + /* Prepare for TX : */
I suppose this should be "Prepare TX DMA" ?
> + spi_imx->dma_chan_tx = dma_request_slave_channel(dev, "tx");
> + if (!spi_imx->dma_chan_tx) {
> + dev_err(dev, "cannot get the TX DMA channel!\n");
Sentence usually starts with capital letter ;-)
> + ret = -EINVAL;
> + goto err;
> + }
> +
> + slave_config.direction = DMA_MEM_TO_DEV;
> + slave_config.dst_addr = spi_imx->mapbase + MXC_CSPITXDATA;
> + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
> + slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
> + ret = dmaengine_slave_config(spi_imx->dma_chan_tx, &slave_config);
> + if (ret) {
> + dev_err(dev, "error in TX dma configuration.");
> + goto err;
> + }
> +
> + /* Prepare for RX : */
> + spi_imx->dma_chan_rx = dma_request_slave_channel(dev, "rx");
> + if (!spi_imx->dma_chan_rx) {
> + dev_dbg(dev, "cannot get the DMA channel.\n");
I'd turn all these dev_err() calls here into dev_dbg() and I'd print an error
message if this function returns !0 at where's it's called from below.
> + ret = -EINVAL;
> + goto err;
> + }
> +
> + slave_config.direction = DMA_DEV_TO_MEM;
> + slave_config.src_addr = spi_imx->mapbase + MXC_CSPIRXDATA;
> + slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
> + slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
> + ret = dmaengine_slave_config(spi_imx->dma_chan_rx, &slave_config);
> + if (ret) {
> + dev_err(dev, "error in RX dma configuration.\n");
> + goto err;
> + }
> + spi_imx->dma_is_inited = 1;
> +
> + return 0;
> +err:
> + spi_imx_sdma_exit(spi_imx);
> + return ret;
> +}
> +
> static int spi_imx_probe(struct platform_device *pdev)
> {
> struct device_node *np = pdev->dev.of_node;
> @@ -849,6 +1279,8 @@ static int spi_imx_probe(struct platform_device *pdev)
> (struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
>
> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (res)
> + spi_imx->mapbase = res->start;
> spi_imx->base = devm_ioremap_resource(&pdev->dev, res);
> if (IS_ERR(spi_imx->base)) {
> ret = PTR_ERR(spi_imx->base);
> @@ -890,6 +1322,9 @@ static int spi_imx_probe(struct platform_device *pdev)
>
> spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per);
>
> + spi_imx->dev = &pdev->dev;
> + spi_imx_sdma_init(spi_imx);
You must check return value here. I would say you want to print an error message
here, but you also want to avoid failing entirely, just indicate the DMA
couldn't be init'd and you'd just use PIO.
> +
> spi_imx->devtype_data->reset(spi_imx);
>
> spi_imx->devtype_data->intctrl(spi_imx, 0);
^ permalink raw reply
* [PATCH v4 1/2] ARM: imx: add select on ARCH_MXC for cpufreq support
From: John Tobias @ 2014-01-14 21:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140113060102.GO23525@S2101-09.ap.freescale.net>
I made a mistake. The HAVE_IMX_ANATOP doesn't require to move up. It
should be ARCH_HAS_OPP.
On Sun, Jan 12, 2014 at 10:01 PM, Shawn Guo <shawn.guo@linaro.org> wrote:
> On Sun, Jan 12, 2014 at 08:54:18PM -0800, John Tobias wrote:
>> I tested leaving the HAVE_IMX_ANATOP under SOC_IMX6Q and SOC_IMX6SL.
>> The iMX6Q cpufreq driver won't show up in menu config / gconfig and
>> that's the reason why I added it.
>
> I tested the following changes against my for-next branch, and I can see
> iMX6Q cpufreq driver in menuconfig. Note, the
> drivers/cpufreq/Kconfig.arm change is on cpufreq tree, so I have to make
> the change locally for the testing.
>
> Shawn
>
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index 1e70150..7071468 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -1,5 +1,7 @@
> config ARCH_MXC
> bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 ||
> ARCH_MULTI_V6_V7
> + select ARCH_HAS_CPUFREQ
> + select ARCH_HAS_OPP
> select ARCH_REQUIRE_GPIOLIB
> select ARM_CPU_SUSPEND if PM
> select ARM_PATCH_PHYS_VIRT
> @@ -12,6 +14,7 @@ config ARCH_MXC
> select MIGHT_HAVE_CACHE_L2X0 if ARCH_MULTI_V6_V7
> select MULTI_IRQ_HANDLER
> select PINCTRL
> + select PM_OPP if PM
> select SOC_BUS
> select SPARSE_IRQ
> select USE_OF
> @@ -787,8 +790,6 @@ config SOC_IMX53
>
> config SOC_IMX6Q
> bool "i.MX6 Quad/DualLite support"
> - select ARCH_HAS_CPUFREQ
> - select ARCH_HAS_OPP
> select ARM_ERRATA_754322
> select ARM_ERRATA_764369 if SMP
> select ARM_ERRATA_775420
> @@ -808,7 +809,6 @@ config SOC_IMX6Q
> select PL310_ERRATA_588369 if CACHE_PL310
> select PL310_ERRATA_727915 if CACHE_PL310
> select PL310_ERRATA_769419 if CACHE_PL310
> - select PM_OPP if PM
>
> help
> This enables support for Freescale i.MX6 Quad processor.
> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
> index ce52ed9..21e069e 100644
> --- a/drivers/cpufreq/Kconfig.arm
> +++ b/drivers/cpufreq/Kconfig.arm
> @@ -80,7 +80,7 @@ config ARM_HIGHBANK_CPUFREQ
>
> config ARM_IMX6Q_CPUFREQ
> tristate "Freescale i.MX6Q cpufreq support"
> - depends on SOC_IMX6Q
> + depends on ARCH_MXC
> depends on REGULATOR_ANATOP
> help
> This adds cpufreq driver support for Freescale i.MX6Q SOC.
>
>
^ permalink raw reply
* [PATCH v5 4/4] ARM: dts: msm: Add Krait CPU/L2 nodes
From: Stephen Boyd @ 2014-01-14 21:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389735034-21430-1-git-send-email-sboyd@codeaurora.org>
This allows us to probe the krait-edac driver.
Cc: David Brown <davidb@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/boot/dts/qcom-msm8974.dtsi | 41 +++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index 9fa57d72f41e..7a494eaabd24 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -9,6 +9,47 @@
compatible = "qcom,msm8974";
interrupt-parent = <&intc>;
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <1 9 0xf04>;
+ compatible = "qcom,krait";
+
+ cpu at 0 {
+ device_type = "cpu";
+ compatible = "qcom,krait";
+ reg = <0>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu at 1 {
+ device_type = "cpu";
+ compatible = "qcom,krait";
+ reg = <1>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu at 2 {
+ device_type = "cpu";
+ compatible = "qcom,krait";
+ reg = <2>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu at 3 {
+ device_type = "cpu";
+ compatible = "qcom,krait";
+ reg = <3>;
+ next-level-cache = <&L2>;
+ };
+
+ L2: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+ interrupts = <0 2 0x4>;
+ };
+ };
+
timer {
compatible = "arm,armv7-timer";
interrupts = <1 2 0xf08>,
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply related
* [PATCH v5 3/4] edac: Add support for Krait CPU cache error detection
From: Stephen Boyd @ 2014-01-14 21:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389735034-21430-1-git-send-email-sboyd@codeaurora.org>
Add support for the Krait CPU cache error detection. This is a
simplified version of the code originally written by Stepan
Moskovchenko[1] ported to the EDAC device framework.
[1] https://www.codeaurora.org/cgit/quic/la/kernel/msm/tree/arch/arm/mach-msm/cache_erp.c?h=msm-3.4
Cc: Stepan Moskovchenko <stepanm@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
drivers/edac/Kconfig | 8 ++
drivers/edac/Makefile | 2 +
drivers/edac/krait_edac.c | 346 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 356 insertions(+)
create mode 100644 drivers/edac/krait_edac.c
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 878f09005fad..68f612d06eed 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -368,4 +368,12 @@ config EDAC_OCTEON_PCI
Support for error detection and correction on the
Cavium Octeon family of SOCs.
+config EDAC_KRAIT_CACHE
+ tristate "Krait L1/L2 Cache"
+ depends on EDAC_MM_EDAC && ARCH_MSM
+ select KRAIT_L2_ACCESSORS
+ help
+ Support for error detection and correction on the
+ Krait L1/L2 cache controller.
+
endif # EDAC
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 4154ed6a02c6..b6ea50564223 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -64,3 +64,5 @@ obj-$(CONFIG_EDAC_OCTEON_PC) += octeon_edac-pc.o
obj-$(CONFIG_EDAC_OCTEON_L2C) += octeon_edac-l2c.o
obj-$(CONFIG_EDAC_OCTEON_LMC) += octeon_edac-lmc.o
obj-$(CONFIG_EDAC_OCTEON_PCI) += octeon_edac-pci.o
+
+obj-$(CONFIG_EDAC_KRAIT_CACHE) += krait_edac.o
diff --git a/drivers/edac/krait_edac.c b/drivers/edac/krait_edac.c
new file mode 100644
index 000000000000..80a363e15b5b
--- /dev/null
+++ b/drivers/edac/krait_edac.c
@@ -0,0 +1,346 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/cpu.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+
+#include <asm/krait-l2-accessors.h>
+
+#include "edac_core.h"
+
+#define CESR_DCTPE BIT(0)
+#define CESR_DCDPE BIT(1)
+#define CESR_ICTPE BIT(2)
+#define CESR_ICDPE BIT(3)
+#define CESR_DCTE (BIT(4) | BIT(5))
+#define CESR_ICTE (BIT(6) | BIT(7))
+#define CESR_TLBMH BIT(16)
+#define CESR_I_MASK 0x000000cc
+/* Print a message for everything but TLB MH events */
+#define CESR_PRINT_MASK 0x000000ff
+
+#define L2ESR 0x204
+#define L2ESR_MPDCD BIT(0)
+#define L2ESR_MPSLV BIT(1)
+#define L2ESR_TSESB BIT(2)
+#define L2ESR_TSEDB BIT(3)
+#define L2ESR_DSESB BIT(4)
+#define L2ESR_DSEDB BIT(5)
+#define L2ESR_MSE BIT(6)
+#define L2ESR_MPLDREXNOK BIT(8)
+#define L2ESR_CPU_MASK 0xf
+#define L2ESR_CPU_SHIFT 16
+#define L2ESR_SP BIT(20)
+
+#define L2ESYNR0 0x208
+#define L2ESYNR1 0x209
+#define L2EAR0 0x20c
+#define L2EAR1 0x20d
+
+struct krait_edac {
+ int l1_irq;
+ struct edac_device_ctl_info * __percpu *edev;
+ struct notifier_block notifier;
+};
+
+struct krait_edac_error {
+ const char * const msg;
+ void (*func)(struct edac_device_ctl_info *edac_dev,
+ int inst_nr, int block_nr, const char *msg);
+};
+
+static unsigned int read_cesr(void)
+{
+ unsigned int cesr;
+
+ asm volatile ("mrc p15, 7, %0, c15, c0, 1 @ cesr" : "=r" (cesr));
+ return cesr;
+}
+
+static void write_cesr(unsigned int cesr)
+{
+ asm volatile ("mcr p15, 7, %0, c15, c0, 1 @ cesr" : : "r" (cesr));
+}
+
+static unsigned int read_cesynr(void)
+{
+ unsigned int cesynr;
+
+ asm volatile ("mrc p15, 7, %0, c15, c0, 3 @ cesynr" : "=r" (cesynr));
+ return cesynr;
+}
+
+static irqreturn_t krait_l1_irq(int irq, void *dev_id)
+{
+ struct edac_device_ctl_info **edac_p = dev_id;
+ struct edac_device_ctl_info *edac = *edac_p;
+ unsigned int cesr = read_cesr();
+ unsigned int i_cesynr, d_cesynr;
+ unsigned int cpu = smp_processor_id();
+ int print_regs = cesr & CESR_PRINT_MASK;
+ int i;
+ static const struct krait_edac_error errors[] = {
+ { "D-cache tag parity error", edac_device_handle_ue },
+ { "D-cache data parity error", edac_device_handle_ue },
+ { "I-cache tag parity error", edac_device_handle_ce },
+ { "I-cache data parity error", edac_device_handle_ce },
+ { "D-cache tag timing error", edac_device_handle_ue },
+ { "D-cache data timing error", edac_device_handle_ue },
+ { "I-cache tag timing error", edac_device_handle_ce },
+ { "I-cache data timing error", edac_device_handle_ce }
+ };
+
+ if (print_regs) {
+ pr_alert("L1 / TLB Error detected on CPU %d!\n", cpu);
+ pr_alert("CESR = 0x%08x\n", cesr);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(errors); i++)
+ if (BIT(i) & cesr)
+ errors[i].func(edac, cpu, 0, errors[i].msg);
+
+ if (cesr & CESR_TLBMH) {
+ asm ("mcr p15, 0, r0, c8, c7, 0");
+ edac_device_handle_ce(edac, cpu, 0, "TLB Multi-Hit error");
+ }
+
+ if (cesr & (CESR_ICTPE | CESR_ICDPE | CESR_ICTE)) {
+ i_cesynr = read_cesynr();
+ pr_alert("I-side CESYNR = 0x%08x\n", i_cesynr);
+ write_cesr(CESR_I_MASK);
+
+ /*
+ * Clear the I-side bits from the captured CESR value so that we
+ * don't accidentally clear any new I-side errors when we do
+ * the CESR write-clear operation.
+ */
+ cesr &= ~CESR_I_MASK;
+ }
+
+ if (cesr & (CESR_DCTPE | CESR_DCDPE | CESR_DCTE)) {
+ d_cesynr = read_cesynr();
+ pr_alert("D-side CESYNR = 0x%08x\n", d_cesynr);
+ }
+
+ /* Clear the interrupt bits we processed */
+ write_cesr(cesr);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t krait_l2_irq(int irq, void *dev_id)
+{
+ struct edac_device_ctl_info *edac = dev_id;
+ unsigned int l2esr;
+ unsigned int l2esynr0;
+ unsigned int l2esynr1;
+ unsigned int l2ear0;
+ unsigned int l2ear1;
+ unsigned long cpu;
+ int i;
+ static const struct krait_edac_error errors[] = {
+ { "master port decode error", edac_device_handle_ce },
+ { "master port slave error", edac_device_handle_ce },
+ { "tag soft error, single-bit", edac_device_handle_ce },
+ { "tag soft error, double-bit", edac_device_handle_ue },
+ { "data soft error, single-bit", edac_device_handle_ce },
+ { "data soft error, double-bit", edac_device_handle_ue },
+ { "modified soft error", edac_device_handle_ce },
+ { "slave port exclusive monitor not available",
+ edac_device_handle_ue},
+ { "master port LDREX received Normal OK response",
+ edac_device_handle_ce },
+ };
+
+ l2esr = krait_get_l2_indirect_reg(L2ESR);
+ pr_alert("Error detected!\n");
+ pr_alert("L2ESR = 0x%08x\n", l2esr);
+
+ if (l2esr & (L2ESR_TSESB | L2ESR_TSEDB | L2ESR_MSE | L2ESR_SP)) {
+ l2esynr0 = krait_get_l2_indirect_reg(L2ESYNR0);
+ l2esynr1 = krait_get_l2_indirect_reg(L2ESYNR1);
+ l2ear0 = krait_get_l2_indirect_reg(L2EAR0);
+ l2ear1 = krait_get_l2_indirect_reg(L2EAR1);
+
+ pr_alert("L2ESYNR0 = 0x%08x\n", l2esynr0);
+ pr_alert("L2ESYNR1 = 0x%08x\n", l2esynr1);
+ pr_alert("L2EAR0 = 0x%08x\n", l2ear0);
+ pr_alert("L2EAR1 = 0x%08x\n", l2ear1);
+ }
+
+ cpu = (l2esr >> L2ESR_CPU_SHIFT) & L2ESR_CPU_MASK;
+ cpu = __ffs(cpu);
+ if (cpu)
+ cpu--;
+ for (i = 0; i < ARRAY_SIZE(errors); i++)
+ if (BIT(i) & l2esr)
+ errors[i].func(edac, cpu, 1, errors[i].msg);
+
+ krait_set_l2_indirect_reg(L2ESR, l2esr);
+
+ return IRQ_HANDLED;
+}
+
+static void enable_l1_irq(void *info)
+{
+ const struct krait_edac *k = info;
+
+ enable_percpu_irq(k->l1_irq, IRQ_TYPE_LEVEL_HIGH);
+}
+
+static void disable_l1_irq(void *info)
+{
+ const struct krait_edac *k = info;
+
+ disable_percpu_irq(k->l1_irq);
+}
+
+static int
+krait_edac_notify(struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+ struct krait_edac *p = container_of(nfb, struct krait_edac, notifier);
+
+ switch (action & ~CPU_TASKS_FROZEN) {
+ case CPU_STARTING:
+ enable_l1_irq(p);
+ break;
+
+ case CPU_DYING:
+ disable_l1_irq(p);
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static int krait_edac_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct edac_device_ctl_info *edev;
+ struct krait_edac *p;
+ int l1_irq, l2_irq;
+ int ret, cpu;
+ struct device_node *node;
+
+ node = of_get_cpu_node(0, NULL);
+ if (!node)
+ return -ENODEV;
+
+ node = of_parse_phandle(node, "next-level-cache", 0);
+ if (!node)
+ return -ENODEV;
+
+ l2_irq = irq_of_parse_and_map(node, 0);
+ of_node_put(node);
+ if (l2_irq < 0)
+ return l2_irq;
+
+ l1_irq = platform_get_irq(pdev, 0);
+ if (l1_irq < 0)
+ return l1_irq;
+
+ p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, p);
+ p->l1_irq = l1_irq;
+
+ p->edev = alloc_percpu(struct edac_device_ctl_info *);
+ if (!p->edev)
+ return -ENOMEM;
+
+ edev = edac_device_alloc_ctl_info(0, "cpu", num_possible_cpus(),
+ "L", 2, 1, NULL, 0,
+ edac_device_alloc_index());
+ if (!edev) {
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+
+ edev->dev = dev;
+ edev->mod_name = dev_name(dev);
+ edev->dev_name = dev_name(dev);
+ edev->ctl_name = "cache";
+
+ for_each_possible_cpu(cpu)
+ *per_cpu_ptr(p->edev, cpu) = edev;
+
+ ret = edac_device_add_device(edev);
+ if (ret)
+ goto err_add;
+
+ ret = request_percpu_irq(l1_irq, krait_l1_irq, "L1 err",
+ p->edev);
+ if (ret)
+ goto err_l1_irq;
+
+ ret = devm_request_irq(dev, l2_irq, krait_l2_irq, 0, "L2 err",
+ edev);
+ if (ret)
+ goto err_l2_irq;
+
+ p->notifier.notifier_call = krait_edac_notify;
+ register_hotcpu_notifier(&p->notifier);
+ on_each_cpu(enable_l1_irq, p, true);
+
+ return 0;
+err_l2_irq:
+ free_percpu_irq(p->l1_irq, p->edev);
+err_l1_irq:
+ edac_device_del_device(dev);
+err_add:
+ edac_device_free_ctl_info(edev);
+err_alloc:
+ free_percpu(p->edev);
+ return ret;
+}
+
+static int krait_edac_remove(struct platform_device *pdev)
+{
+ struct krait_edac *p = platform_get_drvdata(pdev);
+
+ unregister_hotcpu_notifier(&p->notifier);
+ on_each_cpu(disable_l1_irq, p, true);
+ free_percpu_irq(p->l1_irq, p->edev);
+ edac_device_del_device(&pdev->dev);
+ edac_device_free_ctl_info(*__this_cpu_ptr(p->edev));
+ free_percpu(p->edev);
+
+ return 0;
+}
+
+static const struct of_device_id krait_edac_match_table[] = {
+ { .compatible = "qcom,krait" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, krait_edac_match_table);
+
+static struct platform_driver krait_edac_driver = {
+ .probe = krait_edac_probe,
+ .remove = krait_edac_remove,
+ .driver = {
+ .name = "krait_edac",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(krait_edac_match_table),
+ },
+};
+module_platform_driver(krait_edac_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Krait CPU cache error reporting driver");
+MODULE_ALIAS("platform:krait_edac");
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply related
* [PATCH v5 2/4] devicetree: bindings: Document Krait CPU/L1 EDAC
From: Stephen Boyd @ 2014-01-14 21:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389735034-21430-1-git-send-email-sboyd@codeaurora.org>
The Krait CPU/L1 error reporting device is made up a per-CPU
interrupt. While we're here, document the next-level-cache
property that's used by the Krait EDAC driver.
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: <devicetree@vger.kernel.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
Documentation/devicetree/bindings/arm/cpus.txt | 52 ++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index 91304353eea4..c332b5168456 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -191,6 +191,16 @@ nodes to be present and contain the properties described below.
property identifying a 64-bit zero-initialised
memory location.
+ - interrupts
+ Usage: required for cpus with compatible string "qcom,krait".
+ Value type: <prop-encoded-array>
+ Definition: L1/CPU error interrupt
+
+ - next-level-cache
+ Usage: optional
+ Value type: <phandle>
+ Definition: phandle pointing to the next level cache
+
Example 1 (dual-cluster big.LITTLE system 32-bit):
cpus {
@@ -382,3 +392,45 @@ cpus {
cpu-release-addr = <0 0x20000000>;
};
};
+
+
+Example 5 (Krait 32-bit system):
+
+cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <1 9 0xf04>;
+
+ cpu at 0 {
+ device_type = "cpu";
+ compatible = "qcom,krait";
+ reg = <0>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu at 1 {
+ device_type = "cpu";
+ compatible = "qcom,krait";
+ reg = <1>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu at 2 {
+ device_type = "cpu";
+ compatible = "qcom,krait";
+ reg = <2>;
+ next-level-cache = <&L2>;
+ };
+
+ cpu at 3 {
+ device_type = "cpu";
+ compatible = "qcom,krait";
+ reg = <3>;
+ next-level-cache = <&L2>;
+ };
+
+ L2: l2-cache {
+ compatible = "cache";
+ interrupts = <0 2 0x4>;
+ };
+};
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply related
* [PATCH v5 1/4] ARM: Add Krait L2 register accessor functions
From: Stephen Boyd @ 2014-01-14 21:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1389735034-21430-1-git-send-email-sboyd@codeaurora.org>
Krait CPUs have a handful of L2 cache controller registers that
live behind a cp15 based indirection register. First you program
the indirection register (l2cpselr) to point the L2 'window'
register (l2cpdr) at what you want to read/write. Then you
read/write the 'window' register to do what you want. The
l2cpselr register is not banked per-cpu so we must lock around
accesses to it to prevent other CPUs from re-pointing l2cpdr
underneath us.
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Courtney Cavin <courtney.cavin@sonymobile.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/common/Kconfig | 3 ++
arch/arm/common/Makefile | 1 +
arch/arm/common/krait-l2-accessors.c | 58 +++++++++++++++++++++++++++++++
arch/arm/include/asm/krait-l2-accessors.h | 20 +++++++++++
4 files changed, 82 insertions(+)
create mode 100644 arch/arm/common/krait-l2-accessors.c
create mode 100644 arch/arm/include/asm/krait-l2-accessors.h
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index c3a4e9ceba34..9da52dc6260b 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -9,6 +9,9 @@ config DMABOUNCE
bool
select ZONE_DMA
+config KRAIT_L2_ACCESSORS
+ bool
+
config SHARP_LOCOMO
bool
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 4bdc41622c36..2836f992ee5d 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -7,6 +7,7 @@ obj-y += firmware.o
obj-$(CONFIG_ICST) += icst.o
obj-$(CONFIG_SA1111) += sa1111.o
obj-$(CONFIG_DMABOUNCE) += dmabounce.o
+obj-$(CONFIG_KRAIT_L2_ACCESSORS) += krait-l2-accessors.o
obj-$(CONFIG_SHARP_LOCOMO) += locomo.o
obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o
obj-$(CONFIG_SHARP_SCOOP) += scoop.o
diff --git a/arch/arm/common/krait-l2-accessors.c b/arch/arm/common/krait-l2-accessors.c
new file mode 100644
index 000000000000..5d514bbc88a6
--- /dev/null
+++ b/arch/arm/common/krait-l2-accessors.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/export.h>
+
+#include <asm/barrier.h>
+#include <asm/krait-l2-accessors.h>
+
+static DEFINE_RAW_SPINLOCK(krait_l2_lock);
+
+void krait_set_l2_indirect_reg(u32 addr, u32 val)
+{
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&krait_l2_lock, flags);
+ /*
+ * Select the L2 window by poking l2cpselr, then write to the window
+ * via l2cpdr.
+ */
+ asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
+ isb();
+ asm volatile ("mcr p15, 3, %0, c15, c0, 7 @ l2cpdr" : : "r" (val));
+ isb();
+
+ raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
+}
+EXPORT_SYMBOL(krait_set_l2_indirect_reg);
+
+u32 krait_get_l2_indirect_reg(u32 addr)
+{
+ u32 val;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&krait_l2_lock, flags);
+ /*
+ * Select the L2 window by poking l2cpselr, then read from the window
+ * via l2cpdr.
+ */
+ asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
+ isb();
+ asm volatile ("mrc p15, 3, %0, c15, c0, 7 @ l2cpdr" : "=r" (val));
+
+ raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
+
+ return val;
+}
+EXPORT_SYMBOL(krait_get_l2_indirect_reg);
diff --git a/arch/arm/include/asm/krait-l2-accessors.h b/arch/arm/include/asm/krait-l2-accessors.h
new file mode 100644
index 000000000000..48fe5527bc01
--- /dev/null
+++ b/arch/arm/include/asm/krait-l2-accessors.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASMARM_KRAIT_L2_ACCESSORS_H
+#define __ASMARM_KRAIT_L2_ACCESSORS_H
+
+extern void krait_set_l2_indirect_reg(u32 addr, u32 val);
+extern u32 krait_get_l2_indirect_reg(u32 addr);
+
+#endif
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox