* [PATCH v5 4/4] net: dsa: LAN9303: add MDIO managed mode support
From: Juergen Borleis @ 2017-04-13 7:33 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
f.fainelli-Re5JQEeQqe8AvxtiuMwx3w, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
andrew-g2DYL2Zd6BY,
vivien.didelot-4ysUXcep3aM1wj+D4I0NRVaTQe2KTcn/,
davem-fT/PcQaiUtIeIZ0/mPfg9Q, devicetree-u79uwXL29TY76Z2rM5mHXA,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8
In-Reply-To: <20170413073343.8067-1-jbe-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
When the LAN9303 device is in MDIO manged mode, all register accesses must
be done via MDIO.
Please note: this code is compile time tested only due to the absence of such
configured hardware. It is based on a patch from Stefan Roese from 2014.
Signed-off-by: Juergen Borleis <jbe-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
Reviewed-by: Andrew Lunn <andrew-g2DYL2Zd6BY@public.gmane.org>
CC: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
CC: robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
CC: mark.rutland-5wv7dgnIgG8@public.gmane.org
---
.../devicetree/bindings/net/dsa/lan9303.txt | 45 ++++++-
drivers/net/dsa/Kconfig | 8 ++
drivers/net/dsa/Makefile | 1 +
drivers/net/dsa/lan9303_mdio.c | 144 +++++++++++++++++++++
4 files changed, 197 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/dsa/lan9303_mdio.c
diff --git a/Documentation/devicetree/bindings/net/dsa/lan9303.txt b/Documentation/devicetree/bindings/net/dsa/lan9303.txt
index 2edc2561467a7..04f2965a44676 100644
--- a/Documentation/devicetree/bindings/net/dsa/lan9303.txt
+++ b/Documentation/devicetree/bindings/net/dsa/lan9303.txt
@@ -3,7 +3,10 @@ SMSC/MicroChip LAN9303 three port ethernet switch
Required properties:
-- compatible: should be "smsc,lan9303-i2c"
+- compatible: should be
+ - "smsc,lan9303-i2c" for I2C managed mode
+ or
+ - "smsc,lan9303-mdio" for mdio managed mode
Optional properties:
@@ -60,3 +63,43 @@ I2C managed mode:
};
};
};
+
+MDIO managed mode:
+
+ master: masterdevice@X {
+ status = "okay";
+ phy-handle = <&switch>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ switch: switch-phy@0 {
+ compatible = "smsc,lan9303-mdio";
+ reg = <0>;
+ reset-gpios = <&gpio7 6 GPIO_ACTIVE_LOW>;
+ reset-duration = <100>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ label = "cpu";
+ ethernet = <&master>;
+ };
+
+ port@1 { /* external port 1 */
+ reg = <1>;
+ label = "lan1;
+ };
+
+ port@2 { /* external port 2 */
+ reg = <2>;
+ label = "lan2";
+ };
+ };
+ };
+ };
+ };
diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index 83887c68ef7a3..e52b298853474 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -67,4 +67,12 @@ config NET_DSA_SMSC_LAN9303_I2C
Enable access functions if the SMSC/Microchip LAN9303 is configured
for I2C managed mode.
+config NET_DSA_SMSC_LAN9303_MDIO
+ bool "MDIO managed mode"
+ depends on NET_DSA_SMSC_LAN9303
+ depends on OF_MDIO
+ ---help---
+ Enable access functions if the SMSC/Microchip LAN9303 is configured
+ for MDIO managed mode.
+
endmenu
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index e626aeba8525e..e782d9648bc8c 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -1,5 +1,6 @@
lan9303-objs-y := lan9303-core.o
lan9303-objs-$(CONFIG_NET_DSA_SMSC_LAN9303_I2C) += lan9303_i2c.o
+lan9303-objs-$(CONFIG_NET_DSA_SMSC_LAN9303_MDIO) += lan9303_mdio.o
obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
obj-$(CONFIG_NET_DSA_BCM_SF2) += bcm-sf2.o
diff --git a/drivers/net/dsa/lan9303_mdio.c b/drivers/net/dsa/lan9303_mdio.c
new file mode 100644
index 0000000000000..87c5cfa946a92
--- /dev/null
+++ b/drivers/net/dsa/lan9303_mdio.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2017 Pengutronix, Juergen Borleis <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
+ *
+ * Partially based on a patch from
+ * Copyright (c) 2014 Stefan Roese <sr-ynQEQJNshbs@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mdio.h>
+#include <linux/phy.h>
+#include <linux/of.h>
+
+#include "lan9303.h"
+
+/* Generate phy-addr and -reg from the input address */
+#define PHY_ADDR(x) ((((x) >> 6) + 0x10) & 0x1f)
+#define PHY_REG(x) (((x) >> 1) & 0x1f)
+
+struct lan9303_mdio {
+ struct mdio_device *device;
+ struct lan9303 chip;
+};
+
+static void lan9303_mdio_real_write(struct mdio_device *mdio, int reg, u16 val)
+{
+ mdio->bus->write(mdio->bus, PHY_ADDR(reg), PHY_REG(reg), val);
+}
+
+static int lan9303_mdio_write(void *ctx, uint32_t reg, uint32_t val)
+{
+ struct lan9303_mdio *sw_dev = (struct lan9303_mdio *)ctx;
+
+ mutex_lock(&sw_dev->device->bus->mdio_lock);
+ lan9303_mdio_real_write(sw_dev->device, reg, val & 0xffff);
+ lan9303_mdio_real_write(sw_dev->device, reg + 2, (val >> 16) & 0xffff);
+ mutex_unlock(&sw_dev->device->bus->mdio_lock);
+
+ return 0;
+}
+
+static u16 lan9303_mdio_real_read(struct mdio_device *mdio, int reg)
+{
+ return mdio->bus->read(mdio->bus, PHY_ADDR(reg), PHY_REG(reg));
+}
+
+static int lan9303_mdio_read(void *ctx, uint32_t reg, uint32_t *val)
+{
+ struct lan9303_mdio *sw_dev = (struct lan9303_mdio *)ctx;
+
+ mutex_lock(&sw_dev->device->bus->mdio_lock);
+ *val = lan9303_mdio_real_read(sw_dev->device, reg);
+ *val |= (lan9303_mdio_real_read(sw_dev->device, reg + 2) << 16);
+ mutex_unlock(&sw_dev->device->bus->mdio_lock);
+
+ return 0;
+}
+
+static const struct regmap_config lan9303_mdio_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 32,
+ .reg_stride = 1,
+ .can_multi_write = true,
+ .max_register = 0x0ff, /* address bits 0..1 are not used */
+ .reg_format_endian = REGMAP_ENDIAN_LITTLE,
+
+ .volatile_table = &lan9303_register_set,
+ .wr_table = &lan9303_register_set,
+ .rd_table = &lan9303_register_set,
+
+ .reg_read = lan9303_mdio_read,
+ .reg_write = lan9303_mdio_write,
+
+ .cache_type = REGCACHE_NONE,
+};
+
+static int lan9303_mdio_probe(struct mdio_device *mdiodev)
+{
+ struct lan9303_mdio *sw_dev;
+ int ret;
+
+ sw_dev = devm_kzalloc(&mdiodev->dev, sizeof(struct lan9303_mdio),
+ GFP_KERNEL);
+ if (!sw_dev)
+ return -ENOMEM;
+
+ sw_dev->chip.regmap = devm_regmap_init(&mdiodev->dev, NULL, sw_dev,
+ &lan9303_mdio_regmap_config);
+ if (IS_ERR(sw_dev->chip.regmap)) {
+ ret = PTR_ERR(sw_dev->chip.regmap);
+ dev_err(&mdiodev->dev, "regmap init failed: %d\n", ret);
+ return ret;
+ }
+
+ /* link forward and backward */
+ sw_dev->device = mdiodev;
+ dev_set_drvdata(&mdiodev->dev, sw_dev);
+ sw_dev->chip.dev = &mdiodev->dev;
+
+ ret = lan9303_probe(&sw_dev->chip, mdiodev->dev.of_node);
+ if (ret != 0)
+ return ret;
+
+ dev_info(&mdiodev->dev, "LAN9303 MDIO driver loaded successfully\n");
+
+ return 0;
+}
+
+static void lan9303_mdio_remove(struct mdio_device *mdiodev)
+{
+ struct lan9303_mdio *sw_dev = dev_get_drvdata(&mdiodev->dev);
+
+ if (!sw_dev)
+ return;
+
+ lan9303_remove(&sw_dev->chip);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static const struct of_device_id lan9303_mdio_of_match[] = {
+ { .compatible = "smsc,lan9303-mdio" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, lan9303_mdio_of_match);
+
+static struct mdio_driver lan9303_mdio_driver = {
+ .mdiodrv.driver = {
+ .name = "LAN9303_MDIO",
+ .of_match_table = of_match_ptr(lan9303_mdio_of_match),
+ },
+ .probe = lan9303_mdio_probe,
+ .remove = lan9303_mdio_remove,
+};
+mdio_module_driver(lan9303_mdio_driver);
--
2.11.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH v5 1/4] gpio: mvebu: Add limited PWM support
From: Ralph Sennhauser @ 2017-04-13 7:45 UTC (permalink / raw)
To: Thierry Reding
Cc: Andrew Lunn, Linus Walleij, Alexandre Courbot, Rob Herring,
Mark Rutland, Jason Cooper, Gregory Clement,
Sebastian Hesselbarth, Russell King, linux-pwm, linux-gpio,
devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20170412171121.GB11964@ulmo.ba.sec>
On Wed, 12 Apr 2017 19:11:21 +0200
Thierry Reding <thierry.reding@gmail.com> wrote:
> On Sun, Apr 09, 2017 at 08:09:27PM +0200, Ralph Sennhauser wrote:
> > From: Andrew Lunn <andrew@lunn.ch>
> >
> > Armada 370/XP devices can 'blink' GPIO lines with a configurable on
> > and off period. This can be modelled as a PWM.
> >
> > However, there are only two sets of PWM configuration registers for
> > all the GPIO lines. This driver simply allows a single GPIO line per
> > GPIO chip of 32 lines to be used as a PWM. Attempts to use more
> > return EBUSY.
> >
> > Due to the interleaving of registers it is not simple to separate
> > the PWM driver from the GPIO driver. Thus the GPIO driver has been
> > extended with a PWM driver.
> >
> > Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> > URL: https://patchwork.ozlabs.org/patch/427287/
> > URL: https://patchwork.ozlabs.org/patch/427295/
> > [Ralph Sennhauser:
> > * Port forward
> > * Merge PWM portion into gpio-mvebu.c
> > * Switch to atomic PWM API
> > * Add new compatible string marvell,armada-370-xp-gpio
> > * Update and merge documentation patch
> > * Update MAINTAINERS]
> > Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
> > Tested-by: Andrew Lunn <andrew@lunn.ch>
> > ---
> > .../devicetree/bindings/gpio/gpio-mvebu.txt | 32 ++
> > MAINTAINERS | 2 +
> > drivers/gpio/gpio-mvebu.c | 324
> > ++++++++++++++++++++- 3 files changed, 346 insertions(+), 12
> > deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
> > b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt index
> > a6f3bec..fe49e9d 100644 ---
> > a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt +++
> > b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt @@ -38,6
> > +38,24 @@ Required properties:
> > - #gpio-cells: Should be two. The first cell is the pin number. The
> > second cell is reserved for flags, unused at the moment.
> >
> > +Optional properties:
> > +
> > +In order to use the gpio lines in PWM mode, some additional
> > optional +properties are required. Only Armada 370 and XP support
> > these properties. +
> > +- compatible: Must contain "marvell,armada-370-xp-gpio"
> > +
> > +- reg: an additional register set is needed, for the GPIO Blink
> > + Counter on/off registers.
> > +
> > +- reg-names: Must contain an entry "pwm" corresponding to the
> > + additional register range needed for pwm operation.
> > +
> > +- #pwm-cells: Should be two. The first cell is the GPIO line
> > number. The
> > + second cell is the period in nanoseconds.
> > +
> > +- clocks: Must be a phandle to the clock for the gpio controller.
> > +
> > Example:
> >
> > gpio0: gpio@d0018100 {
> > @@ -51,3 +69,17 @@ Example:
> > #interrupt-cells = <2>;
> > interrupts = <16>, <17>, <18>, <19>;
> > };
> > +
> > + gpio1: gpio@18140 {
> > + compatible = "marvell,armada-370-xp-gpio";
> > + reg = <0x18140 0x40>, <0x181c8 0x08>;
> > + reg-names = "gpio", "pwm";
> > + ngpios = <17>;
> > + gpio-controller;
> > + #gpio-cells = <2>;
> > + #pwm-cells = <2>;
> > + interrupt-controller;
> > + #interrupt-cells = <2>;
> > + interrupts = <87>, <88>, <89>;
> > + clocks = <&coreclk 0>;
> > + };
>
> This is going to need an Acked-by from one of the device tree
> maintainers. Rob and devicetree@vger.kernel.org are on Cc, but I
> suspect nobody might look for the binding change "hidden" in this
> patch.
>
> Maybe best to split this off into a separate patch, or explicitly ping
> Rob to look at this patch.
Hi Thierry,
Rob asked for the new compatible string so he did see it presumably. As
you prefer to have an ACK by him I'll see to getting one for the driver
(bindings part). The patch could be split but then one might want to
split it even further. Like this the first patch in the series is a nice
self contained package.
>
<snip/>
>
> > +
> > + mvpwm->clk_rate = clk_get_rate(mvchip->clk);
> > + if (!mvpwm->clk_rate) {
> > + dev_err(dev, "failed to get clock rate\n");
> > + return -EINVAL;
> > + }
> > +
> > + mvpwm->chip.dev = dev;
> > + mvpwm->chip.ops = &mvebu_pwm_ops;
> > + mvpwm->chip.base = mvchip->chip.base;
> > + mvpwm->chip.npwm = mvchip->chip.ngpio;
>
> I still would've done this differently. If you use this with a PWM
> user you have to hook it up via DT anyway, so it doesn't matter
> whether you specify the PWM index or the GPIO via some other
> property. The _only_ use-case where this might actually be an
> advantage is if you request a PWM via the sysfs interface.
Let me answer this in the other mail where you bring this up.
>
<snip/>
> All of my comments are effectively of a bikeshed nature, so from a PWM
> perspective this is:
>
> Acked-by: Thierry Reding <thierry.reding@gmail.com>
Thanks for the detailed review and the ACK. Will work on all the
mentioned bits for v6.
Ralph
^ permalink raw reply
* Re: [PATCH v5 0/4] gpio: mvebu: Add PWM fan support
From: Ralph Sennhauser @ 2017-04-13 7:49 UTC (permalink / raw)
To: Thierry Reding
Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
Jason Cooper, Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
Russell King, linux-pwm-u79uwXL29TY76Z2rM5mHXA,
linux-gpio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170412171656.GC11964-EkSeR96xj6Pcmrwk2tT4+A@public.gmane.org>
On Wed, 12 Apr 2017 19:16:56 +0200
Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Sun, Apr 09, 2017 at 08:09:26PM +0200, Ralph Sennhauser wrote:
> > Hi Therry,
> >
> > Resending this as v5 with some minor changes since v4. What is
> > missing is an ACK from you so Linus can merge the driver and
> > Gregory the dts changes. For this driver to make it into 4.12 it
> > would be nice to have it in next soon. I hope you can make some
> > room in your schedule to have another look at this series.
> >
> > Thanks
> > Ralph
> >
> > ---
> >
> > Notes:
> >
> > About npwm = 1:
> > The only way I can think of to achieve that requires reading the
> > GPIO line from the device tree. This would prevent a user to
> > dynamically choose a line. Which is fine for the fan found on
> > Mamba but let's take some development board with freely accessible
> > GPIOs and suddenly we limit the use of this driver. Given the
> > above, npwm = ngpio with only one usable at a time is a more
> > accurate
>
> I think "accurate" is perhaps not the word I'd choose. "npwm" is
> defined as "number of PWMs controlled by this chip", and that's
> effectively just the one. It's implied that all PWMs exposed by a
> chip can be used concurrently.
I'm not native English so some terms might be off a tad in how I use
them, replace accurate with what you think I meant ;).
The "it's implied" sounds like a contract and EBUSY a violation thereof.
>
> Anyway, I can see how npwm = ngpio might be more convenient, and if
> that is what you want to do, I don't feel strongly enough to object.
The goal is a pwm-fan driver for Mamba. So npwm=1 would work just fine
from that stand point. It's indeed the sysfs case I had in mind which
would be hampered. Whether to consider that one valid / desirable I
don't want to judge. For me it's a hypothetical use case for others it
might be real.
For this series I want just this one device to work and getting the
bindings right to not prevent others extending the driver later when
they need.
The driver which is under rework here is in use for 2 years, so I went
with the feature set provided by it which is more than I need. It's a
one of it's kind driver and I only have this single use case, so really
your call.
Thanks
Ralph
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: Document STM32 I2S bindings
From: Olivier MOYSAN @ 2017-04-13 8:01 UTC (permalink / raw)
To: Mark Brown
Cc: mark.rutland@arm.com, Rob Herring, alsa-devel@alsa-project.org,
Alexandre TORGUE, devicetree@vger.kernel.org, Arnaud POULIQUEN,
tiwai@suse.com, lgirdwood@gmail.com, mcoquelin.stm32@gmail.com,
perex@perex.cz, linux-arm-kernel@lists.infradead.org,
Benjamin GAIGNARD
In-Reply-To: <20170412153831.r2urwvfseipfsrsi@sirena.org.uk>
Hello Mark,
On 04/12/2017 05:38 PM, Mark Brown wrote:
> On Wed, Apr 12, 2017 at 12:58:16PM +0000, Olivier MOYSAN wrote:
>> On 04/12/2017 01:32 PM, Mark Brown wrote:
>
>>> It is totally normal to just not use one direction in a given system, we
>>> don't normally need to do anything special to handle things. I'm a bit
>>> confused as to what's different here and needs configuring?
>
>> The IP does not provide an audio channel configured either as rx or tx.
>> I agree, that in such case, the cpu driver does not generally need
>> to worry about direction and there is nothing special required to handle it.
>
> No, that's not what I'm saying - such hardware would be extremely
> unusual.
>
>> Here the IP provides 2 channels, 1 tx and 1 rx, which may be active or
>> not. The driver has to know which channel is used, and if both channels
>> have to be managed. The affected registers depend on selected channel.
>
> This sounds like essentially every audio controller out there. The
> overwhelming majority of controllers do exactly as you describe and have
> both directions in the same IP, this really doesn't seem at all unusual.
> Off the top of my head I can only think of one SoC family which combines
> multiple IPs to do bidirectional audio (though I didn't check).
>
> It really feels like there is something different here and I'm just
> missing it.
>
Yes, I think I need to give more details on design choices.
The IP provides 2 channels.
I can see mainly 3 solutions to link dais to these channels:
1) 2 static dais NOT exclusive
- dai tx
- dai rx
The IP exhibits a mode register, where you select mode TX, RX or FD.
There are 2 two options to manage this register.
option 1:
start first channel with mode RX or TX
when second channel is started, mode has to be changed to FD.
Transfers have to be stopped before changing configuration
registers, so this leads to cuts in audio stream.
option 2:
start a first channel with mode FD.
In this case, we may have unpredictable behavior for the stream
which is not already started. probably underrun/overrun.
So, this solution rises problem for full-duplex management.
2) 3 static dais exclusive
- dai tx
- dai rx
- dai rx-tx (fd)
This is the current implementation.
The choice of the dai is done at probe time. It is provided by DT
through sound-dai parameter.
When dai fd is selected, after starting first stream, we assume that
second stream will be started. In this case we wait for second stream
to be available before enabling IP and starting transfers.
3) 1 dynamic dai
- dai rx or tx or fd (according to dma conf in IP node)
Here the driver exposes only a single dai constructed from dma
configuration provided by IP DT node.
This allows to get ride of sound-dai parameter.
This was my suggestion after Rob comments on DT bindings.
Hope this will help clarifying design constraints.
>> Moreover specific processing has to be performed if both channels are used.
>
> Given that this case has to be supported anyway I'd be more inclined to
> ask the question the other way around TBH.
>
Best regards
olivier
^ permalink raw reply
* Re: [PATCH v3] arm64: dts: rk3399: add support for firefly-rk3399 board
From: Heiko Stübner @ 2017-04-13 8:22 UTC (permalink / raw)
To: Kever Yang
Cc: linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Jianqun Xu, Liang Chen,
Brian Norris, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Andy Yan,
Rob Herring, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Will Deacon, Mark Rutland, Catalin Marinas, Matthias Brugger
In-Reply-To: <6d1eb0cc-fe3b-a483-123c-8558096c0846-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
Am Donnerstag, 13. April 2017, 12:00:19 CEST schrieb Kever Yang:
> Hi Heiko,
>
> On 04/12/2017 09:29 PM, Heiko Stuebner wrote:
> > Hi Kever,
> >
> > Am Montag, 10. April 2017, 11:50:13 CEST schrieb Kever Yang:
> >> Firefly-rk3399 is a bord from T-Firefly, you can find detail about
> >> it here:
> >> http://en.t-firefly.com/en/firenow/Firefly_RK3399/
> >>
> >> This patch add basic node for the board and make it able to bring
> >> up.
> >>
> >> Peripheral works:
> >> - usb hub which connect to ehci controller;
> >> - UART2 debug
> >> - eMMC
> >> - PCIe
> >>
> >> Not work:
> >> - USB 3.0 HOST, type-C port
> >> - sdio, sd-card
> >>
> >> Not test for other peripheral:
> >> - HDMI
> >> - Ethernet
> >> - OPTICAL
> >> - WiFi/BT
> >> - MIPI CSI/DSI
> >> - IR
> >> - EDP/DP
> >>
> >> Signed-off-by: Kever Yang <kever.yang-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
> >
> > applied for 4.13, as we're a bit late for 4.12, with the following
changes:
> Thanks for your help, I'm not familiar with the devices status on upstream
> because not working on kernel upstream for a long time.
>
> > - commit subject
> > - dropped status from backlight (as there is no disabled common node
> >
> > and it's specific to the firefly itself)
> >
> > - quite some reordering of properties
> > - reordered regulator nodes per their addresses: 0x1b < 0x40
> > - dropped obsolete regulator-compatible properties
> > - fixed gpio-irq on the mpu6500
> > - dropped out-of-tree orientation properties of mpu6500
> >
> > --> please provide the optional "mount-matrix" in a follow-up patch
> >
> > see bindings/iio/imu/inv_mpu6050.txt
>
> Maybe we can drop this mpu6050 node first? I can't find binding file for it.
The binding (and driver in the kernel) is the same as for the mpu6050.
So you can find the documentation in
Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt
Someone should add the other ids from
drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
to the binding.
mount-matrix is optional, so the basic node itself can stay in the dt.
Heiko
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH v1 1/1] mtd: mtk-nor: set controller's address width according to nor flash
From: Cyrille Pitchen @ 2017-04-13 8:24 UTC (permalink / raw)
To: Guochun Mao
Cc: Cyrille Pitchen, Mark Rutland, devicetree, Richard Weinberger,
Russell King, linux-kernel, Rob Herring, linux-mtd,
Matthias Brugger, linux-mediatek, David Woodhouse,
linux-arm-kernel
In-Reply-To: <1492051237.2866.36.camel@mhfsdcap03>
Hi Guochun,
Le 13/04/2017 à 04:40, Guochun Mao a écrit :
> Hi Cyrille,
>
> On Wed, 2017-04-12 at 22:57 +0200, Cyrille Pitchen wrote:
>> Hi Guochun,
>>
>> Le 05/04/2017 à 10:37, Guochun Mao a écrit :
>>> When nor's size larger than 16MByte, nor's address width maybe
>>> set to 3 or 4, and controller should change address width according
>>> to nor's setting.
>>>
>>> Signed-off-by: Guochun Mao <guochun.mao@mediatek.com>st
Acked-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
>>> ---
>>> drivers/mtd/spi-nor/mtk-quadspi.c | 27 +++++++++++++++++++++++++++
>>> 1 file changed, 27 insertions(+)
>>>
>>> diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/mtk-quadspi.c
>>> index e661877..b637770 100644
>>> --- a/drivers/mtd/spi-nor/mtk-quadspi.c
>>> +++ b/drivers/mtd/spi-nor/mtk-quadspi.c
>>> @@ -104,6 +104,8 @@
>>> #define MTK_NOR_MAX_RX_TX_SHIFT 6
>>> /* can shift up to 56 bits (7 bytes) transfer by MTK_NOR_PRG_CMD */
>>> #define MTK_NOR_MAX_SHIFT 7
>>> +/* nor controller 4-byte address mode enable bit */
>>> +#define MTK_NOR_4B_ADDR_EN BIT(4)
>>>
>>> /* Helpers for accessing the program data / shift data registers */
>>> #define MTK_NOR_PRG_REG(n) (MTK_NOR_PRGDATA0_REG + 4 * (n))
>>> @@ -230,10 +232,35 @@ static int mt8173_nor_write_buffer_disable(struct mt8173_nor *mt8173_nor)
>>> 10000);
>>> }
>>>
>>> +static void mt8173_nor_set_addr_width(struct mt8173_nor *mt8173_nor)
>>> +{
>>> + u8 val;
>>> + struct spi_nor *nor = &mt8173_nor->nor;
>>> +
>>> + val = readb(mt8173_nor->base + MTK_NOR_DUAL_REG);
>>> +
>>> + switch (nor->addr_width) {
>>> + case 3:
>>> + val &= ~MTK_NOR_4B_ADDR_EN;
>>> + break;
>>> + case 4:
>>> + val |= MTK_NOR_4B_ADDR_EN;
>>> + break;
>>> + default:
>>> + dev_warn(mt8173_nor->dev, "Unexpected address width %u.\n",
>>> + nor->addr_width);
>>> + break;
>>> + }
>>> +
>>> + writeb(val, mt8173_nor->base + MTK_NOR_DUAL_REG);
>>> +}
>>> +
>>> static void mt8173_nor_set_addr(struct mt8173_nor *mt8173_nor, u32 addr)
>>> {
>>> int i;
>>>
>>> + mt8173_nor_set_addr_width(mt8173_nor);
>>> +
>>> for (i = 0; i < 3; i++) {
>>
>> Should it be 'i < nor->addr_width' instead of 'i < 3' ?
>> Does it work when accessing data after 128Mbit ?
>
> Yes, it can work.
>
> Let's see the whole function,
>
> static void mt8173_nor_set_addr(struct mt8173_nor *mt8173_nor, u32 addr)
> {
> int i;
>
> mt8173_nor_set_addr_width(mt8173_nor);
>
> for (i = 0; i < 3; i++) {
> writeb(addr & 0xff, mt8173_nor->base + MTK_NOR_RADR0_REG
> + i * 4);
> addr >>= 8;
> }
> /* Last register is non-contiguous */
> writeb(addr & 0xff, mt8173_nor->base + MTK_NOR_RADR3_REG);
> }
>
> The nor controller has 4 registers for address.
> This '3' indicates the number of contiguous address' registers
> base + MTK_NOR_RADR0_REG(0x10)
> base + MTK_NOR_RADR1_REG(0x14)
> base + MTK_NOR_RADR2_REG(0x18),
> but the last address register is non-contiguous,
> it's base + MTK_NOR_RADR3_REG(0xc8)
>
> mt8173_nor_set_addr will set addr into these 4 registers by Byte.
> The bit MTK_NOR_4B_ADDR_EN will decide whether 3-byte(0x10,0x14,0x18)
> or 4-byte(0x10,0x14,x018,0xc8) been sent to nor device.
> and, it can access data after 128Mbit when sent 4-byte address.
Indeed, you're right. Sorry for the noise!
>
> Best regards,
>
> Guochun
>
>>
>> Best regards,
>>
>> Cyrille
>>
>>> writeb(addr & 0xff, mt8173_nor->base + MTK_NOR_RADR0_REG + i * 4);
>>> addr >>= 8;
>>>
>>
>
>
>
^ permalink raw reply
* Re: [PATCHv4 0/2] Nokia H4+ support
From: Marcel Holtmann @ 2017-04-13 8:33 UTC (permalink / raw)
To: Sebastian Reichel
Cc: Gustavo F. Padovan, Johan Hedberg, Rob Herring, Pavel Machek,
Linux Bluetooth, devicetree, linux-kernel
In-Reply-To: <20170413002659.25821-1-sre@kernel.org>
Hi Sebastian,
> Here is the fourth revision of the nokia bluetooth patchset. Compared
> to the previous one the following things have changed:
>
> * Drop patch 1-8 (applied by Marcel) and update Cc/To for patchset
> * Order includes in the driver alphabetically
> * Explicitly include <linux/of.h> in the nokia bluetooth driver
>
> -- Sebastian
>
> Sebastian Reichel (2):
> dt-bindings: net: bluetooth: Add nokia-bluetooth
> Bluetooth: add nokia driver
both patches have been applied to bluetooth-next tree.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH 2/2] hwrng: mtk: Add driver for hardware random generator on MT7623 SoC
From: PrasannaKumar Muralidharan @ 2017-04-13 8:39 UTC (permalink / raw)
To: sean.wang
Cc: Herbert Xu, Matt Mackall, Rob Herring, Mark Rutland,
Corentin LABBE, Romain Perier, shannon.nelson, Wei Yongjun,
devicetree, linux-crypto, linux-mediatek, linux-arm-kernel,
linux-kernel, keyhaede
In-Reply-To: <1492067108-14748-3-git-send-email-sean.wang@mediatek.com>
Hi Sean,
Mostly looks good, have few minor comments.
On 13 April 2017 at 12:35, <sean.wang@mediatek.com> wrote:
> +static bool mtk_rng_wait_ready(struct hwrng *rng, bool wait)
> +{
> + struct mtk_rng *priv = to_mtk_rng(rng);
> + int ready;
> +
> + ready = readl(priv->base + RNG_CTRL) & RNG_READY;
> + if (!ready && wait)
> + readl_poll_timeout_atomic(priv->base + RNG_CTRL, ready,
> + ready & RNG_READY, USEC_POLL,
> + TIMEOUT_POLL);
> + return !!ready;
> +}
Use readl_poll_timeout_atomic's return value or -EIO instead of
!!ready. This will simplify mtk_rng_read.
> +static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
> +{
> + struct mtk_rng *priv = to_mtk_rng(rng);
> + int retval = 0;
> +
> + while (max >= sizeof(u32)) {
> + if (!mtk_rng_wait_ready(rng, wait))
> + break;
> +
> + *(u32 *)buf = readl(priv->base + RNG_DATA);
> + retval += sizeof(u32);
> + buf += sizeof(u32);
> + max -= sizeof(u32);
> + }
> +
> + if (unlikely(wait && max))
> + dev_warn(priv->dev, "timeout might be not properly set\n");
Is this really necessary? Better to choose proper timeout than
providing this warning message. In rare cases if the timeout could
occur due to some reason (may be a hardware fault) print appropriate
warning message.
> + return retval || !wait ? retval : -EIO;
> +}
Set retavl to mtk_rng_wait_ready and return retval.
Regards,
Prasanna
^ permalink raw reply
* Re: [PATCH 1/2] mfd: arizona: Add GPIO maintain state flag
From: Charles Keepax @ 2017-04-13 9:15 UTC (permalink / raw)
To: Richard Fitzgerald
Cc: Rob Herring, linus.walleij, lee.jones, gnurou, mark.rutland,
linux-gpio, devicetree, linux-kernel, patches
In-Reply-To: <1491903267.4826.8.camel@rf-debian.wolfsonmicro.main>
On Tue, Apr 11, 2017 at 10:34:27AM +0100, Richard Fitzgerald wrote:
> On Mon, 2017-04-10 at 15:17 -0500, Rob Herring wrote:
> > On Fri, Apr 07, 2017 at 01:38:44PM +0100, Charles Keepax wrote:
> > > The Arizona devices only maintain the state of output GPIOs whilst the
> > > CODEC is active, this can cause issues if the CODEC suspends whilst
> > > something is relying on the state of one of its GPIOs. However, in
> > > many systems the CODEC GPIOs are used for audio related features
> > > and thus the state of the GPIOs is unimportant whilst the CODEC is
> > > suspended. Often keeping the CODEC resumed in such a system would
> > > incur a power impact that is unacceptable.
> > >
> > > Add a flag through the second cell of the GPIO specifier in device
> > > tree, to allow the user to select whether a GPIO being configured as
> > > an output should keep the CODEC resumed.
> >
> > If the whole codec can't be suspended, why does this need to be per
> > GPIO? You could just have a single boolean property.
> >
>
> Three reasons I can think of:
>
> 1) The GPIO binding already provides for passing extra information
> through the binding ("Exact meaning of each specifier cell is controller
> specific" as it says in the main gpio binding doc) so why add yet
> another custom property to do it?
>
> 2) Doing it through the gpio means that if ultimately the child DT node
> that is using it gets disabled (status="disabled") or that driver isn't
> in use the codec will be able to go to sleep. That won't happen with a
> brute-force "big lock".
>
> 3) The codec only has to be kept awake while any such GPIO is actually
> in use. See (2)
>
Yeah option 3 is the primary issue here, we only want to keep the
CODEC enabled whilst specific GPIOs are in use. As GPIOs can be
dynamically requested/released by things in the kernel we want to
know which GPIOs require the CODEC to be kept alive. Also in the
future one might be tempted to add maintain whilst high and
maintain whilst low options for lines with pulls on them to
further optimise power.
Thanks,
Charles
^ permalink raw reply
* Re: [PATCH] [media] imx: csi: retain current field order and colorimetry setting as default
From: Philipp Zabel @ 2017-04-13 10:07 UTC (permalink / raw)
To: Hans Verkuil
Cc: Steve Longerbeam, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, shawnguo-DgEjT+Ai2ygdnm+yROfE0A,
kernel-bIcnvbaLZ9MEGnE8C9+IrQ, fabio.estevam-3arQi8VN3Tc,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, mchehab-DgEjT+Ai2ygdnm+yROfE0A,
nick-gcszYUEDH4VrovVCs/uTlw, markus.heiser-O6JHGLzbNUwb1SvskN2V4Q,
laurent.pinchart+renesas-ryLnwIuWjnjg/C1BVhZhaw,
bparrot-l0cyMroinI0, geert-Td1EMuHUCqxL1ZNQvxDV9g,
arnd-r2nGTMty4D4, sudipm.mukherjee-Re5JQEeQqe8AvxtiuMwx3w,
minghsiu.tsai-NuS5LvNUpcJWk0Htik3J/w,
tiffany.lin-NuS5LvNUpcJWk0Htik3J/w,
jean-christophe.trotin-qxv4g6HH51o,
horms+renesas-/R6kz+dDXgpPR4JQBCEnsQ,
niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw,
robert.jarzmik-GANU6spQydw, songjun.wu-UWL1GkI3JZL3oGB3hsPCZA,
andrew-ct.chen-NuS5LvNUpcJWk0Htik3J/w,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
shuah-DgEjT+Ai2ygdnm+yROfE0A, sakari.ailus-VuQAYsv1563Yd54FQh9/CA,
pavel-+ZI9xUNit7I, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, linux-medi
In-Reply-To: <6c22519f-64f8-7213-d458-23470bdd5ecd-qWit8jRvyhVmR6Xm/wNWPw@public.gmane.org>
On Wed, 2017-04-12 at 09:03 +0200, Hans Verkuil wrote:
[...]
> >> Do you have a git tree with this patch? It is really hard to review without
> >> having the full imx-media-csi.c source.
> >
> > The patch applies on top of
> >
> > https://github.com/slongerbeam/mediatree.git imx-media-staging-md-v14
> >
> > I have uploaded a branch
> >
> > git://git.pengutronix.de/git/pza/linux imx-media-staging-md-v14+color
> >
> > with the patch applied on top.
> >
> >> I think one problem is that it is not clearly defined how subdevs and colorspace
> >> information should work.
>
> Ah, having the full source helped.
>
> Ignore my previous review, it was incorrect.
Ok.
> I'll have to think about this some more. I'll get back to this, but it may take some
> time since my vacation starts tomorrow. The spec is simply unclear about how to handle
> this so we have to come up with some guidelines.
Yes, please. Until then, have a nice vacation.
regards
Philipp
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 0/4] XRA1403,gpio - add XRA1403 gpio expander driver
From: Nandor Han @ 2017-04-13 10:27 UTC (permalink / raw)
To: gregkh, davem, geert, mchehab, daniel.vetter, linus.walleij,
gnurou, robh+dt, mark.rutland, linux-gpio, devicetree,
linux-kernel
Cc: Nandor Han
The patchset will add a driver to support basic functionality for
XRA1403 device. Features supported:
- get/set GPIO direction (input, output)
- get/set GPIO level (low, high)
Documentation: A gpio-xra1403.txt file was added to document the DTS
bindings related to driver.
Testing:
1.1 XRA1403 connected to iMX53 MCU
1.2 Use the GPIO tools provided by kernel from tools/gpio dir
2.1 `lsgpio`
root@csmon ppd:~# lsgpio
GPIO chip: gpiochip8, "xra1403", 16 GPIO lines
line 0: unnamed unused [output]
line 1: unnamed unused [output]
line 2: unnamed unused [output]
line 3: unnamed unused [output]
line 4: unnamed unused [output]
line 5: unnamed unused
line 6: unnamed unused
line 7: unnamed unused [output]
line 8: unnamed unused [output]
line 9: unnamed unused
line 10: unnamed unused [output]
line 11: unnamed unused
line 12: unnamed unused
line 13: unnamed unused
line 14: unnamed unused
line 15: unnamed unused [output]
GPIO chip: gpiochip7, "xra1403", 16 GPIO lines
line 0: unnamed unused
line 1: unnamed unused
line 2: unnamed unused
line 3: unnamed unused
line 4: unnamed unused
line 5: unnamed unused
line 6: unnamed unused
line 7: unnamed unused
line 8: unnamed unused
line 9: unnamed unused
line 10: unnamed unused
line 11: unnamed unused
line 12: unnamed unused
line 13: unnamed unused
line 14: unnamed unused
line 15: unnamed unused
3.1 `gpio-hammer`
root@csmon ppd:~# gpio-hammer -n gpiochip8 -o0 -o1 -o2 -o3
Hammer lines [0, 1, 2, 3] on gpiochip8, initial states: [0, 0, 0, 0]
[\] [0: 0, 1: 0, 2: 0, 3: 0]
...
[\] [0: 1, 1: 1, 2: 1, 3: 1]
When using `gpio-hammer` I also attached an oscilloscope to one of the pins and I was
able to monitor and validate the GPIO status.
Nandor Han (4):
dt-bindings: gpio - add exar to vendor prefixes list
gpio - Add EXAR XRA1403 SPI GPIO expander driver
doc,dts - add XRA1403 DTS binding documentation
Add XRA1403 support to MAINTAINERS file
.../devicetree/bindings/gpio/gpio-xra1403.txt | 46 ++++
.../devicetree/bindings/vendor-prefixes.txt | 1 +
MAINTAINERS | 8 +
drivers/gpio/Kconfig | 5 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-xra1403.c | 236 +++++++++++++++++++++
6 files changed, 297 insertions(+)
create mode 100644 Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
create mode 100644 drivers/gpio/gpio-xra1403.c
--
2.10.1
^ permalink raw reply
* [PATCH v2 1/4] dt-bindings: gpio - add exar to vendor prefixes list
From: Nandor Han @ 2017-04-13 10:27 UTC (permalink / raw)
To: gregkh, davem, geert, mchehab, daniel.vetter, linus.walleij,
gnurou, robh+dt, mark.rutland, linux-gpio, devicetree,
linux-kernel
Cc: Nandor Han
In-Reply-To: <cover.1492077070.git.nandor.han@ge.com>
Add Exar Corporation to vendors list.
Signed-off-by: Nandor Han <nandor.han@ge.com>
---
Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index c7d1b72..ba9058c 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -104,6 +104,7 @@ ettus NI Ettus Research
eukrea Eukréa Electromatique
everest Everest Semiconductor Co. Ltd.
everspin Everspin Technologies, Inc.
+exar Exar Corporation
excito Excito
ezchip EZchip Semiconductor
faraday Faraday Technology Corporation
--
2.10.1
^ permalink raw reply related
* [PATCH v2 2/4] gpio - Add EXAR XRA1403 SPI GPIO expander driver
From: Nandor Han @ 2017-04-13 10:27 UTC (permalink / raw)
To: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
davem-fT/PcQaiUtIeIZ0/mPfg9Q, geert-Td1EMuHUCqxL1ZNQvxDV9g,
mchehab-DgEjT+Ai2ygdnm+yROfE0A, daniel.vetter-/w4YWyX8dFk,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
gnurou-Re5JQEeQqe8AvxtiuMwx3w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, linux-gpio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Nandor Han, Semi Malinen
In-Reply-To: <cover.1492077070.git.nandor.han-JJi787mZWgc@public.gmane.org>
This is a simple driver that provides a /sys/class/gpio
interface for controlling and configuring the GPIO lines.
It does not provide support for chip select or interrupts.
Signed-off-by: Nandor Han <nandor.han-JJi787mZWgc@public.gmane.org>
Signed-off-by: Semi Malinen <semi.malinen-JJi787mZWgc@public.gmane.org>
---
drivers/gpio/Kconfig | 5 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-xra1403.c | 236 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 242 insertions(+)
create mode 100644 drivers/gpio/gpio-xra1403.c
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 63ceed2..53cbe9b 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1214,6 +1214,11 @@ config GPIO_PISOSR
GPIO driver for SPI compatible parallel-in/serial-out shift
registers. These are input only devices.
+config GPIO_XRA1403
+ tristate "EXAR XRA1403 16-bit GPIO expander"
+ help
+ GPIO driver for EXAR XRA1403 16-bit SPI-based GPIO expander.
+
endmenu
menu "SPI or I2C GPIO expanders"
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 095598e..76dc3d7 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -140,6 +140,7 @@ obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o
obj-$(CONFIG_GPIO_XGENE_SB) += gpio-xgene-sb.o
obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
obj-$(CONFIG_GPIO_XLP) += gpio-xlp.o
+obj-$(CONFIG_GPIO_XRA1403) += gpio-xra1403.o
obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o
obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o
obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o
diff --git a/drivers/gpio/gpio-xra1403.c b/drivers/gpio/gpio-xra1403.c
new file mode 100644
index 0000000..e6966d9
--- /dev/null
+++ b/drivers/gpio/gpio-xra1403.c
@@ -0,0 +1,236 @@
+/*
+ * GPIO driver for EXAR XRA1403 16-bit GPIO expander
+ *
+ * Copyright (c) 2017, General Electric Company
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/>.
+ */
+
+#include <linux/bitops.h>
+#include <linux/gpio/driver.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+
+/* XRA1403 registers */
+#define XRA_GSR 0x00 /* GPIO State */
+#define XRA_OCR 0x02 /* Output Control */
+#define XRA_PIR 0x04 /* Input Polarity Inversion */
+#define XRA_GCR 0x06 /* GPIO Configuration */
+#define XRA_PUR 0x08 /* Input Internal Pull-up Resistor Enable/Disable */
+#define XRA_IER 0x0A /* Input Interrupt Enable */
+#define XRA_TSCR 0x0C /* Output Three-State Control */
+#define XRA_ISR 0x0E /* Input Interrupt Status */
+#define XRA_REIR 0x10 /* Input Rising Edge Interrupt Enable */
+#define XRA_FEIR 0x12 /* Input Falling Edge Interrupt Enable */
+#define XRA_IFR 0x14 /* Input Filter Enable/Disable */
+
+struct xra1403 {
+ struct gpio_chip chip;
+ struct regmap *regmap;
+};
+
+static const struct regmap_config xra1403_regmap_cfg = {
+ .reg_bits = 7,
+ .pad_bits = 1,
+ .val_bits = 8,
+
+ .max_register = XRA_IFR | 0x01,
+};
+
+static unsigned int to_reg(unsigned int reg, unsigned int offset)
+{
+ return reg + (offset > 7);
+}
+
+static int xra1403_direction_input(struct gpio_chip *chip, unsigned int offset)
+{
+ struct xra1403 *xra = gpiochip_get_data(chip);
+
+ return regmap_update_bits(xra->regmap, to_reg(XRA_GCR, offset),
+ BIT(offset % 8), BIT(offset % 8));
+}
+
+static int xra1403_direction_output(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ int ret;
+ struct xra1403 *xra = gpiochip_get_data(chip);
+
+ ret = regmap_update_bits(xra->regmap, to_reg(XRA_GCR, offset),
+ BIT(offset % 8), 0);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(xra->regmap, to_reg(XRA_OCR, offset),
+ BIT(offset % 8), value ? BIT(offset % 8) : 0);
+
+ return ret;
+}
+
+static int xra1403_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ int ret;
+ unsigned int val;
+ struct xra1403 *xra = gpiochip_get_data(chip);
+
+ ret = regmap_read(xra->regmap, to_reg(XRA_GCR, offset), &val);
+ if (ret)
+ return ret;
+
+ return !!(val & BIT(offset % 8));
+}
+
+static int xra1403_get(struct gpio_chip *chip, unsigned int offset)
+{
+ int ret;
+ unsigned int val;
+ struct xra1403 *xra = gpiochip_get_data(chip);
+
+ ret = regmap_read(xra->regmap, to_reg(XRA_GSR, offset), &val);
+ if (ret)
+ return ret;
+
+ return !!(val & BIT(offset % 8));
+}
+
+static void xra1403_set(struct gpio_chip *chip, unsigned int offset, int value)
+{
+ int ret;
+ struct xra1403 *xra = gpiochip_get_data(chip);
+
+ ret = regmap_update_bits(xra->regmap, to_reg(XRA_OCR, offset),
+ BIT(offset % 8), value ? BIT(offset % 8) : 0);
+ if (ret)
+ dev_err(chip->parent, "Failed to set pin: %d, ret: %d\n",
+ offset, ret);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+ int reg;
+ struct xra1403 *xra = gpiochip_get_data(chip);
+ int value[xra1403_regmap_cfg.max_register];
+ int i;
+ unsigned int gcr;
+ unsigned int gsr;
+
+ seq_puts(s, "xra reg:");
+ for (reg = 0; reg <= xra1403_regmap_cfg.max_register; reg++)
+ seq_printf(s, " %2.2x", reg);
+ seq_puts(s, "\n value:");
+ for (reg = 0; reg < xra1403_regmap_cfg.max_register; reg++) {
+ regmap_read(xra->regmap, reg, &value[reg]);
+ seq_printf(s, " %2.2x", value[reg]);
+ }
+ seq_puts(s, "\n");
+
+ gcr = value[XRA_GCR + 1] << 8 | value[XRA_GCR];
+ gsr = value[XRA_GSR + 1] << 8 | value[XRA_GSR];
+ for (i = 0; i < chip->ngpio; i++) {
+ const char *label = gpiochip_is_requested(chip, i);
+
+ if (!label)
+ continue;
+
+ seq_printf(s, " gpio-%-3d (%-12s) %s %s\n",
+ chip->base + i, label,
+ (gcr & BIT(i)) ? "in" : "out",
+ (gsr & BIT(i)) ? "hi" : "lo");
+ }
+}
+#else
+#define xra1403_dbg_show NULL
+#endif
+
+static int xra1403_probe(struct spi_device *spi)
+{
+ struct xra1403 *xra;
+ struct gpio_desc *reset_gpio;
+ int ret;
+
+ xra = devm_kzalloc(&spi->dev, sizeof(*xra), GFP_KERNEL);
+ if (!xra)
+ return -ENOMEM;
+
+ /* bring the chip out of reset if reset pin is provided*/
+ reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(reset_gpio))
+ dev_warn(&spi->dev, "Could not get reset-gpios\n");
+
+ xra->chip.direction_input = xra1403_direction_input;
+ xra->chip.direction_output = xra1403_direction_output;
+ xra->chip.get_direction = xra1403_get_direction;
+ xra->chip.get = xra1403_get;
+ xra->chip.set = xra1403_set;
+
+ xra->chip.dbg_show = xra1403_dbg_show;
+
+ xra->chip.ngpio = 16;
+ xra->chip.label = "xra1403";
+
+ xra->chip.base = -1;
+ xra->chip.can_sleep = true;
+ xra->chip.parent = &spi->dev;
+ xra->chip.owner = THIS_MODULE;
+
+ xra->regmap = devm_regmap_init_spi(spi, &xra1403_regmap_cfg);
+ if (IS_ERR(xra->regmap)) {
+ ret = PTR_ERR(xra->regmap);
+ dev_err(&spi->dev, "Failed to allocate regmap: %d\n", ret);
+ return ret;
+ }
+
+ ret = devm_gpiochip_add_data(&spi->dev, &xra->chip, xra);
+ if (ret < 0) {
+ dev_err(&spi->dev, "Unable to register gpiochip\n");
+ return ret;
+ }
+
+ spi_set_drvdata(spi, xra);
+
+ return 0;
+}
+
+static const struct spi_device_id xra1403_ids[] = {
+ { "xra1403" },
+ {},
+};
+MODULE_DEVICE_TABLE(spi, xra1403_ids);
+
+static const struct of_device_id xra1403_spi_of_match[] = {
+ { .compatible = "exar,xra1403" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, xra1403_spi_of_match);
+
+static struct spi_driver xra1403_driver = {
+ .probe = xra1403_probe,
+ .id_table = xra1403_ids,
+ .driver = {
+ .name = "xra1403",
+ .of_match_table = of_match_ptr(xra1403_spi_of_match),
+ },
+};
+
+module_spi_driver(xra1403_driver);
+
+MODULE_AUTHOR("Nandor Han <nandor.han-JJi787mZWgc@public.gmane.org>");
+MODULE_AUTHOR("Semi Malinen <semi.malinen-JJi787mZWgc@public.gmane.org>");
+MODULE_DESCRIPTION("GPIO expander driver for EXAR XRA1403");
+MODULE_LICENSE("GPL v2");
--
2.10.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v2 3/4] doc,dts - add XRA1403 DTS binding documentation
From: Nandor Han @ 2017-04-13 10:27 UTC (permalink / raw)
To: gregkh, davem, geert, mchehab, daniel.vetter, linus.walleij,
gnurou, robh+dt, mark.rutland, linux-gpio, devicetree,
linux-kernel
Cc: Nandor Han
In-Reply-To: <cover.1492077070.git.nandor.han@ge.com>
Add the XRA1403 DTS binding documentation.
Signed-off-by: Nandor Han <nandor.han@ge.com>
---
.../devicetree/bindings/gpio/gpio-xra1403.txt | 46 ++++++++++++++++++++++
1 file changed, 46 insertions(+)
create mode 100644 Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
diff --git a/Documentation/devicetree/bindings/gpio/gpio-xra1403.txt b/Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
new file mode 100644
index 0000000..e13cc39
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
@@ -0,0 +1,46 @@
+GPIO Driver for XRA1403 16-BIT GPIO Expander With Reset Input from EXAR
+
+The XRA1403 is an 16-bit GPIO expander with an SPI interface. Features available:
+ - Individually programmable inputs:
+ - Internal pull-up resistors
+ - Polarity inversion
+ - Individual interrupt enable
+ - Rising edge and/or Falling edge interrupt
+ - Input filter
+ - Individually programmable outputs
+ - Output Level Control
+ - Output Three-State Control
+
+Properties
+----------
+Check documentation for SPI and GPIO controllers regarding properties needed to configure the node.
+
+ - compatible = "exar,xra1403".
+ - reg - SPI id of the device.
+ - gpio-controller - marks the node as gpio.
+ - #gpio-cells - should be two where the first cell is the pin number
+ and the second one is used for optional parameters.
+
+Optional properties:
+-------------------
+ - reset-gpios: in case available used to control the device reset line.
+ - interrupt-controller - marks the node as interrupt controller.
+ - #interrupt-cells - should be two and represents the number of cells
+ needed to encode interrupt source.
+
+Example
+--------
+
+ gpioxra0: gpio@2 {
+ compatible = "exar,xra1403";
+ reg = <2>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ reset-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
+ spi-max-frequency = <1000000>;
+ };
--
2.10.1
^ permalink raw reply related
* [PATCH v2 4/4] Add XRA1403 support to MAINTAINERS file
From: Nandor Han @ 2017-04-13 10:27 UTC (permalink / raw)
To: gregkh, davem, geert, mchehab, daniel.vetter, linus.walleij,
gnurou, robh+dt, mark.rutland, linux-gpio, devicetree,
linux-kernel
Cc: Nandor Han
In-Reply-To: <cover.1492077070.git.nandor.han@ge.com>
Add XRA1403 support to MAINTAINERS list.
Signed-off-by: Nandor Han <nandor.han@ge.com>
---
MAINTAINERS | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 892e958..0c5b984 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14013,6 +14013,14 @@ L: linux-kernel@vger.kernel.org
S: Supported
F: drivers/char/xillybus/
+XRA1403 GPIO EXPANDER
+M: Nandor Han <nandor.han@ge.com>
+M: Semi Malinen <semi.malinen@ge.com>
+L: linux-gpio@vger.kernel.org
+S: Maintained
+F: drivers/gpio/gpio-xra1403.c
+F: Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
+
XTENSA XTFPGA PLATFORM SUPPORT
M: Max Filippov <jcmvbkbc@gmail.com>
L: linux-xtensa@linux-xtensa.org
--
2.10.1
^ permalink raw reply related
* Re: [PATCH 2/2] hwrng: mtk: Add driver for hardware random generator on MT7623 SoC
From: Corentin Labbe @ 2017-04-13 11:06 UTC (permalink / raw)
To: sean.wang-NuS5LvNUpcJWk0Htik3J/w
Cc: herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q,
mpm-VDJrAJ4Gl5ZBDgjK7y7TUQ, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, prasannatsmkumar-Re5JQEeQqe8AvxtiuMwx3w,
romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
shannon.nelson-QHcLZuEGTsvQT0dZR+AlfA,
weiyongjun1-hv44wF8Li93QT0dZR+AlfA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
keyhaede-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <1492067108-14748-3-git-send-email-sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Hello
I have some minor comment below:
On Thu, Apr 13, 2017 at 03:05:08PM +0800, sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org wrote:
> From: Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
>
> This patch adds support for hardware random generator on MT7623 SoC
> and should also work on other similar Mediatek SoCs. Currently,
> the driver is already tested successfully with rng-tools.
>
> Signed-off-by: Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> ---
> drivers/char/hw_random/Kconfig | 16 +++-
> drivers/char/hw_random/Makefile | 2 +-
> drivers/char/hw_random/mtk-rng.c | 174 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 190 insertions(+), 2 deletions(-)
> create mode 100644 drivers/char/hw_random/mtk-rng.c
>
> diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
> index 0cafe08..af782ce 100644
> --- a/drivers/char/hw_random/Kconfig
> +++ b/drivers/char/hw_random/Kconfig
> @@ -419,10 +419,24 @@ config HW_RANDOM_CAVIUM
> Generator hardware found on Cavium SoCs.
>
> To compile this driver as a module, choose M here: the
> - module will be called cavium_rng.
> + module will be called mtk-rng.
Unwanted change
>
> If unsure, say Y.
>
> +config HW_RANDOM_MTK
> + tristate "Mediatek Random Number Generator support"
> + depends on HW_RANDOM
> + depends on ARCH_MEDIATEK || COMPILE_TEST
> + default y
> + ---help---
> + This driver provides kernel-side support for the Random Number
> + Generator hardware found on Mediatek SoCs.
> +
> + To compile this driver as a module, choose M here. the
> + module will be called mtk-rng.
> +
> + If unsure, say Y.
> +
> endif # HW_RANDOM
>
> config UML_RANDOM
> diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
> index 5f52b1e..68be716 100644
> --- a/drivers/char/hw_random/Makefile
> +++ b/drivers/char/hw_random/Makefile
> @@ -1,7 +1,6 @@
> #
> # Makefile for HW Random Number Generator (RNG) device drivers.
> #
> -
Another unwanted change
> obj-$(CONFIG_HW_RANDOM) += rng-core.o
> rng-core-y := core.o
> obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o
> @@ -36,3 +35,4 @@ obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o
> obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o
> obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o
> obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o
> +obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o
> diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c
> new file mode 100644
> index 0000000..6561ee0
> --- /dev/null
> +++ b/drivers/char/hw_random/mtk-rng.c
> @@ -0,0 +1,174 @@
> +/*
> + * Driver for Mediatek Hardware Random Number Generator
> + *
> + * Copyright (C) 2017 Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> + *
> + * 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.
> + */
> +#define MTK_RNG_DEV KBUILD_MODNAME
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/hw_random.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +#define USEC_POLL 2
> +#define TIMEOUT_POLL 20
> +
> +#define RNG_CTRL 0x00
> +#define RNG_EN BIT(0)
> +#define RNG_READY BIT(31)
Keep only one space between define and name
> +
> +#define RNG_DATA 0x08
> +
> +#define to_mtk_rng(p) container_of(p, struct mtk_rng, rng)
> +
> +struct mtk_rng {
> + struct device *dev;
> + void __iomem *base;
> + struct clk *clk;
> + struct hwrng rng;
> +};
> +
> +static int mtk_rng_init(struct hwrng *rng)
> +{
> + struct mtk_rng *priv = to_mtk_rng(rng);
> + u32 val;
> + int err;
> +
> + err = clk_prepare_enable(priv->clk);
> + if (err)
> + return err;
> +
> + val = readl(priv->base + RNG_CTRL);
> + val |= RNG_EN;
> + writel(val, priv->base + RNG_CTRL);
> +
> + return 0;
> +}
> +
> +static void mtk_rng_cleanup(struct hwrng *rng)
> +{
> + struct mtk_rng *priv = to_mtk_rng(rng);
> + u32 val;
> +
> + val = readl(priv->base + RNG_CTRL);
> + val &= ~RNG_EN;
> + writel(val, priv->base + RNG_CTRL);
> +
> + clk_disable_unprepare(priv->clk);
> +}
> +
> +static bool mtk_rng_wait_ready(struct hwrng *rng, bool wait)
> +{
> + struct mtk_rng *priv = to_mtk_rng(rng);
> + int ready;
> +
> + ready = readl(priv->base + RNG_CTRL) & RNG_READY;
> + if (!ready && wait)
> + readl_poll_timeout_atomic(priv->base + RNG_CTRL, ready,
> + ready & RNG_READY, USEC_POLL,
> + TIMEOUT_POLL);
> + return !!ready;
> +}
> +
> +static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
> +{
> + struct mtk_rng *priv = to_mtk_rng(rng);
> + int retval = 0;
> +
> + while (max >= sizeof(u32)) {
> + if (!mtk_rng_wait_ready(rng, wait))
> + break;
> +
> + *(u32 *)buf = readl(priv->base + RNG_DATA);
> + retval += sizeof(u32);
> + buf += sizeof(u32);
> + max -= sizeof(u32);
> + }
> +
> + if (unlikely(wait && max))
> + dev_warn(priv->dev, "timeout might be not properly set\n");
> +
> + return retval || !wait ? retval : -EIO;
> +}
> +
> +static int mtk_rng_probe(struct platform_device *pdev)
> +{
> + struct resource *res;
> + int ret;
> + struct mtk_rng *priv;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(&pdev->dev, "no iomem resource\n");
> + return -ENXIO;
> + }
> +
> + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->dev = &pdev->dev;
> + priv->rng.name = pdev->name;
> + priv->rng.init = mtk_rng_init;
> + priv->rng.cleanup = mtk_rng_cleanup;
> + priv->rng.read = mtk_rng_read;
> +
> + priv->clk = devm_clk_get(&pdev->dev, "rng");
> + if (IS_ERR(priv->clk)) {
> + ret = PTR_ERR(priv->clk);
> + dev_err(&pdev->dev, "no clock for device: %d\n", ret);
> + return ret;
> + }
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
You get that resource twice
Regards
Corentin Labbe
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH] of: Fix DMA configuration for non-DT masters
From: Oza Oza @ 2017-04-13 11:41 UTC (permalink / raw)
To: Robin Murphy
Cc: Linux IOMMU, devicetree-u79uwXL29TY76Z2rM5mHXA,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <b02ace9b-f8f3-269d-6db4-3c1b1ea1e816-5wv7dgnIgG8@public.gmane.org>
On Wed, Mar 29, 2017 at 11:12 PM, Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org> wrote:
> On 29/03/17 06:46, Oza Oza wrote:
>> On Wed, Mar 29, 2017 at 10:23 AM, Oza Oza <oza.oza-dY08KVG/lbpWk0Htik3J/w@public.gmane.org> wrote:
>>> On Wed, Mar 29, 2017 at 12:27 AM, Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org> wrote:
>>>> For PCI masters not represented in DT, we pass the OF node of their
>>>> associated host bridge to of_dma_configure(), such that they can inherit
>>>> the appropriate DMA configuration from whatever is described there.
>>>> Unfortunately, whilst this has worked for the "dma-coherent" property,
>>>> it turns out to miss the case where the host bridge node has a non-empty
>>>> "dma-ranges", since nobody is expecting the 'device' to be a bus itself.
>>>>
>>>> It transpires, though, that the de-facto interface since the prototype
>>>> change in 1f5c69aa51f9 ("of: Move of_dma_configure() to device.c to help
>>>> re-use") is very clear-cut: either the master_np argument is redundant
>>>> with dev->of_node, or dev->of_node is NULL and master_np is the relevant
>>>> parent bus. Let's ratify that behaviour, then teach the whole
>>>> of_dma_configure() pipeline to cope with both cases properly.
>>>>
>>>> Signed-off-by: Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org>
>
> [...]
>
>>>
>>> pci and memory mapped device world is different.
>
> ???
>
> No they aren't. There is nothing magic about PCI. PCI *is* a
> memory-mapped bus.
>
> The only PCI-specific aspect here is the Linux code path which passes a
> host controller node into of_dma_configure() where the latter expects a
> node for the actual endpoint device. It managed to work for
> "dma-coherent", because that may appear either directly on a device node
> or on any of its parent buses, but "dma-ranges" is *only* valid for DT
> nodes representing buses, thus reveals that using a parent bus to stand
> in for a device isn't actually correct. I only posted that horrible hack
> patch to prove the point that having a child node to represent the
> actual device is indeed sufficient to make of_dma_configure() work
> correctly for PCI masters as-is (modulo the other issues).
>
>> of course if you talk
>>> from iommu perspective, all the master are same for IOMMU
>
> I don't understand what you mean by that. There's nothing about IOMMUs
> here, it's purely about parsing DT properties correctly.
>
>>> but the original intention of the patch is to try to solve 2 problems.
>>> please refer to https://lkml.org/lkml/2017/3/29/10
>
> One patch should not solve two separate problems anyway. Taking a step
> back, there are at least 3 things that this discussion has brought up:
>
> 1) The way in which we call of_dma_configure() for PCI devices causes
> the "dma-ranges" property on PCI host controllers to be ignored.
>
> 2) of_dma_get_range() only considers the first entry in any "dma-ranges"
> property.
>
> 3) When of_dma_configure() does set a DMA mask, there is nothing on
> arm64 and other architectures to prevent drivers overriding that with a
> wider mask later.
>
> Those are 3 separate problems, to solve with 3 or more separate patches,
> and I have deliberately put the second and third to one side for the
> moment. This patch fixes problem 1.
>
>>> 1) expose generic API for pci world clients to configure their
>>> dma-ranges. right now there is none.
>>> 2) same API can be used by IOMMU to derive dma_mask.
>>>
>>> while the current patch posted to handle dma-ranges for both memory
>>> mapped and pci devices, which I think is overdoing.
>
> No, of_dma_configure() handles the "dma-ranges" property as it is
> defined in the DT spec to describe the mapping between a child bus
> address space and a parent bus address space. Whether those
> memory-mapped parent and child buses are PCI, ISA, AMBA, HyperTransport,
> or anything else is irrelevant other than for the encoding of the
> address specifiers. All this patch does is sort out the cases where we
> have a real device node to start at, from the cases where we don't and
> so start directly at the device's parent bus node instead.
>
>>> besides we have different configuration of dma-ranges based on iommu
>>> is enabled or not enabled.
>
> That doesn't sound right, unless you mean the firmware actually programs
> the host controller's AXI bridge differently for system configurations
> where the IOMMU is expected to be used or not? (and even then, I don't
> really see why it would be necessary to do that...)
>
>>> #define PCIE_DMA_RANGES dma-ranges = <0x43000000 0x00 0x80000000 0x00
>>> 0x80000000 0x00 0x80000000 \
>>> 0x43000000 0x08 0x00000000 0x08
>>> 0x00000000 0x08 0x00000000 \
>>> 0x43000000 0x80 0x00000000 0x80
>>> 0x00000000 0x40 0x00000000>;
>>> Not sure if this patch will consider above dma-ranges.
>>>
>>> my suggestion is to leave existing of_dma_get_range as is, and have
>>> new function for pci world as discussed in
>>> please refer to https://lkml.org/lkml/2017/3/29/10
>
> And then we keep adding new functions to do the exact same thing for
> every other discoverable bus type whose bridge is be described in DT? I
> fail to see how that is in any way better than simply fixing the
> existing code to work as it was intended to.
>
> of_dma_get_ranges() uses of_translate_dma_address() just the same way as
> existing PowerPC PCI code does, which further disproves your assertion
> that parsing PCI addresses is somehow special - it's really only a
> matter of getting the right number of address cells in order to to read
> a child address to give to of_translate_dma_address() in the first
> place. Incidentally, I now notice that the proposed
> of_pci_get_dma_ranges() is incomplete as it doesn't use
> of_translate_dma_address() or otherwise traverse upwards through the
> dma-ranges of any further parent buses.
>
>>>
>>> Regards,
>>> Oza.
>>
>> also I see that, in case of multiple ranges of_dma_get_range doesnt handle that.
>> and also it is not meant to handle.
>
> Yes, the existing code doesn't handle multiple dma-ranges entries,
> because nobody's had the need to implement that so far, and this patch
> does not change that because it's fixing a separate problem.
>
> Now, of course of_dma_get_range() *should* be capable of handling
> multiple entries regardless of this patch, and I'm going to write *that*
> patch right now (it's going to be a case of adding a handful of lines
> which probably won't even conflict with this one at all). If we had a
> bunch of different range parsing functions, we'd then have to duplicate
> the equivalent logic across all of them, which is clearly undesirable
> when it can easily be avoided altogether.
>
> Robin.
>
>> so with this patch will return wrong size and hence wrong dma_mask.
>> having said, I think it is better to separate pci world dma-ranges
>> function on of_pci.c
>>
>> for which my discussion with Rob already, (same thread)
>> https://lkml.org/lkml/2017/3/29/10
>> Waiting for Rob's viewpoint on this.
>>
>>
>> Regards,
>> Oza.
>>
>
first of all the patch
https://lkml.org/lkml/2017/3/30/304
is not only to address the original problem of dma_mask but also to
provide generic APIs
to PCI RC drivers such as pcie-iproc.c or even rcar to get their dma-ranges.
this API not only provides basis to retrieve the ranges but also it
should have capability to handle
inbound memory flags.
having said that the PCI dma-ranges do differ slightly from
traditional memory ranges.
because it has got flags.
now those flags could be IORESOURCE_CACHEABLE or anything else.
our SOC will be having use of these flags in near future (although can
not discuss details as of now).
but in short we will need these flags to be taken care which were
passed form DT.
so PCIe iproc driver calls this function to get all teh information
about dma-ranges.
now if such function exists, other framework could also make use of it
to get resources and figure out dma_mask.
and in that case you really need not change of_dma_get_range.
not only of_dma_get_range can hdnle PCI flags property but also it can
not handle multiple ranges because finally it has only
single *dma_addr, *paddr, *size out parameters.
so the burdon will be on API to fix the behavior as what to return
rather than having Caller to choose what to do with the ranges.
coming back to my current patch
currently it does not do flag handling, but in near future I will have
to add, but for that, this patch
https://lkml.org/lkml/2017/3/30/304
needs to bring under consideration to be ACKed.
hope this explains the need of API.
Regards,
Oza.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH RFC 0/5] *** SPI Slave mode support ***
From: jiada_wang @ 2017-04-13 12:13 UTC (permalink / raw)
To: broonie, robh+dt, mark.rutland, shawnguo, kernel, fabio.estevam
Cc: Jiada Wang, devicetree, linux-kernel, linux-arm-kernel, linux-spi
From: Jiada Wang <jiada_wang@mentor.com>
v1:
add Slave mode support in SPI core
spidev create slave device when SPI controller work in slave mode
spi-imx support to work in slave mode
Jiada Wang (5):
spi: core: add support to work in Slave mode
spi: spidev: use different name for SPI controller slave mode device
spi: imx: add selection for iMX53 and iMX6 controller
ARM: dts: imx: change compatiblity for SPI controllers on imx53 later
soc
spi: imx: Add support for SPI Slave mode for imx53 and imx6 chips
Documentation/devicetree/bindings/spi/spi-bus.txt | 27 ++-
Documentation/spi/spi-summary | 19 +-
arch/arm/boot/dts/imx53.dtsi | 4 +-
arch/arm/boot/dts/imx6q.dtsi | 2 +-
arch/arm/boot/dts/imx6qdl.dtsi | 8 +-
arch/arm/boot/dts/imx6sl.dtsi | 8 +-
arch/arm/boot/dts/imx6sx.dtsi | 8 +-
arch/arm/boot/dts/imx6ul.dtsi | 8 +-
drivers/spi/Kconfig | 14 +-
drivers/spi/spi-imx.c | 216 ++++++++++++++++++++--
drivers/spi/spi.c | 23 ++-
drivers/spi/spidev.c | 15 +-
include/linux/spi/spi.h | 15 ++
13 files changed, 310 insertions(+), 57 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH RFC 1/5] spi: core: add support to work in Slave mode
From: jiada_wang-nmGgyN9QBj3QT0dZR+AlfA @ 2017-04-13 12:14 UTC (permalink / raw)
To: broonie-DgEjT+Ai2ygdnm+yROfE0A, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, shawnguo-DgEjT+Ai2ygdnm+yROfE0A,
kernel-bIcnvbaLZ9MEGnE8C9+IrQ, fabio.estevam-3arQi8VN3Tc
Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Jiada Wang
In-Reply-To: <1492085644-4195-1-git-send-email-jiada_wang-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
From: Jiada Wang <jiada_wang-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
Add support for SPI bus controller to work in slave mode using
the existing SPI master framework.
- SPI device on SPI bus controller with 'spi-slave' property
declared in DT node represents SPI controller itself to work
as a slave device and listening to external SPI master devices
- when SPI bus controller works in slave mode, 'chip_select' and
'max_speed_hz' are not required.
- SPI slave mode continue to use 'struct spi_master'
Signed-off-by: Jiada Wang <jiada_wang-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
---
Documentation/devicetree/bindings/spi/spi-bus.txt | 27 ++++++++++++++---------
Documentation/spi/spi-summary | 19 +++++++++++-----
drivers/spi/Kconfig | 14 +++++++++++-
drivers/spi/spi.c | 23 ++++++++++++++++++-
include/linux/spi/spi.h | 15 +++++++++++++
5 files changed, 80 insertions(+), 18 deletions(-)
diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt
index 4b1d6e7..96e93ba 100644
--- a/Documentation/devicetree/bindings/spi/spi-bus.txt
+++ b/Documentation/devicetree/bindings/spi/spi-bus.txt
@@ -1,17 +1,20 @@
SPI (Serial Peripheral Interface) busses
-SPI busses can be described with a node for the SPI master device
-and a set of child nodes for each SPI slave on the bus. For this
-discussion, it is assumed that the system's SPI controller is in
-SPI master mode. This binding does not describe SPI controllers
-in slave mode.
+SPI busses can be described with a node for the SPI controller device
+and a set of child nodes for each SPI slave on the bus. The system's SPI
+controller can work either in master mode or in slave mode, based on the
+child node on it.
-The SPI master node requires the following properties:
+The SPI controller node requires the following properties:
+- compatible - name of SPI bus controller following generic names
+ recommended practice.
+
+In master mode, the SPI controller node requires the following additional
+properties:
- #address-cells - number of cells required to define a chip select
address on the SPI bus.
- #size-cells - should be zero.
-- compatible - name of SPI bus controller following generic names
- recommended practice.
+
No other properties are required in the SPI bus node. It is assumed
that a driver for an SPI bus device will understand that it is an SPI bus.
However, the binding does not attempt to define the specific method for
@@ -43,10 +46,11 @@ cs3 : &gpio1 2 0
SPI slave nodes must be children of the SPI master node and can
contain the following properties.
-- reg - (required) chip select address of device.
+- reg - (required, master mode only) chip select address of device.
- compatible - (required) name of SPI device following generic names
recommended practice.
-- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz.
+- spi-max-frequency - (required, master mode only) Maximum SPI clocking speed of
+ device in Hz.
- spi-cpol - (optional) Empty property indicating device requires
inverse clock polarity (CPOL) mode.
- spi-cpha - (optional) Empty property indicating device requires
@@ -63,6 +67,9 @@ contain the following properties.
used for MISO. Defaults to 1 if not present.
- spi-rx-delay-us - (optional) Microsecond delay after a read transfer.
- spi-tx-delay-us - (optional) Microsecond delay after a write transfer.
+- spi-slave - (optional) Empty property indicating SPI bus controller
+ itself works in slave mode to interface with external master
+ devices.
Some SPI controllers and devices support Dual and Quad SPI transfer mode.
It allows data in the SPI system to be transferred using 2 wires (DUAL) or 4
diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary
index d1824b3..4c2ceaa 100644
--- a/Documentation/spi/spi-summary
+++ b/Documentation/spi/spi-summary
@@ -62,9 +62,8 @@ chips described as using "three wire" signaling: SCK, data, nCSx.
(That data line is sometimes called MOMI or SISO.)
Microcontrollers often support both master and slave sides of the SPI
-protocol. This document (and Linux) currently only supports the master
-side of SPI interactions.
-
+protocol. This document (and Linux) supports both the master and slave
+sides of SPI interactions.
Who uses it? On what kinds of systems?
---------------------------------------
@@ -154,9 +153,8 @@ control audio interfaces, present touchscreen sensors as input interfaces,
or monitor temperature and voltage levels during industrial processing.
And those might all be sharing the same controller driver.
-A "struct spi_device" encapsulates the master-side interface between
-those two types of driver. At this writing, Linux has no slave side
-programming interface.
+A "struct spi_device" encapsulates the controller-side interface between
+those two types of drivers.
There is a minimal core of SPI programming interfaces, focussing on
using the driver model to connect controller and protocol drivers using
@@ -168,12 +166,21 @@ shows up in sysfs in several locations:
/sys/devices/.../CTLR/spiB.C ... spi_device on bus "B",
chipselect C, accessed through CTLR.
+ /sys/devices/.../CTLR/spiB-slv ... SPI bus "B" controller itself as a
+ spi_device works in slave mode, accessed through CTRL.
+
/sys/bus/spi/devices/spiB.C ... symlink to that physical
.../CTLR/spiB.C device
+ /sys/bus/spi/devices/spiB-slv ... symlink to that physical
+ .../CTLR/spiB-slv device
+
/sys/devices/.../CTLR/spiB.C/modalias ... identifies the driver
that should be used with this device (for hotplug/coldplug)
+ /sys/devices/.../CTLR/spiB-slv/modalias ... identifies the driver
+ that should be used with this device (for hotplug/coldplug)
+
/sys/bus/spi/drivers/D ... driver for one or more spi*.* devices
/sys/class/spi_master/spiB ... symlink (or actual device node) to
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 25ae7f2e..1096c7d 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -784,6 +784,18 @@ config SPI_TLE62X0
endif # SPI_MASTER
-# (slave support would go here)
+#
+# SLAVE side ... listening to other SPI masters
+#
+
+config SPI_SLAVE
+ bool "SPI slave protocol handlers"
+ help
+ If your system has a slave-capable SPI controller, you can enable
+ slave protocol handlers.
+
+if SPI_SLAVE
+
+endif # SPI_SLAVE
endif # SPI
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 90b5b2e..3af26e2 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -475,6 +475,12 @@ static void spi_dev_set_name(struct spi_device *spi)
return;
}
+ if (spi->slave_mode) {
+ dev_set_name(&spi->dev, "%s-slv",
+ dev_name(&spi->master->dev));
+ return;
+ }
+
dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev),
spi->chip_select);
}
@@ -484,6 +490,9 @@ static int spi_dev_check(struct device *dev, void *data)
struct spi_device *spi = to_spi_device(dev);
struct spi_device *new_spi = data;
+ if (spi->slave_mode)
+ return 0;
+
if (spi->master == new_spi->master &&
spi->chip_select == new_spi->chip_select)
return -EBUSY;
@@ -523,6 +532,9 @@ int spi_add_device(struct spi_device *spi)
*/
mutex_lock(&spi_add_lock);
+ if (spi->slave_mode)
+ goto setup_spi;
+
status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check);
if (status) {
dev_err(dev, "chipselect %d already in use\n",
@@ -533,6 +545,7 @@ int spi_add_device(struct spi_device *spi)
if (master->cs_gpios)
spi->cs_gpio = master->cs_gpios[spi->chip_select];
+setup_spi:
/* Drivers may modify this initial i/o setup, but will
* normally rely on the device being setup. Devices
* using SPI_CS_HIGH can't coexist well otherwise...
@@ -1511,6 +1524,14 @@ static int of_spi_parse_dt(struct spi_master *master, struct spi_device *spi,
u32 value;
int rc;
+ if (of_find_property(nc, "spi-slave", NULL)) {
+ if (!spi_controller_has_slavemode(master))
+ return -EINVAL;
+
+ spi->slave_mode = 1;
+ return 0;
+ }
+
/* Device address */
rc = of_property_read_u32(nc, "reg", &value);
if (rc) {
@@ -1961,7 +1982,7 @@ int spi_register_master(struct spi_master *master)
status = device_add(&master->dev);
if (status < 0)
goto done;
- dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),
+ dev_dbg(dev, "registered controller %s%s\n", dev_name(&master->dev),
dynamic ? " (dynamic)" : "");
/* If we're using a queued driver, start the queue */
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 75c6bd0..bb81425 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -115,6 +115,8 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
* This may be changed by the device's driver, or left at the
* default (0) indicating protocol words are eight bit bytes.
* The spi_transfer.bits_per_word can override this for each transfer.
+ * @slave_mode: indicates whether SPI controller works in master mode
+ * or slave mode to transfer data with external spi devices.
* @irq: Negative, or the number passed to request_irq() to receive
* interrupts from this device.
* @controller_state: Controller's runtime state
@@ -144,6 +146,7 @@ struct spi_device {
u8 chip_select;
u8 bits_per_word;
u16 mode;
+ u8 slave_mode;
#define SPI_CPHA 0x01 /* clock phase */
#define SPI_CPOL 0x02 /* clock polarity */
#define SPI_MODE_0 (0|0) /* (original MicroWire) */
@@ -372,6 +375,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
* transfer_one callback.
* @handle_err: the subsystem calls the driver to handle an error that occurs
* in the generic implementation of transfer_one_message().
+ * @has_slavemode: checks whether SPI Controller supports slave mode or not.
* @unprepare_message: undo any work done by prepare_message().
* @spi_flash_read: to support spi-controller hardwares that provide
* accelerated interface to read from flash devices.
@@ -549,6 +553,7 @@ struct spi_master {
struct spi_transfer *transfer);
void (*handle_err)(struct spi_master *master,
struct spi_message *message);
+ bool (*has_slavemode)(struct spi_master *master);
/* gpio chip select */
int *cs_gpios;
@@ -590,6 +595,16 @@ static inline void spi_master_put(struct spi_master *master)
put_device(&master->dev);
}
+
+static inline bool spi_controller_has_slavemode(struct spi_master *master)
+{
+#ifdef CONFIG_SPI_SLAVE
+ if (master->has_slavemode)
+ return master->has_slavemode(master);
+#endif
+ return false;
+}
+
/* PM calls that need to be issued by the driver */
extern int spi_master_suspend(struct spi_master *master);
extern int spi_master_resume(struct spi_master *master);
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH RFC 2/5] spi: spidev: use different name for SPI controller slave mode device
From: jiada_wang @ 2017-04-13 12:14 UTC (permalink / raw)
To: broonie, robh+dt, mark.rutland, shawnguo, kernel, fabio.estevam
Cc: Jiada Wang, devicetree, linux-kernel, linux-arm-kernel, linux-spi
In-Reply-To: <1492085644-4195-1-git-send-email-jiada_wang@mentor.com>
From: Jiada Wang <jiada_wang@mentor.com>
SPI bus controller has started to support to work in slave mode,
for device SPI controller itself works in slave mode, use name
'spidev[bus]-slv' as its name to differentiate from other
SPI devices
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
drivers/spi/spidev.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 9e2e099..e2996fb 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -781,9 +781,18 @@ static int spidev_probe(struct spi_device *spi)
struct device *dev;
spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
- dev = device_create(spidev_class, &spi->dev, spidev->devt,
- spidev, "spidev%d.%d",
- spi->master->bus_num, spi->chip_select);
+ if (spi->slave_mode)
+ dev = device_create(spidev_class, &spi->dev,
+ spidev->devt, spidev,
+ "spidev%d-slv",
+ spi->master->bus_num);
+ else
+ dev = device_create(spidev_class, &spi->dev,
+ spidev->devt, spidev,
+ "spidev%d.%d",
+ spi->master->bus_num,
+ spi->chip_select);
+
status = PTR_ERR_OR_ZERO(dev);
} else {
dev_dbg(&spi->dev, "no minor number available!\n");
--
2.7.4
^ permalink raw reply related
* [PATCH RFC 3/5] spi: imx: add selection for iMX53 and iMX6 controller
From: jiada_wang @ 2017-04-13 12:14 UTC (permalink / raw)
To: broonie, robh+dt, mark.rutland, shawnguo, kernel, fabio.estevam
Cc: linux-spi, devicetree, linux-kernel, linux-arm-kernel, Jiada Wang
In-Reply-To: <1492085644-4195-1-git-send-email-jiada_wang@mentor.com>
From: Jiada Wang <jiada_wang@mentor.com>
ECSPI contorller for iMX53 and iMX6 has few hardware issues
comparing to iMX51.
The change add possibility to detect which controller is used
to apply possible workaround and limitations.
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
drivers/spi/spi-imx.c | 43 ++++++++++++++++++++++++++++++++++++++++---
1 file changed, 40 insertions(+), 3 deletions(-)
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 9a7c62f..b2323b9 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -67,7 +67,8 @@ enum spi_imx_devtype {
IMX27_CSPI,
IMX31_CSPI,
IMX35_CSPI, /* CSPI on all i.mx except above */
- IMX51_ECSPI, /* ECSPI on i.mx51 and later */
+ IMX51_ECSPI, /* ECSPI on i.mx51 */
+ IMX53_ECSPI, /* ECSPI on i.mx53 and later */
};
struct spi_imx_data;
@@ -127,9 +128,32 @@ static inline int is_imx51_ecspi(struct spi_imx_data *d)
return d->devtype_data->devtype == IMX51_ECSPI;
}
+static inline int is_imx53_ecspi(struct spi_imx_data *d)
+{
+ return d->devtype_data->devtype == IMX53_ECSPI;
+}
+
static inline unsigned spi_imx_get_fifosize(struct spi_imx_data *d)
{
- return is_imx51_ecspi(d) ? 64 : 8;
+ switch (d->devtype_data->devtype) {
+ case IMX51_ECSPI:
+ case IMX53_ECSPI:
+ return 64;
+ default:
+ return 8;
+ }
+}
+
+static inline bool spi_imx_has_dmamode(struct spi_imx_data *d)
+{
+ switch (d->devtype_data->devtype) {
+ case IMX35_CSPI:
+ case IMX51_ECSPI:
+ case IMX53_ECSPI:
+ return true;
+ default:
+ return false;
+ }
}
#define MXC_SPI_BUF_RX(type) \
@@ -746,6 +770,15 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
.devtype = IMX51_ECSPI,
};
+static struct spi_imx_devtype_data imx53_ecspi_devtype_data = {
+ .intctrl = mx51_ecspi_intctrl,
+ .config = mx51_ecspi_config,
+ .trigger = mx51_ecspi_trigger,
+ .rx_available = mx51_ecspi_rx_available,
+ .reset = mx51_ecspi_reset,
+ .devtype = IMX53_ECSPI,
+};
+
static const struct platform_device_id spi_imx_devtype[] = {
{
.name = "imx1-cspi",
@@ -766,6 +799,9 @@ static const struct platform_device_id spi_imx_devtype[] = {
.name = "imx51-ecspi",
.driver_data = (kernel_ulong_t) &imx51_ecspi_devtype_data,
}, {
+ .name = "imx53-ecspi",
+ .driver_data = (kernel_ulong_t) &imx53_ecspi_devtype_data,
+ }, {
/* sentinel */
}
};
@@ -777,6 +813,7 @@ static const struct of_device_id spi_imx_dt_ids[] = {
{ .compatible = "fsl,imx31-cspi", .data = &imx31_cspi_devtype_data, },
{ .compatible = "fsl,imx35-cspi", .data = &imx35_cspi_devtype_data, },
{ .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, },
+ { .compatible = "fsl,imx53-ecspi", .data = &imx53_ecspi_devtype_data, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, spi_imx_dt_ids);
@@ -1266,7 +1303,7 @@ static int spi_imx_probe(struct platform_device *pdev)
* Only validated on i.mx35 and i.mx6 now, can remove the constraint
* if validated on other chips.
*/
- if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx)) {
+ if (spi_imx_has_dmamode(spi_imx)) {
ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master);
if (ret == -EPROBE_DEFER)
goto out_clk_put;
--
2.7.4
^ permalink raw reply related
* [PATCH RFC 4/5] ARM: dts: imx: change compatiblity for SPI controllers on imx53 later soc
From: jiada_wang @ 2017-04-13 12:14 UTC (permalink / raw)
To: broonie, robh+dt, mark.rutland, shawnguo, kernel, fabio.estevam
Cc: linux-spi, devicetree, linux-kernel, linux-arm-kernel, Jiada Wang
In-Reply-To: <1492085644-4195-1-git-send-email-jiada_wang@mentor.com>
From: Jiada Wang <jiada_wang@mentor.com>
for SPI controllers on imx53 and later SoCs, there is HW issue when
work in slave mode, as new device type 'IMX53_ECSPI' has been added
for these SPI controllers which is compatible with 'fsl,imx53-ecspi'.
This patch updates DTS to make imx53 later SPI controller only be
compatibile with 'fsl,imx53-ecspi'.
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
arch/arm/boot/dts/imx53.dtsi | 4 ++--
arch/arm/boot/dts/imx6q.dtsi | 2 +-
arch/arm/boot/dts/imx6qdl.dtsi | 8 ++++----
arch/arm/boot/dts/imx6sl.dtsi | 8 ++++----
arch/arm/boot/dts/imx6sx.dtsi | 8 ++++----
arch/arm/boot/dts/imx6ul.dtsi | 8 ++++----
6 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index 2e516f4..9eeafb9 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -243,7 +243,7 @@
ecspi1: ecspi@50010000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx53-ecspi";
reg = <0x50010000 0x4000>;
interrupts = <36>;
clocks = <&clks IMX5_CLK_ECSPI1_IPG_GATE>,
@@ -662,7 +662,7 @@
ecspi2: ecspi@63fac000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx53-ecspi";
reg = <0x63fac000 0x4000>;
interrupts = <37>;
clocks = <&clks IMX5_CLK_ECSPI2_IPG_GATE>,
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index e9a5d0b..7373671 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -90,7 +90,7 @@
ecspi5: ecspi@02018000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6q-ecspi", "fsl,imx53-ecspi";
reg = <0x02018000 0x4000>;
interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6Q_CLK_ECSPI5>,
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 6d7bf64..4a4b509 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -265,7 +265,7 @@
ecspi1: ecspi@02008000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6q-ecspi", "fsl,imx53-ecspi";
reg = <0x02008000 0x4000>;
interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_ECSPI1>,
@@ -279,7 +279,7 @@
ecspi2: ecspi@0200c000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6q-ecspi", "fsl,imx53-ecspi";
reg = <0x0200c000 0x4000>;
interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_ECSPI2>,
@@ -293,7 +293,7 @@
ecspi3: ecspi@02010000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6q-ecspi", "fsl,imx53-ecspi";
reg = <0x02010000 0x4000>;
interrupts = <0 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_ECSPI3>,
@@ -307,7 +307,7 @@
ecspi4: ecspi@02014000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6q-ecspi", "fsl,imx53-ecspi";
reg = <0x02014000 0x4000>;
interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_ECSPI4>,
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index cc9572e..1d1200c 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -168,7 +168,7 @@
ecspi1: ecspi@02008000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6sl-ecspi", "fsl,imx53-ecspi";
reg = <0x02008000 0x4000>;
interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_ECSPI1>,
@@ -180,7 +180,7 @@
ecspi2: ecspi@0200c000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6sl-ecspi", "fsl,imx53-ecspi";
reg = <0x0200c000 0x4000>;
interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_ECSPI2>,
@@ -192,7 +192,7 @@
ecspi3: ecspi@02010000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6sl-ecspi", "fsl,imx53-ecspi";
reg = <0x02010000 0x4000>;
interrupts = <0 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_ECSPI3>,
@@ -204,7 +204,7 @@
ecspi4: ecspi@02014000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6sl-ecspi", "fsl,imx53-ecspi";
reg = <0x02014000 0x4000>;
interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SL_CLK_ECSPI4>,
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index dd4ec85..c115ed3 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -251,7 +251,7 @@
ecspi1: ecspi@02008000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6sx-ecspi", "fsl,imx53-ecspi";
reg = <0x02008000 0x4000>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_ECSPI1>,
@@ -263,7 +263,7 @@
ecspi2: ecspi@0200c000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6sx-ecspi", "fsl,imx53-ecspi";
reg = <0x0200c000 0x4000>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_ECSPI2>,
@@ -275,7 +275,7 @@
ecspi3: ecspi@02010000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6sx-ecspi", "fsl,imx53-ecspi";
reg = <0x02010000 0x4000>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_ECSPI3>,
@@ -287,7 +287,7 @@
ecspi4: ecspi@02014000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6sx-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6sx-ecspi", "fsl,imx53-ecspi";
reg = <0x02014000 0x4000>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_ECSPI4>,
diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
index b9d7d2d..d35ad5b 100644
--- a/arch/arm/boot/dts/imx6ul.dtsi
+++ b/arch/arm/boot/dts/imx6ul.dtsi
@@ -204,7 +204,7 @@
ecspi1: ecspi@02008000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx53-ecspi";
reg = <0x02008000 0x4000>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_ECSPI1>,
@@ -216,7 +216,7 @@
ecspi2: ecspi@0200c000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx53-ecspi";
reg = <0x0200c000 0x4000>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_ECSPI2>,
@@ -228,7 +228,7 @@
ecspi3: ecspi@02010000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx53-ecspi";
reg = <0x02010000 0x4000>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_ECSPI3>,
@@ -240,7 +240,7 @@
ecspi4: ecspi@02014000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx6ul-ecspi", "fsl,imx53-ecspi";
reg = <0x02014000 0x4000>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_ECSPI4>,
--
2.7.4
^ permalink raw reply related
* [PATCH RFC 5/5] spi: imx: Add support for SPI Slave mode for imx53 and imx6 chips
From: jiada_wang @ 2017-04-13 12:14 UTC (permalink / raw)
To: broonie, robh+dt, mark.rutland, shawnguo, kernel, fabio.estevam
Cc: linux-spi, devicetree, linux-kernel, linux-arm-kernel, Jiada Wang
In-Reply-To: <1492085644-4195-1-git-send-email-jiada_wang@mentor.com>
From: Jiada Wang <jiada_wang@mentor.com>
Previously i.MX SPI controller only works in Master mode.
This patch adds support to work also in Slave mode.
Currently SPI Slave mode support patch has the following limitations:
1. The stale data in RXFIFO will be dropped when the Slave does any new
transfer.
2. One transfer can be finished only after all transfer->len data been
transferred to master device
3. Slave device only accepts transfer->len data. Any data longer than this
from master device will be dropped. Any data shorter than this from
master will cause SPI to stuck due to mentioned HW limitation 2.
4. Only PIO transfer is supported in Slave mode.
Following HW limitation applies:
1. ECSPI has a HW issue when works in Slave mode, after 64
words written to TXFIFO, even TXFIFO becomes empty,
ECSPI_TXDATA keeps shift out the last word data,
so we have to disable ECSPI when in slave mode after the
transfer completes
2. Due to Freescale errata ERR003775 "eCSPI: Burst completion by Chip
Select (SS) signal in Slave mode is not functional" burst size must
be set exactly to the size of the transfer. This limit SPI transaction
with maximum 2^12 bits.
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
drivers/spi/spi-imx.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 159 insertions(+), 14 deletions(-)
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index b2323b9..f6e1baa 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -53,9 +53,13 @@
/* generic defines to abstract from the different register layouts */
#define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */
#define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */
+#define MXC_INT_RDR BIT(4) /* Receive date threshold interrupt */
/* The maximum bytes that a sdma BD can transfer.*/
#define MAX_SDMA_BD_BYTES (1 << 15)
+/* The maximum bytes that IMX53_ECSPI can transfer in slave mode.*/
+#define MX53_MAX_TRANSFER_BYTES 512
+
struct spi_imx_config {
unsigned int speed_hz;
unsigned int bpw;
@@ -79,6 +83,7 @@ struct spi_imx_devtype_data {
void (*trigger)(struct spi_imx_data *);
int (*rx_available)(struct spi_imx_data *);
void (*reset)(struct spi_imx_data *);
+ void (*disable)(struct spi_imx_data *);
enum spi_imx_devtype devtype;
};
@@ -104,6 +109,10 @@ struct spi_imx_data {
const void *tx_buf;
unsigned int txfifo; /* number of words pushed in tx FIFO */
+ /* Slave mode */
+ unsigned int slave_mode;
+ unsigned int slave_burst;
+
/* DMA */
bool usedma;
u32 wml;
@@ -156,6 +165,19 @@ static inline bool spi_imx_has_dmamode(struct spi_imx_data *d)
}
}
+static bool spi_imx_has_slavemode(struct spi_master *master)
+{
+ struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+ switch (spi_imx->devtype_data->devtype) {
+ case IMX51_ECSPI:
+ case IMX53_ECSPI:
+ return true;
+ default:
+ return false;
+ }
+}
+
#define MXC_SPI_BUF_RX(type) \
static void spi_imx_buf_rx_##type(struct spi_imx_data *spi_imx) \
{ \
@@ -285,6 +307,7 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
#define MX51_ECSPI_INT 0x10
#define MX51_ECSPI_INT_TEEN (1 << 0)
#define MX51_ECSPI_INT_RREN (1 << 3)
+#define MX51_ECSPI_INT_RDREN (1 << 4)
#define MX51_ECSPI_DMA 0x14
#define MX51_ECSPI_DMA_TX_WML(wml) ((wml) & 0x3f)
@@ -301,6 +324,51 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
#define MX51_ECSPI_TESTREG 0x20
#define MX51_ECSPI_TESTREG_LBC BIT(31)
+static void mx53_ecspi_rx_slave(struct spi_imx_data *spi_imx)
+{
+ u32 val = be32_to_cpu(readl(spi_imx->base + MXC_CSPIRXDATA));
+
+ if (spi_imx->rx_buf) {
+ int shift = spi_imx->slave_burst % sizeof(val);
+
+ if (shift) {
+ memcpy(spi_imx->rx_buf,
+ ((u8 *)&val) + sizeof(val) - shift, shift);
+ } else {
+ *((u32 *)spi_imx->rx_buf) = val;
+ shift = sizeof(val);
+ }
+
+ spi_imx->rx_buf += shift;
+ spi_imx->slave_burst -= shift;
+ }
+}
+
+static void mx53_ecspi_tx_slave(struct spi_imx_data *spi_imx)
+{
+ u32 val = 0;
+ int shift = spi_imx->count % sizeof(val);
+
+ if (spi_imx->tx_buf) {
+ if (shift) {
+ memcpy(((u8 *)&val) + sizeof(val) - shift,
+ spi_imx->tx_buf, shift);
+ } else {
+ val = *((u32 *)spi_imx->tx_buf);
+ shift = sizeof(val);
+ }
+ val = cpu_to_be32(val);
+ spi_imx->tx_buf += shift;
+ }
+
+ if (!shift)
+ shift = sizeof(val);
+
+ spi_imx->count -= shift;
+
+ writel(val, spi_imx->base + MXC_CSPITXDATA);
+}
+
/* MX51 eCSPI */
static unsigned int mx51_ecspi_clkdiv(struct spi_imx_data *spi_imx,
unsigned int fspi, unsigned int *fres)
@@ -350,6 +418,9 @@ static void mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int enable)
if (enable & MXC_INT_RR)
val |= MX51_ECSPI_INT_RREN;
+ if (enable & MXC_INT_RDR)
+ val |= MX51_ECSPI_INT_RDREN;
+
writel(val, spi_imx->base + MX51_ECSPI_INT);
}
@@ -362,6 +433,15 @@ static void mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
}
+static void __maybe_unused mx51_ecspi_disable(struct spi_imx_data *spi_imx)
+{
+ u32 ctrl;
+
+ ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL);
+ ctrl &= ~MX51_ECSPI_CTRL_ENABLE;
+ writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
+}
+
static int mx51_ecspi_config(struct spi_device *spi,
struct spi_imx_config *config)
{
@@ -370,14 +450,13 @@ static int mx51_ecspi_config(struct spi_device *spi,
u32 clk = config->speed_hz, delay, reg;
u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
- /*
- * The hardware seems to have a race condition when changing modes. The
- * current assumption is that the selection of the channel arrives
- * earlier in the hardware than the mode bits when they are written at
- * the same time.
- * So set master mode for all channels as we do not support slave mode.
- */
- ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
+ writel(0, spi_imx->base + MX51_ECSPI_CTRL);
+
+ /* set Master or Slave mode */
+ if (spi_imx->slave_mode)
+ ctrl &= ~MX51_ECSPI_CTRL_MODE_MASK;
+ else
+ ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
/* set clock speed */
ctrl |= mx51_ecspi_clkdiv(spi_imx, config->speed_hz, &clk);
@@ -386,9 +465,21 @@ static int mx51_ecspi_config(struct spi_device *spi,
/* set chip select to use */
ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select);
- ctrl |= (config->bpw - 1) << MX51_ECSPI_CTRL_BL_OFFSET;
+ if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
+ ctrl |= (spi_imx->slave_burst * 8 - 1)
+ << MX51_ECSPI_CTRL_BL_OFFSET;
+ else
+ ctrl |= (config->bpw - 1) << MX51_ECSPI_CTRL_BL_OFFSET;
- cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select);
+ /*
+ * eCSPI burst completion by Chip Select signal in Slave mode
+ * is not functional, config SPI burst completed when
+ * BURST_LENGTH + 1 bits are received
+ */
+ if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx))
+ cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select);
+ else
+ cfg |= MX51_ECSPI_CONFIG_SBBCTRL(spi->chip_select);
if (spi->mode & SPI_CPHA)
cfg |= MX51_ECSPI_CONFIG_SCLKPHA(spi->chip_select);
@@ -767,6 +858,7 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = {
.trigger = mx51_ecspi_trigger,
.rx_available = mx51_ecspi_rx_available,
.reset = mx51_ecspi_reset,
+ .disable = mx51_ecspi_disable,
.devtype = IMX51_ECSPI,
};
@@ -776,6 +868,7 @@ static struct spi_imx_devtype_data imx53_ecspi_devtype_data = {
.trigger = mx51_ecspi_trigger,
.rx_available = mx51_ecspi_rx_available,
.reset = mx51_ecspi_reset,
+ .disable = mx51_ecspi_disable,
.devtype = IMX53_ECSPI,
};
@@ -838,14 +931,16 @@ static void spi_imx_push(struct spi_imx_data *spi_imx)
spi_imx->txfifo++;
}
- spi_imx->devtype_data->trigger(spi_imx);
+ if (!spi_imx->slave_mode)
+ spi_imx->devtype_data->trigger(spi_imx);
}
static irqreturn_t spi_imx_isr(int irq, void *dev_id)
{
struct spi_imx_data *spi_imx = dev_id;
- while (spi_imx->devtype_data->rx_available(spi_imx)) {
+ while (spi_imx->txfifo &&
+ spi_imx->devtype_data->rx_available(spi_imx)) {
spi_imx->rx(spi_imx);
spi_imx->txfifo--;
}
@@ -927,6 +1022,8 @@ static int spi_imx_setupxfer(struct spi_device *spi,
config.bpw = t ? t->bits_per_word : spi->bits_per_word;
config.speed_hz = t ? t->speed_hz : spi->max_speed_hz;
+ spi_imx->slave_mode = spi->slave_mode;
+
if (!config.speed_hz)
config.speed_hz = spi->max_speed_hz;
if (!config.bpw)
@@ -944,7 +1041,8 @@ static int spi_imx_setupxfer(struct spi_device *spi,
spi_imx->tx = spi_imx_buf_tx_u32;
}
- if (spi_imx_can_dma(spi_imx->bitbang.master, spi, t))
+ if (!spi->slave_mode &&
+ spi_imx_can_dma(spi_imx->bitbang.master, spi, t))
spi_imx->usedma = 1;
else
spi_imx->usedma = 0;
@@ -956,6 +1054,12 @@ static int spi_imx_setupxfer(struct spi_device *spi,
return ret;
}
+ if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode) {
+ spi_imx->rx = mx53_ecspi_rx_slave;
+ spi_imx->tx = mx53_ecspi_tx_slave;
+ spi_imx->slave_burst = t->len;
+ }
+
spi_imx->devtype_data->config(spi, &config);
return 0;
@@ -1117,16 +1221,46 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
unsigned long transfer_timeout;
unsigned long timeout;
+ int ret = transfer->len;
+
+ if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode &&
+ transfer->len > MX53_MAX_TRANSFER_BYTES) {
+ pr_err("Transaction too big, max size is %d bytes\n",
+ MX53_MAX_TRANSFER_BYTES);
+ return -EMSGSIZE;
+ }
spi_imx->tx_buf = transfer->tx_buf;
spi_imx->rx_buf = transfer->rx_buf;
spi_imx->count = transfer->len;
spi_imx->txfifo = 0;
+ if (spi_imx->slave_mode)
+ spi_imx->slave_burst = spi_imx->count;
+
reinit_completion(&spi_imx->xfer_done);
spi_imx_push(spi_imx);
+ if (spi_imx->slave_mode) {
+ spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TE |
+ MXC_INT_RDR);
+
+ if (wait_for_completion_interruptible(&spi_imx->xfer_done) < 0)
+ ret = -EINTR;
+
+ /* ecspi has a HW issue when works in Slave mode,
+ * after 64 words writtern to TXFIFO, even TXFIFO becomes empty,
+ * ECSPI_TXDATA keeps shift out the last word data,
+ * so we have to disable ECSPI when in slave mode after the
+ * transfer completes
+ */
+ if (spi_imx->devtype_data->disable)
+ spi_imx->devtype_data->disable(spi_imx);
+
+ goto out;
+ }
+
spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TE);
transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len);
@@ -1139,7 +1273,8 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
return -ETIMEDOUT;
}
- return transfer->len;
+out:
+ return ret;
}
static int spi_imx_transfer(struct spi_device *spi,
@@ -1147,6 +1282,10 @@ static int spi_imx_transfer(struct spi_device *spi,
{
struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+ /* flush rxfifo before transfer */
+ while (spi_imx->devtype_data->rx_available(spi_imx))
+ spi_imx->rx(spi_imx);
+
if (spi_imx->usedma)
return spi_imx_dma_transfer(spi_imx, transfer);
else
@@ -1155,6 +1294,11 @@ static int spi_imx_transfer(struct spi_device *spi,
static int spi_imx_setup(struct spi_device *spi)
{
+ if (spi->slave_mode) {
+ dev_dbg(&spi->dev, "%s: slave mode\n", __func__);
+ return 0;
+ }
+
dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", __func__,
spi->mode, spi->bits_per_word, spi->max_speed_hz);
@@ -1254,6 +1398,7 @@ static int spi_imx_probe(struct platform_device *pdev)
spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
if (is_imx35_cspi(spi_imx) || is_imx51_ecspi(spi_imx))
spi_imx->bitbang.master->mode_bits |= SPI_LOOP;
+ spi_imx->bitbang.master->has_slavemode = spi_imx_has_slavemode;
init_completion(&spi_imx->xfer_done);
--
2.7.4
^ permalink raw reply related
* Re: [PATCH 1/2] mfd: arizona: Add GPIO maintain state flag
From: Linus Walleij @ 2017-04-13 12:14 UTC (permalink / raw)
To: Charles Keepax
Cc: Richard Fitzgerald, Rob Herring, Lee Jones, Alexandre Courbot,
Mark Rutland, linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
open list:WOLFSON MICROELECTRONICS DRIVERS
In-Reply-To: <20170413091513.GA1878-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
On Thu, Apr 13, 2017 at 11:15 AM, Charles Keepax
<ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org> wrote:
> On Tue, Apr 11, 2017 at 10:34:27AM +0100, Richard Fitzgerald wrote:
>> 3) The codec only has to be kept awake while any such GPIO is actually
>> in use. See (2)
>
> Yeah option 3 is the primary issue here, we only want to keep the
> CODEC enabled whilst specific GPIOs are in use. As GPIOs can be
> dynamically requested/released by things in the kernel we want to
> know which GPIOs require the CODEC to be kept alive. Also in the
> future one might be tempted to add maintain whilst high and
> maintain whilst low options for lines with pulls on them to
> further optimise power.
Why does this have to be encoded as information in the device
tree? Isn't it better to use a static table in the driver?
I don't see what use system integrators and others playing
around with the device tree has of this, it will just be confusing
to them if it is a chip-internal detail.
Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/2] mfd: arizona: Add GPIO maintain state flag
From: Richard Fitzgerald @ 2017-04-13 12:21 UTC (permalink / raw)
To: Linus Walleij
Cc: Charles Keepax, Rob Herring, Lee Jones, Alexandre Courbot,
Mark Rutland, linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
open list:WOLFSON MICROELECTRONICS DRIVERS
In-Reply-To: <CACRpkdZ6PBv72BCn1bXsvhcHD2+dsCdh=3F3Vnnm7AWZqyWrig-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Thu, 2017-04-13 at 14:14 +0200, Linus Walleij wrote:
> On Thu, Apr 13, 2017 at 11:15 AM, Charles Keepax
> <ckeepax-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E@public.gmane.org> wrote:
> > On Tue, Apr 11, 2017 at 10:34:27AM +0100, Richard Fitzgerald wrote:
>
> >> 3) The codec only has to be kept awake while any such GPIO is actually
> >> in use. See (2)
> >
> > Yeah option 3 is the primary issue here, we only want to keep the
> > CODEC enabled whilst specific GPIOs are in use. As GPIOs can be
> > dynamically requested/released by things in the kernel we want to
> > know which GPIOs require the CODEC to be kept alive. Also in the
> > future one might be tempted to add maintain whilst high and
> > maintain whilst low options for lines with pulls on them to
> > further optimise power.
>
> Why does this have to be encoded as information in the device
> tree? Isn't it better to use a static table in the driver?
>
> I don't see what use system integrators and others playing
> around with the device tree has of this, it will just be confusing
> to them if it is a chip-internal detail.
>
They are GPIOs for connecting to external hardware, we don't know what
people are going to connect them to so they have to tell us how they
need them to behave.
> Yours,
> Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ 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