Devicetree
 help / color / mirror / Atom feed
* [PATCH v2 2/3] dt-bindings: iio/adc: Add AUX2 channel idx for JZ4770 SoC ADC
From: Artur Rojek @ 2019-07-27 19:59 UTC (permalink / raw)
  To: Jonathan Cameron, Rob Herring, Mark Rutland, Paul Cercueil
  Cc: linux-iio, devicetree, linux-kernel, Artur Rojek, Rob Herring
In-Reply-To: <20190727195940.14010-1-contact@artur-rojek.eu>

Introduce support for AUX2 channel found in ADC hardware present on
Ingenic JZ4770 SoC.

Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
Reviewed-by: Rob Herring <robh@kernel.org>
---

Changes:

v2: no change

 include/dt-bindings/iio/adc/ingenic,adc.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/dt-bindings/iio/adc/ingenic,adc.h b/include/dt-bindings/iio/adc/ingenic,adc.h
index 82706b2706ac..42f871ab3272 100644
--- a/include/dt-bindings/iio/adc/ingenic,adc.h
+++ b/include/dt-bindings/iio/adc/ingenic,adc.h
@@ -6,5 +6,6 @@
 /* ADC channel idx. */
 #define INGENIC_ADC_AUX		0
 #define INGENIC_ADC_BATTERY	1
+#define INGENIC_ADC_AUX2	2
 
 #endif
-- 
2.22.0

^ permalink raw reply related

* [PATCH v2 1/3] dt-bindings: iio/adc: Add a compatible string for JZ4770 SoC ADC
From: Artur Rojek @ 2019-07-27 19:59 UTC (permalink / raw)
  To: Jonathan Cameron, Rob Herring, Mark Rutland, Paul Cercueil
  Cc: linux-iio, devicetree, linux-kernel, Artur Rojek, Rob Herring

Add a compatible string for the ADC controller present on
Ingenic JZ4770 SoC.

Signed-off-by: Artur Rojek <contact@artur-rojek.eu>
Reviewed-by: Rob Herring <robh@kernel.org>
---

Changes:

v2: no change

 Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt b/Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt
index f01159f20d87..cd9048cf9dcf 100644
--- a/Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt
+++ b/Documentation/devicetree/bindings/iio/adc/ingenic,adc.txt
@@ -5,6 +5,7 @@ Required properties:
 - compatible: Should be one of:
   * ingenic,jz4725b-adc
   * ingenic,jz4740-adc
+  * ingenic,jz4770-adc
 - reg: ADC controller registers location and length.
 - clocks: phandle to the SoC's ADC clock.
 - clock-names: Must be set to "adc".
-- 
2.22.0

^ permalink raw reply related

* Re: [PATCH 1/4] dt-bindings: counter: new bindings for TI eQEP
From: Jonathan Cameron @ 2019-07-27 19:48 UTC (permalink / raw)
  To: David Lechner
  Cc: linux-iio, linux-omap, devicetree, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, William Breathitt Gray,
	Thierry Reding, linux-kernel, linux-pwm
In-Reply-To: <20190722154538.5314-2-david@lechnology.com>

On Mon, 22 Jul 2019 10:45:35 -0500
David Lechner <david@lechnology.com> wrote:

> This documents device tree binding for the Texas Instruments Enhanced
> Quadrature Encoder Pulse (eQEP) Module found in various TI SoCs.
> 
> Signed-off-by: David Lechner <david@lechnology.com>

Up to William given it is a counter binding, (unless Rob overrules)
but new bindings are generally preferred as yaml.

Content looks fine to me.

Thanks,

Jonathan

> ---
>  .../devicetree/bindings/counter/ti-eqep.txt    | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/counter/ti-eqep.txt
> 
> diff --git a/Documentation/devicetree/bindings/counter/ti-eqep.txt b/Documentation/devicetree/bindings/counter/ti-eqep.txt
> new file mode 100644
> index 000000000000..fbcebc2c2cc2
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/counter/ti-eqep.txt
> @@ -0,0 +1,18 @@
> +Texas Instruments Enhanced Quadrature Encoder Pulse (eQEP) Module
> +
> +Required properties:
> +- compatible:		Must be "ti,am3352-eqep".
> +- reg:			Physical base address and size of the registers map.
> +- clocks:		Handle to the PWM's functional clock.
> +- clock-names:		Must be "fck".
> +- interrupts:		Handle to the eQEP event interrupt
> +
> +Example:
> +
> +	eqep0: eqep@180 {
> +		compatible = "ti,am3352-eqep";
> +		reg = <0x180 0x80>;
> +		clocks = <&l4ls_gclk>;
> +		clock-names = "fck";
> +		interrupts = <79>;
> +	};

^ permalink raw reply

* Re: [PATCH 0/4] new driver for TI eQEP
From: Jonathan Cameron @ 2019-07-27 19:45 UTC (permalink / raw)
  To: David Lechner
  Cc: William Breathitt Gray, linux-iio, linux-omap, devicetree,
	Rob Herring, Mark Rutland, Benoît Cousson, Tony Lindgren,
	Thierry Reding, linux-kernel, linux-pwm
In-Reply-To: <4616508c-d753-586d-0d3b-5a003e86f582@lechnology.com>

On Thu, 25 Jul 2019 17:52:21 -0500
David Lechner <david@lechnology.com> wrote:

> On 7/25/19 7:40 AM, William Breathitt Gray wrote:
> > On Mon, Jul 22, 2019 at 10:45:34AM -0500, David Lechner wrote:  
> >> This series adds device tree bindings and a new counter driver for the Texas
> >> Instruments Enhanced Quadrature Encoder Pulse (eQEP).
> >>
> >> As mentioned in one of the commit messages, to start with, the driver only
> >> supports reading the current counter value and setting the min/max values.
> >> Other features can be added on an as-needed basis.
> >>
> >> The only other feature I am interested in is adding is getting time data in
> >> order to calculate the rotational speed of a motor. However, there probably
> >> needs to be a higher level discussion of how this can fit into the counter
> >> subsystem in general first.  
> > 
> > I believe exposing some sort of time data has merit. Quadrature counter
> > devices in particular are commonly used for position tracking of
> > automation systems, and such systems would benefit from velocity/speed
> > information. So let's try to introduce that sort of functionality in this
> > driver if possible.
> > 
> > First, let's discuss your specific use case and requirements, and hopefully we
> > can generalize it enough to be of use for future drivers. From your description,
> > it sounds like you're attaching some sort of rotary encoder to the eQEP device.
> > Is that correct? What sort of time data are you hoping to use; does the eQEP
> > device provide a clock value, or would you be grabbing a timestamp from the
> > system?  
> 
> My use case is robotics using LEGO MINDSTORMS. More specifically, I am using
> motors that have a cheap optical rotary encoder (plastic wheel and infrared
> LED/detectors) that give 360 counts per 1 rotation of the motor shaft. One count
> is defined as the rising edge or falling edge of the A signal. We are looking at
> anywhere from 0 to around 2000 counts per second. We use the speed as feedback in
> a control algorithm to drive the motor at a constant speed. The control loop
> updates on the order of 1 to 10 ms.
> 
> Because the encoder resolution and speeds are relatively low, we are currently
> logging a timestamp for each count. If no count occurs for 50ms, then we log the
> same count again with a new timestamp (otherwise we would never see 0 speed). To
> get the actual speed, we find the first timestamp > 20 ms before the current
> timestamp then compute the speed as the change in position divided by the change
> in time between these two samples. This give a fairly accurate speed across most
> of the range, but does get a bit noisy once we get below 100 counts per second.
> It also means that we need a ring buffer that holds about 50 samples.
> 
> The timestamp itself comes from the eQEP, not the system. There are latching
> registers to ensure that the timestamp read is from exactly the moment when
> the count register was read.
> 
>   
> > I'm not sure yet if it would make sense to expose rotational speed directly as
> > an attribute. If we were to expose just the count value and timestamp since the
> > last read, that should be enough for a user to compute the delta and derive
> > speed. I'll think more about this since some devices may simplify that case if
> > the hardware is able to compute the speed for us.
> >   
> 
> I agree that it probably doesn't make sense to expect drivers to compute the
> speed. There isn't really a general way to do that works for an arbitrary
> speed. For example at high speeds, it is better to just look at the change
> in counts over a fixed interval rather than triggering a timestamp based on
> a certain number of counts.

Worth noting perhaps that userspace has the same problem with knowing the
right approach...

> 
> I also don't think having a timestamp sysfs attribute would be very useful.
> To make it work at all, I think it would have to be implemented such that
> it returns the timestamp for the count that was most recently read via sysfs.
> And it would require 4 syscalls (2 seeks and 2 reads) to get a single count/
> timestamp pair in a control loop. On a 300MHz ARM9 processor, this is not
> a negligible amount of time.
> 
> I noticed that several of the other counter drivers also register an IIO
> device. So this got me thinking that perhaps the counter subsystem should
> just be for configuring a counter device an then the IIO subsystem should
> be used for triggers and ring buffers.
> 
> For the general case a counter device could have two possible triggers.
> One that triggers an interrupt after X counts and another that triggers
> with a period of T nanoseconds (or microseconds). Both triggers would add
> a count/timestamp pair to an IIO ring buffer.
> 
> To fully reproduce our current methodology the first trigger would actually
> need two configurable settings, the count X that triggers every X counts and
> a watchdog time setting (using terminology from eQEP docs) that will also
> trigger if and only if the count does not change before the time has elapsed.
> Note, this is different from the other proposed time based trigger which
> would cause a trigger interrupt at a fixed period regardless of whether
> the count changed or not.
> 
> ---
> 
> Thinking more generally though, I think what I would propose is adding a new
> component to the existing list of Count, Signal and Synapse. The new component
> could be called Event. Event would be more general than the trigger conditions
> I have just discussed. In addition to those two, it could be any event
> generated by the hardware, such as an error condition or a change in direction.
> 
> Drivers could register an arbitrary number of events for each Count, so we
> would have /sys/bus/counter/devices/counterX/eventY/*. There should be a few
> standard attributes, like "name" and "enable". Configurable events would need
> ext attributes to allow configuration.
> 
> However, I see that there are already preset and error_noise "events" for
> count objects, so maybe we don't do the eventY thing and keep it flatter (or
> is the counter subsystem still considered in "staging" where breaking ABI
> changes could be made?).

No.  I would say it can be extended but compatibility needs to be maintained.

> 
> When thinking about what events would actually do when enabled though, it
> seems like we should be using IIO events and triggers (we have found reading
> sysfs attributes to be insufficient performance-wise). It seems like unnecessary
> work to reproduce all of this in the counter subsystem. Which makes me wonder if
> it would be better to have counter devices just be a different device type (i.e.
> different struct device_type for dev->type) in the IIO subsystem instead of
> creating a completely new subsystem.

Hmm. That might have sort of worked, rather than the full split we went with
when it became clear counters really didn't fit the IIO model,
but it may not have come out cleanly and wouldn't have shared all that much code
(I think...) In particular the buffered paths in IIO present a large and
complex interface which would need to be replace given the different
fundamental structures in the counter abstraction.

It may be that the best thing to do here is to use very similar concepts
and implement some sort of kfifo interface for counters.  There may
well even be code to share, but I don't think we want to go back to 
trying to handle these as devices within IIO.

Tricky to know how well this would work without a prototype though...

Jonathan

^ permalink raw reply

* Re: [PATCH 3/3][V4] dt-bindings: iio: imu: add bindings for ADIS16460
From: Jonathan Cameron @ 2019-07-27 18:56 UTC (permalink / raw)
  To: Alexandru Ardelean
  Cc: linux-iio, linux-spi, devicetree, linux-kernel, robh+dt,
	mark.rutland, broonie, Rob Herring
In-Reply-To: <20190723073641.27801-4-alexandru.ardelean@analog.com>

On Tue, 23 Jul 2019 10:36:40 +0300
Alexandru Ardelean <alexandru.ardelean@analog.com> wrote:

> This change adds device-tree bindings for the ADIS16460.
> 
> Reviewed-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>

Really trivial, but convention (as driven by what git am -s does if nothing
else, is to add extra tags in chronological order.  So Rob would be after
you.  I tweaked it which I don't always remember to do.

It's not consistent across the kernel but I'll fight for my little corner
to be :)

Applied.

Thanks,

Jonathan

> ---
>  .../bindings/iio/imu/adi,adis16460.yaml       | 53 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 54 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml
> 
> diff --git a/Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml b/Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml
> new file mode 100644
> index 000000000000..0c53009ba7d6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml
> @@ -0,0 +1,53 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/iio/imu/adi,adis16460.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Analog Devices ADIS16460 and similar IMUs
> +
> +maintainers:
> +  - Dragos Bogdan <dragos.bogdan@analog.com>
> +
> +description: |
> +  Analog Devices ADIS16460 and similar IMUs
> +  https://www.analog.com/media/en/technical-documentation/data-sheets/ADIS16460.pdf
> +
> +properties:
> +  compatible:
> +    enum:
> +      - adi,adis16460
> +
> +  reg:
> +    maxItems: 1
> +
> +  spi-cpha: true
> +
> +  spi-cpol: true
> +
> +  interrupts:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +
> +examples:
> +  - |
> +    #include <dt-bindings/gpio/gpio.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    spi0 {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        imu@0 {
> +            compatible = "adi,adis16460";
> +            reg = <0>;
> +            spi-max-frequency = <5000000>;
> +            spi-cpol;
> +            spi-cpha;
> +            interrupt-parent = <&gpio0>;
> +            interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
> +        };
> +    };
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f7de89e82e35..07105e43ea1e 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -951,6 +951,7 @@ S:	Supported
>  L:	linux-iio@vger.kernel.org
>  W:	http://ez.analog.com/community/linux-device-drivers
>  F:	drivers/iio/imu/adis16460.c
> +F:	Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml
>  
>  ANALOG DEVICES INC ADP5061 DRIVER
>  M:	Stefan Popa <stefan.popa@analog.com>

^ permalink raw reply

* Re: [PATCH 2/3][V4] iio: imu: Add support for the ADIS16460 IMU
From: Jonathan Cameron @ 2019-07-27 18:54 UTC (permalink / raw)
  To: Alexandru Ardelean
  Cc: linux-iio, linux-spi, devicetree, linux-kernel, robh+dt,
	mark.rutland, broonie, Dragos Bogdan, Michael Hennerich
In-Reply-To: <20190723073641.27801-3-alexandru.ardelean@analog.com>

On Tue, 23 Jul 2019 10:36:39 +0300
Alexandru Ardelean <alexandru.ardelean@analog.com> wrote:

> The ADIS16460 device is a complete inertial system that includes a triaxial
> gyroscope and a triaxial accelerometer. It's more simplified design than
> that of the ADIS16480, and does not offer the triaxial magnetometers &
> pressure sensors. It does also have a temperature sensor (like the
> ADIS16480).
> Since it is part of the ADIS16XXX family, it re-uses parts of the ADIS
> library.
> 
> Naturally, the register map is different and much more simplified than the
> ADIS16480 subfamily, so it cannot be integrated into that driver. A major
> difference is that the registers are not paged.
> 
> One thing that is particularly special about it, is that it requires a
> higher delay between CS changes (i.e. when CS goes up, the spec recommends
> that it be brought down after a minimum of 16 uS).
> Other ADIS chips require (via spec) a minimum of 2 uS between CS changes.
> The kernel's 10 uS default should be fine for those other chips; they
> haven't been tested with lower CS change delays yet.
> 
> Datasheet:
>   https://www.analog.com/media/en/technical-documentation/data-sheets/adis16460.pdf
> 
> Signed-off-by: Dragos Bogdan <dragos.bogdan@analog.com>
> Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Applied to the togreg branch of iio.git and pushed out as testing.

Note there was a typo / variable naming inconsistency that I fixed up.
See inline.

Thanks,

Jonathan

> ---
>  MAINTAINERS                 |   7 +
>  drivers/iio/imu/Kconfig     |  12 +
>  drivers/iio/imu/Makefile    |   1 +
>  drivers/iio/imu/adis16460.c | 489 ++++++++++++++++++++++++++++++++++++
>  4 files changed, 509 insertions(+)
>  create mode 100644 drivers/iio/imu/adis16460.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 783569e3c4b4..f7de89e82e35 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -945,6 +945,13 @@ L:	linux-iio@vger.kernel.org
>  F:	include/linux/iio/imu/adis.h
>  F:	drivers/iio/imu/adis.c
>  
> +ANALOG DEVICES INC ADIS16460 DRIVER
> +M:	Dragos Bogdan <dragos.bogdan@analog.com>
> +S:	Supported
> +L:	linux-iio@vger.kernel.org
> +W:	http://ez.analog.com/community/linux-device-drivers
> +F:	drivers/iio/imu/adis16460.c
> +
>  ANALOG DEVICES INC ADP5061 DRIVER
>  M:	Stefan Popa <stefan.popa@analog.com>
>  L:	linux-pm@vger.kernel.org
> diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
> index 4957e6df447e..f3c7282321a8 100644
> --- a/drivers/iio/imu/Kconfig
> +++ b/drivers/iio/imu/Kconfig
> @@ -17,6 +17,18 @@ config ADIS16400
>  	  adis16365, adis16400 and adis16405 triaxial inertial sensors
>  	  (adis16400 series also have magnetometers).
>  
> +config ADIS16460
> +	tristate "Analog Devices ADIS16460 and similar IMU driver"
> +	depends on SPI
> +	select IIO_ADIS_LIB
> +	select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
> +	help
> +	  Say yes here to build support for Analog Devices ADIS16460 inertial
> +	  sensor.
> +
> +	  To compile this driver as a module, choose M here: the module will be
> +	  called adis16460.
> +
>  config ADIS16480
>  	tristate "Analog Devices ADIS16480 and similar IMU driver"
>  	depends on SPI
> diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
> index 9e452fce1aaf..4a6958865504 100644
> --- a/drivers/iio/imu/Makefile
> +++ b/drivers/iio/imu/Makefile
> @@ -5,6 +5,7 @@
>  
>  # When adding new entries keep the list in alphabetical order
>  obj-$(CONFIG_ADIS16400) += adis16400.o
> +obj-$(CONFIG_ADIS16460) += adis16460.o
>  obj-$(CONFIG_ADIS16480) += adis16480.o
>  
>  adis_lib-y += adis.o
> diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c
> new file mode 100644
> index 000000000000..db713cba75a2
> --- /dev/null
> +++ b/drivers/iio/imu/adis16460.c
> @@ -0,0 +1,489 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * ADIS16460 IMU driver
> + *
> + * Copyright 2019 Analog Devices Inc.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/module.h>
> +#include <linux/spi/spi.h>
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/imu/adis.h>
> +
> +#include <linux/debugfs.h>
> +
> +#define ADIS16460_REG_FLASH_CNT		0x00
> +#define ADIS16460_REG_DIAG_STAT		0x02
> +#define ADIS16460_REG_X_GYRO_LOW	0x04
> +#define ADIS16460_REG_X_GYRO_OUT	0x06
> +#define ADIS16460_REG_Y_GYRO_LOW	0x08
> +#define ADIS16460_REG_Y_GYRO_OUT	0x0A
> +#define ADIS16460_REG_Z_GYRO_LOW	0x0C
> +#define ADIS16460_REG_Z_GYRO_OUT	0x0E
> +#define ADIS16460_REG_X_ACCL_LOW	0x10
> +#define ADIS16460_REG_X_ACCL_OUT	0x12
> +#define ADIS16460_REG_Y_ACCL_LOW	0x14
> +#define ADIS16460_REG_Y_ACCL_OUT	0x16
> +#define ADIS16460_REG_Z_ACCL_LOW	0x18
> +#define ADIS16460_REG_Z_ACCL_OUT	0x1A
> +#define ADIS16460_REG_SMPL_CNTR		0x1C
> +#define ADIS16460_REG_TEMP_OUT		0x1E
> +#define ADIS16460_REG_X_DELT_ANG	0x24
> +#define ADIS16460_REG_Y_DELT_ANG	0x26
> +#define ADIS16460_REG_Z_DELT_ANG	0x28
> +#define ADIS16460_REG_X_DELT_VEL	0x2A
> +#define ADIS16460_REG_Y_DELT_VEL	0x2C
> +#define ADIS16460_REG_Z_DELT_VEL	0x2E
> +#define ADIS16460_REG_MSC_CTRL		0x32
> +#define ADIS16460_REG_SYNC_SCAL		0x34
> +#define ADIS16460_REG_DEC_RATE		0x36
> +#define ADIS16460_REG_FLTR_CTRL		0x38
> +#define ADIS16460_REG_GLOB_CMD		0x3E
> +#define ADIS16460_REG_X_GYRO_OFF	0x40
> +#define ADIS16460_REG_Y_GYRO_OFF	0x42
> +#define ADIS16460_REG_Z_GYRO_OFF	0x44
> +#define ADIS16460_REG_X_ACCL_OFF	0x46
> +#define ADIS16460_REG_Y_ACCL_OFF	0x48
> +#define ADIS16460_REG_Z_ACCL_OFF	0x4A
> +#define ADIS16460_REG_LOT_ID1		0x52
> +#define ADIS16460_REG_LOT_ID2		0x54
> +#define ADIS16460_REG_PROD_ID		0x56
> +#define ADIS16460_REG_SERIAL_NUM	0x58
> +#define ADIS16460_REG_CAL_SGNTR		0x60
> +#define ADIS16460_REG_CAL_CRC		0x62
> +#define ADIS16460_REG_CODE_SGNTR	0x64
> +#define ADIS16460_REG_CODE_CRC		0x66
> +
> +struct adis16460_chip_info {
> +	unsigned int num_channels;
> +	const struct iio_chan_spec *channels;
> +	unsigned int gyro_max_val;
> +	unsigned int gyro_max_scale;
> +	unsigned int accel_max_val;
> +	unsigned int accel_max_scale;
> +};
> +
> +struct adis16460 {
> +	const struct adis16460_chip_info *chip_info;
> +	struct adis adis;
> +};
> +
> +#ifdef CONFIG_DEBUG_FS
> +
> +static int adis16460_show_serial_number(void *arg, u64 *val)
> +{
> +	struct adis16460 *adis16460 = arg;
> +	u16 serial;
> +	int ret;
> +
> +	ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_SERIAL_NUM,
> +		&serial);
> +	if (ret < 0)
> +		return ret;
> +
> +	*val = serial;
> +
> +	return 0;
> +}
> +DEFINE_SIMPLE_ATTRIBUTE(adis16460_serial_number_fops,
> +	adis16460_show_serial_number, NULL, "0x%.4llx\n");
> +
> +static int adis16460_show_product_id(void *arg, u64 *val)
> +{
> +	struct adis16460 *adis16460 = arg;
> +	u16 prod_id;
> +	int ret;
> +
> +	ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_PROD_ID,
> +		&prod_id);
> +	if (ret < 0)
> +		return ret;
> +
> +	*val = prod_id;
> +
> +	return 0;
> +}
> +DEFINE_SIMPLE_ATTRIBUTE(adis16460_product_id_fops,
> +	adis16460_show_product_id, NULL, "%llu\n");
> +
> +static int adis16460_show_flash_count(void *arg, u64 *val)
> +{
> +	struct adis16460 *adis16460 = arg;
> +	u32 flash_count;
> +	int ret;
> +
> +	ret = adis_read_reg_32(&adis16460->adis, ADIS16460_REG_FLASH_CNT,
> +		&flash_count);
> +	if (ret < 0)
> +		return ret;
> +
> +	*val = flash_count;
> +
> +	return 0;
> +}
> +DEFINE_SIMPLE_ATTRIBUTE(adis16460_flash_count_fops,
> +	adis16460_show_flash_count, NULL, "%lld\n");
> +
> +static int adis16460_debugfs_init(struct iio_dev *indio_dev)
> +{
> +	struct adis16460 *adis16460 = iio_priv(indio_dev);
> +
> +	debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry,
> +		adis16460, &adis16460_serial_number_fops);
> +	debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry,
> +		adis16460, &adis16460_product_id_fops);
> +	debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry,
> +		adis16460, &adis16460_flash_count_fops);
> +
> +	return 0;
> +}
> +
> +#else
> +
> +static int adis16460_debugfs_init(struct iio_dev *indio_dev)
> +{
> +	return 0;
> +}
> +
> +#endif
> +
> +static int adis16460_set_freq(struct iio_dev *indio_dev, int val, int val2)
> +{
> +	struct adis16460 *st = iio_priv(indio_dev);
> +	unsigned int t;
> +
> +	t =  val * 1000 + val2 / 1000;
> +	if (t <= 0)
> +		return -EINVAL;
> +
> +	t = 2048000 / t;
> +	if (t > 2048)
> +		t = 2048;
> +
> +	if (t != 0)
> +		t--;
> +
> +	return adis_write_reg_16(&st->adis, ADIS16460_REG_DEC_RATE, t);
> +}
> +
> +static int adis16460_get_freq(struct iio_dev *indio_dev, int *val, int *val2)
> +{
> +	struct adis16460 *st = iio_priv(indio_dev);
> +	uint16_t t;
> +	int ret;
> +	unsigned int freq;
> +
> +	ret = adis_read_reg_16(&st->adis, ADIS16460_REG_DEC_RATE, &t);
> +	if (ret < 0)
> +		return ret;
> +
> +	freq = 2048000 / (t + 1);
> +	*val = freq / 1000;
> +	*val2 = (freq % 1000) * 1000;
> +
> +	return IIO_VAL_INT_PLUS_MICRO;
> +}
> +
> +static int adis16460_read_raw(struct iio_dev *indio_dev,
> +	const struct iio_chan_spec *chan, int *val, int *val2, long info)
> +{
> +	struct adis16460 *st = iio_priv(indio_dev);
> +
> +	switch (info) {
> +	case IIO_CHAN_INFO_RAW:
> +		return adis_single_conversion(indio_dev, chan, 0, val);
> +	case IIO_CHAN_INFO_SCALE:
> +		switch (chan->type) {
> +		case IIO_ANGL_VEL:
> +			*val = st->chip_info->gyro_max_scale;
> +			*val2 = st->chip_info->gyro_max_val;
> +			return IIO_VAL_FRACTIONAL;
> +		case IIO_ACCEL:
> +			*val = st->chip_info->accel_max_scale;
> +			*val2 = st->chip_info->accel_max_val;
> +			return IIO_VAL_FRACTIONAL;
> +		case IIO_TEMP:
> +			*val = 50; /* 50 milli degrees Celsius/LSB */
> +			return IIO_VAL_INT;
> +		default:
> +			return -EINVAL;
> +		}
> +	case IIO_CHAN_INFO_OFFSET:
> +		*val = 500; /* 25 degrees Celsius = 0x0000 */
> +		return IIO_VAL_INT;
> +	case IIO_CHAN_INFO_SAMP_FREQ:
> +		return adis16460_get_freq(indio_dev, val, val2);
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static int adis16460_write_raw(struct iio_dev *indio_dev,
> +	const struct iio_chan_spec *chan, int val, int val2, long info)
> +{
> +	switch (info) {
> +	case IIO_CHAN_INFO_SAMP_FREQ:
> +		return adis16460_set_freq(indio_dev, val, val2);
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +enum {
> +	ADIS16460_SCAN_GYRO_X,
> +	ADIS16460_SCAN_GYRO_Y,
> +	ADIS16460_SCAN_GYRO_Z,
> +	ADIS16460_SCAN_ACCEL_X,
> +	ADIS16460_SCAN_ACCEL_Y,
> +	ADIS16460_SCAN_ACCEL_Z,
> +	ADIS16460_SCAN_TEMP,
> +};
> +
> +#define ADIS16460_MOD_CHANNEL(_type, _mod, _address, _si, _bits) \
> +	{ \
> +		.type = (_type), \
> +		.modified = 1, \
> +		.channel2 = (_mod), \
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> +		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
> +		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
> +		.address = (_address), \
> +		.scan_index = (_si), \
> +		.scan_type = { \
> +			.sign = 's', \
> +			.realbits = (_bits), \
> +			.storagebits = (_bits), \
> +			.endianness = IIO_BE, \
> +		}, \
> +	}
> +
> +#define ADIS16460_GYRO_CHANNEL(_mod) \
> +	ADIS16460_MOD_CHANNEL(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \
> +	ADIS16460_REG_ ## _mod ## _GYRO_LOW, ADIS16460_SCAN_GYRO_ ## _mod, \
> +	32)
> +
> +#define ADIS16460_ACCEL_CHANNEL(_mod) \
> +	ADIS16460_MOD_CHANNEL(IIO_ACCEL, IIO_MOD_ ## _mod, \
> +	ADIS16460_REG_ ## _mod ## _ACCL_LOW, ADIS16460_SCAN_ACCEL_ ## _mod, \
> +	32)
> +
> +#define ADIS16460_TEMP_CHANNEL() { \
> +		.type = IIO_TEMP, \
> +		.indexed = 1, \
> +		.channel = 0, \
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
> +			BIT(IIO_CHAN_INFO_SCALE) | \
> +			BIT(IIO_CHAN_INFO_OFFSET), \
> +		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
> +		.address = ADIS16460_REG_TEMP_OUT, \
> +		.scan_index = ADIS16460_SCAN_TEMP, \
> +		.scan_type = { \
> +			.sign = 's', \
> +			.realbits = 16, \
> +			.storagebits = 16, \
> +			.endianness = IIO_BE, \
> +		}, \
> +	}
> +
> +static const struct iio_chan_spec adis16460_channels[] = {
> +	ADIS16460_GYRO_CHANNEL(X),
> +	ADIS16460_GYRO_CHANNEL(Y),
> +	ADIS16460_GYRO_CHANNEL(Z),
> +	ADIS16460_ACCEL_CHANNEL(X),
> +	ADIS16460_ACCEL_CHANNEL(Y),
> +	ADIS16460_ACCEL_CHANNEL(Z),
> +	ADIS16460_TEMP_CHANNEL(),
> +	IIO_CHAN_SOFT_TIMESTAMP(7)
> +};
> +
> +static const struct adis16460_chip_info adis16460_chip_info = {
> +	.channels = adis16460_channels,
> +	.num_channels = ARRAY_SIZE(adis16460_channels),
> +	/*
> +	 * storing the value in rad/degree and the scale in degree
> +	 * gives us the result in rad and better precession than
> +	 * storing the scale directly in rad.
> +	 */
> +	.gyro_max_val = IIO_RAD_TO_DEGREE(200 << 16),
> +	.gyro_max_scale = 1,
> +	.accel_max_val = IIO_M_S_2_TO_G(20000 << 16),
> +	.accel_max_scale = 5,
> +};
> +
> +static const struct iio_info adis16460_info = {
> +	.read_raw = &adis16460_read_raw,
> +	.write_raw = &adis16460_write_raw,
> +	.update_scan_mode = adis_update_scan_mode,
> +	.debugfs_reg_access = adis_debugfs_reg_access,
> +};
> +
> +static int adis16460_enable_irq(struct adis *adis, bool enable)
> +{
> +	/*
> +	 * There is no way to gate the data-ready signal internally inside the
> +	 * ADIS16460 :(
> +	 */
> +	if (enable)
> +		enable_irq(adis->spi->irq);
> +	else
> +		disable_irq(adis->spi->irq);
> +
> +	return 0;
> +}
> +
> +static int adis16460_initial_setup(struct iio_dev *indio_dev)
> +{
> +	struct adis16460 *st = iio_priv(indio_dev);
> +	uint16_t prod_id;
> +	unsigned int device_id;
> +	int ret;
> +
> +	adis_reset(&st->adis);
> +	msleep(222);
> +
> +	ret = adis_write_reg_16(&st->adis, ADIS16460_REG_GLOB_CMD, BIT(1));
> +	if (ret)
> +		return ret;
> +	msleep(75);
> +
> +	ret = adis_check_status(&st->adis);
> +	if (ret)
> +		return ret;
> +
> +	ret = adis_read_reg_16(&st->adis, ADIS16460_REG_PROD_ID, &prod_id);
> +	if (ret)
> +		return ret;
> +
> +	ret = sscanf(indio_dev->name, "adis%u\n", &device_id);
> +	if (ret != 1)
> +		return -EINVAL;
> +
> +	if (prod_id != device_id)
> +		dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
> +				device_id, prod_id);
> +
> +	return 0;
> +}
> +
> +#define ADIS16460_DIAG_STAT_IN_CLK_OOS	7
> +#define ADIS16460_DIAG_STAT_FLASH_MEM	6
> +#define ADIS16460_DIAG_STAT_SELF_TEST	5
> +#define ADIS16460_DIAG_STAT_OVERRANGE	4
> +#define ADIS16460_DIAG_STAT_SPI_COMM	3
> +#define ADIS16460_DIAG_STAT_FLASH_UPT	2
> +
> +static const char * const adis16460_status_error_msgs[] = {
> +	[ADIS16460_DIAG_STAT_IN_CLK_OOS] = "Input clock out of sync",
> +	[ADIS16460_DIAG_STAT_FLASH_MEM] = "Flash memory failure",
> +	[ADIS16460_DIAG_STAT_SELF_TEST] = "Self test diagnostic failure",
> +	[ADIS16460_DIAG_STAT_OVERRANGE] = "Sensor overrange",
> +	[ADIS16460_DIAG_STAT_SPI_COMM] = "SPI communication failure",
> +	[ADIS16460_DIAG_STAT_FLASH_UPT] = "Flash update failure",
> +};
> +
> +static const struct adis_data adis16460_data = {
> +	.diag_stat_reg = ADIS16460_REG_DIAG_STAT,
> +	.glob_cmd_reg = ADIS16460_REG_GLOB_CMD,
> +	.has_paging = false,
> +	.read_delay = 5,
> +	.write_delay = 5,
> +	.cs_change_delay = 16,
> +	.status_error_msgs = adis16460_status_error_msgs,
> +	.status_error_mask = BIT(ADIS16460_DIAG_STAT_IN_CLK_OOS) |
> +		BIT(ADIS16460_DIAG_STAT_FLASH_MEM) |
> +		BIT(ADIS16460_DIAG_STAT_SELF_TEST) |
> +		BIT(ADIS16460_DIAG_STAT_OVERRANGE) |
> +		BIT(ADIS16460_DIAG_STAT_SPI_COMM) |
> +		BIT(ADIS16460_DIAG_STAT_FLASH_UPT),
> +	.enable_irq = adis16460_enable_irq,
> +};
> +
> +static int adis16460_probe(struct spi_device *spi)
> +{
> +	struct iio_dev *indio_dev;
> +	struct adis16460 *st;
> +	int ret;
> +
> +	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
> +	if (indio_dev == NULL)
> +		return -ENOMEM;
> +
> +	spi_set_drvdata(spi, indio_dev);
> +
> +	st = iio_priv(indio_dev);
> +
> +	st->chip_info = &adis16460_chip_info;
> +	indio_dev->dev.parent = &spi->dev;
> +	indio_dev->name = spi_get_device_id(spi)->name;
> +	indio_dev->channels = st->chip_info->channels;
> +	indio_dev->num_channels = st->chip_info->num_channels;
> +	indio_dev->info = &adis16460_info;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +
> +	ret = adis_init(&st->adis, indio_dev, spi, &adis16460_data);
> +	if (ret)
> +		return ret;
> +
> +	ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL);
> +	if (ret)
> +		return ret;
> +
> +	adis16460_enable_irq(&st->adis, 0);
> +
> +	ret = adis16460_initial_setup(indio_dev);
> +	if (ret)
> +		goto error_cleanup_buffer;
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret)
> +		goto error_cleanup_buffer;
> +
> +	adis16460_debugfs_init(indio_dev);
> +
> +	return 0;
> +
> +error_cleanup_buffer:
> +	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
> +	return ret;
> +}
> +
> +static int adis16460_remove(struct spi_device *spi)
> +{
> +	struct iio_dev *indio_dev = spi_get_drvdata(spi);
> +	struct adis16460 *st = iio_priv(indio_dev);
> +
> +	iio_device_unregister(indio_dev);
> +
> +	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
> +
> +	return 0;
> +}
> +
> +static const struct spi_device_id adis16460_ids[] = {
this is plural, it's used below as singular
*_id;

I've fixed it up as ids everywhere.

Please check the result.

Jonathan

> +	{ "adis16460", 0 },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(spi, adis16460_id);
> +
> +static const struct of_device_id adis16460_of_match[] = {
> +	{ .compatible = "adi,adis16460" },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, adis16460_of_match);
> +
> +static struct spi_driver adis16460_driver = {
> +	.driver = {
> +		.name = "adis16460",
> +		.of_match_table = adis16460_of_match,
> +	},
> +	.id_table = adis16460_ids,
> +	.probe = adis16460_probe,
> +	.remove = adis16460_remove,
> +};
> +module_spi_driver(adis16460_driver);
> +
> +MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>");
> +MODULE_DESCRIPTION("Analog Devices ADIS16460 IMU driver");
> +MODULE_LICENSE("GPL");

^ permalink raw reply

* Re: [PATCH net-next 3/3] net: dsa: mt7530: Add support for port 5
From: Russell King - ARM Linux admin @ 2019-07-27 18:53 UTC (permalink / raw)
  To: René van Dorst
  Cc: netdev, frank-w, sean.wang, f.fainelli, davem, matthias.bgg,
	andrew, vivien.didelot, john, linux-mediatek, linux-mips, robh+dt,
	devicetree
In-Reply-To: <20190724192549.24615-4-opensource@vdorst.com>

On Wed, Jul 24, 2019 at 09:25:49PM +0200, René van Dorst wrote:
> Adding support for port 5.
> 
> Port 5 can muxed/interface to:
> - internal 5th GMAC of the switch; can be used as 2nd CPU port or as
>   extra port with an external phy for a 6th ethernet port.
> - internal PHY of port 0 or 4; Used in most applications so that port 0
>   or 4 is the WAN port and interfaces with the 2nd GMAC of the SOC.

...

> @@ -1381,15 +1506,19 @@ static void mt7530_phylink_validate(struct dsa_switch *ds, int port,
>  	phylink_set_port_modes(mask);
>  	phylink_set(mask, Autoneg);
>  
> -	if (state->interface != PHY_INTERFACE_MODE_TRGMII) {
> +	if (state->interface == PHY_INTERFACE_MODE_TRGMII) {
> +		phylink_set(mask, 1000baseT_Full);
> +	} else {
>  		phylink_set(mask, 10baseT_Half);
>  		phylink_set(mask, 10baseT_Full);
>  		phylink_set(mask, 100baseT_Half);
>  		phylink_set(mask, 100baseT_Full);
> -		phylink_set(mask, 1000baseT_Half);
> -	}
>  
> -	phylink_set(mask, 1000baseT_Full);
> +		if (state->interface != PHY_INTERFACE_MODE_MII) {
> +			phylink_set(mask, 1000baseT_Half);
> +			phylink_set(mask, 1000baseT_Full);
> +		}
> +	}

As port 5 could use an external PHY, and it supports gigabit speeds,
consider that the PHY may provide not only copper but also fiber
connectivity, so port 5 should probably also have 1000baseX modes
too, which would allow such a PHY to bridge the switch to fiber.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up

^ permalink raw reply

* Re: [PATCH net-next 1/3] net: dsa: mt7530: Convert to PHYLINK API
From: Russell King - ARM Linux admin @ 2019-07-27 18:48 UTC (permalink / raw)
  To: René van Dorst
  Cc: netdev, frank-w, sean.wang, f.fainelli, davem, matthias.bgg,
	andrew, vivien.didelot, john, linux-mediatek, linux-mips, robh+dt,
	devicetree
In-Reply-To: <20190724192549.24615-2-opensource@vdorst.com>

Hi,

Just a couple of minor points.

On Wed, Jul 24, 2019 at 09:25:47PM +0200, René van Dorst wrote:
> +static void mt7530_phylink_mac_config(struct dsa_switch *ds, int port,
> +				      unsigned int mode,
> +				      const struct phylink_link_state *state)
> +{
> +	struct mt7530_priv *priv = ds->priv;
> +	u32 mcr_cur, mcr_new;
> +
> +	switch (port) {
> +	case 0: /* Internal phy */
> +	case 1:
> +	case 2:
> +	case 3:
> +	case 4:
> +		if (state->interface != PHY_INTERFACE_MODE_GMII)
> +			return;
> +		break;
> +	/* case 5: Port 5 is not supported! */
> +	case 6: /* 1st cpu port */
> +		if (state->interface != PHY_INTERFACE_MODE_RGMII &&
> +		    state->interface != PHY_INTERFACE_MODE_TRGMII)
> +			return;
> +
> +		if (priv->p6_interface == state->interface)
> +			break;
> +		/* Setup TX circuit incluing relevant PAD and driving */
> +		mt7530_pad_clk_setup(ds, state->interface);
> +
> +		if (priv->id == ID_MT7530) {
> +			/* Setup RX circuit, relevant PAD and driving on the
> +			 * host which must be placed after the setup on the
> +			 * device side is all finished.
> +			 */
> +			mt7623_pad_clk_setup(ds);
> +		}
> +		priv->p6_interface = state->interface;
> +		break;
> +	default:
> +		dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);
> +		return;
> +	}

	if (phylink_autoneg_inband(mode)) {
		dev_err(ds->dev, "%s: in-band negotiation unsupported\n",
			__func__);
		return;
	}

or similar, since you don't support inband AN in this code path.

> +
> +	mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port));
> +	mcr_new = mcr_cur;
> +	mcr_new &= ~(PMCR_FORCE_SPEED_1000 | PMCR_FORCE_SPEED_100 |
> +		     PMCR_FORCE_FDX | PMCR_TX_FC_EN | PMCR_RX_FC_EN);
> +	mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN |
> +		   PMCR_BACKPR_EN | PMCR_FORCE_MODE | PMCR_FORCE_LNK;
> +
> +	switch (state->speed) {
> +	case SPEED_1000:
> +		mcr_new |= PMCR_FORCE_SPEED_1000;
> +		break;
> +	case SPEED_100:
> +		mcr_new |= PMCR_FORCE_SPEED_100;
> +		break;
> +	}
> +	if (state->duplex == DUPLEX_FULL) {
> +		mcr_new |= PMCR_FORCE_FDX;
> +		if (state->pause & MLO_PAUSE_TX)
> +			mcr_new |= PMCR_TX_FC_EN;
> +		if (state->pause & MLO_PAUSE_RX)
> +			mcr_new |= PMCR_RX_FC_EN;
> +	}
> +
> +	if (mcr_new != mcr_cur)
> +		mt7530_write(priv, MT7530_PMCR_P(port), mcr_new);
> +}
> +
> +static void mt7530_phylink_mac_link_down(struct dsa_switch *ds, int port,
> +					 unsigned int mode,
> +					 phy_interface_t interface)
> +{
> +	struct mt7530_priv *priv = ds->priv;
> +
> +	mt7530_port_set_status(priv, port, 0);
> +}
> +
> +static void mt7530_phylink_mac_link_up(struct dsa_switch *ds, int port,
> +				       unsigned int mode,
> +				       phy_interface_t interface,
> +				       struct phy_device *phydev)
> +{
> +	struct mt7530_priv *priv = ds->priv;
> +
> +	mt7530_port_set_status(priv, port, 1);
> +}
> +
> +static void mt7530_phylink_validate(struct dsa_switch *ds, int port,
> +				    unsigned long *supported,
> +				    struct phylink_link_state *state)
> +{
> +	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
> +
> +	switch (port) {
> +	case 0: /* Internal phy */
> +	case 1:
> +	case 2:
> +	case 3:
> +	case 4:
> +		if (state->interface != PHY_INTERFACE_MODE_NA &&
> +		    state->interface != PHY_INTERFACE_MODE_GMII)
> +			goto unsupported;
> +		break;
> +	/* case 5: Port 5 not supported! */
> +	case 6: /* 1st cpu port */
> +		if (state->interface != PHY_INTERFACE_MODE_NA &&
> +		    state->interface != PHY_INTERFACE_MODE_RGMII &&
> +		    state->interface != PHY_INTERFACE_MODE_TRGMII)
> +			goto unsupported;
> +		break;
> +	default:
> +		linkmode_zero(supported);
> +		dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);

You could reorder this as:

	default:
		dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);
	unsupported:
		linkmode_zero(supported);

and save having the "unsupported" at the end of the function.  Not sure
what DaveM would think of it though.


-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up
According to speedtest.net: 11.9Mbps down 500kbps up

^ permalink raw reply

* Re: [PATCH 1/3][V4] iio: imu: adis: Add support for SPI transfer cs_change_delay
From: Jonathan Cameron @ 2019-07-27 18:48 UTC (permalink / raw)
  To: Alexandru Ardelean
  Cc: linux-iio, linux-spi, devicetree, linux-kernel, robh+dt,
	mark.rutland, broonie, Michael Hennerich
In-Reply-To: <20190723073641.27801-2-alexandru.ardelean@analog.com>

On Tue, 23 Jul 2019 10:36:38 +0300
Alexandru Ardelean <alexandru.ardelean@analog.com> wrote:

> The ADIS16460 requires a higher delay before the next transfer. Since the
> SPI framework supports configuring the delay before the next transfer, this
> driver will become the first user of it.
> 
> The support for this functionality in ADIS16460 requires an addition to the
> ADIS lib to support the `cs_change_delay` functionality from the SPI
> subsystem.
> 
> Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Applied to the togreg branch of iio.git and pushed out as testing for
the autobuilders to play with it.

Thanks,

Jonathan

> ---
>  drivers/iio/imu/adis.c       | 12 ++++++++++++
>  include/linux/iio/imu/adis.h |  2 ++
>  2 files changed, 14 insertions(+)
> 
> diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
> index 30281e91dbf9..1631c255deab 100644
> --- a/drivers/iio/imu/adis.c
> +++ b/drivers/iio/imu/adis.c
> @@ -39,18 +39,24 @@ int adis_write_reg(struct adis *adis, unsigned int reg,
>  			.len = 2,
>  			.cs_change = 1,
>  			.delay_usecs = adis->data->write_delay,
> +			.cs_change_delay = adis->data->cs_change_delay,
> +			.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
>  		}, {
>  			.tx_buf = adis->tx + 2,
>  			.bits_per_word = 8,
>  			.len = 2,
>  			.cs_change = 1,
>  			.delay_usecs = adis->data->write_delay,
> +			.cs_change_delay = adis->data->cs_change_delay,
> +			.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
>  		}, {
>  			.tx_buf = adis->tx + 4,
>  			.bits_per_word = 8,
>  			.len = 2,
>  			.cs_change = 1,
>  			.delay_usecs = adis->data->write_delay,
> +			.cs_change_delay = adis->data->cs_change_delay,
> +			.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
>  		}, {
>  			.tx_buf = adis->tx + 6,
>  			.bits_per_word = 8,
> @@ -133,12 +139,16 @@ int adis_read_reg(struct adis *adis, unsigned int reg,
>  			.len = 2,
>  			.cs_change = 1,
>  			.delay_usecs = adis->data->write_delay,
> +			.cs_change_delay = adis->data->cs_change_delay,
> +			.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
>  		}, {
>  			.tx_buf = adis->tx + 2,
>  			.bits_per_word = 8,
>  			.len = 2,
>  			.cs_change = 1,
>  			.delay_usecs = adis->data->read_delay,
> +			.cs_change_delay = adis->data->cs_change_delay,
> +			.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
>  		}, {
>  			.tx_buf = adis->tx + 4,
>  			.rx_buf = adis->rx,
> @@ -146,6 +156,8 @@ int adis_read_reg(struct adis *adis, unsigned int reg,
>  			.len = 2,
>  			.cs_change = 1,
>  			.delay_usecs = adis->data->read_delay,
> +			.cs_change_delay = adis->data->cs_change_delay,
> +			.cs_change_delay_unit = SPI_DELAY_UNIT_USECS,
>  		}, {
>  			.rx_buf = adis->rx + 2,
>  			.bits_per_word = 8,
> diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h
> index 3428d06b2f44..4c53815bb729 100644
> --- a/include/linux/iio/imu/adis.h
> +++ b/include/linux/iio/imu/adis.h
> @@ -26,6 +26,7 @@ struct adis_burst;
>   * struct adis_data - ADIS chip variant specific data
>   * @read_delay: SPI delay for read operations in us
>   * @write_delay: SPI delay for write operations in us
> + * @cs_change_delay: SPI delay between CS changes in us
>   * @glob_cmd_reg: Register address of the GLOB_CMD register
>   * @msc_ctrl_reg: Register address of the MSC_CTRL register
>   * @diag_stat_reg: Register address of the DIAG_STAT register
> @@ -35,6 +36,7 @@ struct adis_burst;
>  struct adis_data {
>  	unsigned int read_delay;
>  	unsigned int write_delay;
> +	unsigned int cs_change_delay;
>  
>  	unsigned int glob_cmd_reg;
>  	unsigned int msc_ctrl_reg;

^ permalink raw reply

* Re: [PATCH net-next 3/3] net: dsa: mt7530: Add support for port 5
From: René van Dorst @ 2019-07-27 18:43 UTC (permalink / raw)
  To: David Miller
  Cc: netdev, frank-w, sean.wang, f.fainelli, linux, matthias.bgg,
	andrew, vivien.didelot, john, linux-mediatek, linux-mips, robh+dt,
	devicetree
In-Reply-To: <20190726.140420.688330328284393964.davem@davemloft.net>

Quoting David Miller <davem@davemloft.net>:

> From: René van Dorst <opensource@vdorst.com>
> Date: Wed, 24 Jul 2019 21:25:49 +0200
>
>> @@ -1167,6 +1236,10 @@ mt7530_setup(struct dsa_switch *ds)
>>  	u32 id, val;
>>  	struct device_node *dn;
>>  	struct mt7530_dummy_poll p;
>> +	phy_interface_t interface;
>> +	struct device_node *mac_np;
>> +	struct device_node *phy_node;
>> +	const __be32 *_id;
>

Hi David,

> Reverse christmas tree here please.
>
> Thank you.

OK, I shall change that.
I spin a new version.

Greats,

René

^ permalink raw reply

* Re: [PATCH net-next 3/3] net: dsa: mt7530: Add support for port 5
From: René van Dorst @ 2019-07-27 18:38 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: netdev, frank-w, sean.wang, linux, davem, matthias.bgg, andrew,
	vivien.didelot, john, linux-mediatek, linux-mips, robh+dt,
	devicetree
In-Reply-To: <f4a9e219-cd03-1512-874d-925c43e3c44f@gmail.com>

Quoting Florian Fainelli <f.fainelli@gmail.com>:

> On 7/24/2019 9:25 PM, René van Dorst wrote:
>> Adding support for port 5.
>>
>> Port 5 can muxed/interface to:
>> - internal 5th GMAC of the switch; can be used as 2nd CPU port or as
>>   extra port with an external phy for a 6th ethernet port.
>> - internal PHY of port 0 or 4; Used in most applications so that port 0
>>   or 4 is the WAN port and interfaces with the 2nd GMAC of the SOC.
>>
>> Signed-off-by: René van Dorst <opensource@vdorst.com>
>
> [snip]
>
>> +	/* Setup port 5 */
>> +	priv->p5_intf_sel = P5_DISABLED;
>> +	interface = PHY_INTERFACE_MODE_NA;
>> +
>> +	if (!dsa_is_unused_port(ds, 5)) {
>> +		priv->p5_intf_sel = P5_INTF_SEL_GMAC5;
>> +		interface = of_get_phy_mode(ds->ports[5].dn);
>> +	} else {
>> +		/* Scan the ethernet nodes. Look for GMAC1, Lookup used phy */
>> +		for_each_child_of_node(dn, mac_np) {
>> +			if (!of_device_is_compatible(mac_np,
>> +						     "mediatek,eth-mac"))
>> +				continue;
>> +			_id = of_get_property(mac_np, "reg", NULL);
>> +			if (be32_to_cpup(_id)  != 1)
>> +				continue;
>> +
>> +			interface = of_get_phy_mode(mac_np);
>> +			phy_node = of_parse_phandle(mac_np, "phy-handle", 0);
>> +
>> +			if (phy_node->parent == priv->dev->of_node->parent) {
>> +				_id = of_get_property(phy_node, "reg", NULL);
>> +				id = be32_to_cpup(_id);
>> +				if (id == 0)
>> +					priv->p5_intf_sel = P5_INTF_SEL_PHY_P0;
>> +				if (id == 4)
>> +					priv->p5_intf_sel = P5_INTF_SEL_PHY_P4;
>

Hi Florian,

> Can you use of_mdio_parse_addr() here?

Yes that function be used.

Thanks for mention this function.

I see that I can refactor this scan routine a bit more.
Also I missing a of_node_put(phy_node) at the end.

> --
> Florian

Greats,

René

^ permalink raw reply

* Re: [PATCH 2/5] MIPS: lantiq: use a generic "EBU" driver for Falcon and XWAY SoCs
From: Martin Blumenstingl @ 2019-07-27 18:37 UTC (permalink / raw)
  To: John Crispin
  Cc: tglx, jason, maz, ralf, paul.burton, jhogan, robh+dt, linux-mips,
	devicetree, linux-kernel, mark.rutland, Hauke Mehrtens
In-Reply-To: <d0ef8f73-3555-b53a-eb2b-40066827b6d9@phrozen.org>

Hi John,

On Sat, Jul 27, 2019 at 8:35 PM John Crispin <john@phrozen.org> wrote:
>
>
> On 27/07/2019 19:53, Martin Blumenstingl wrote:
> > + *  Copyright (C) 2011-2012 John Crispin<blogic@openwrt.org>
>
> could you change that to john@phrozen.org please
sure, I'll update it when I have to re-send this series


Martin

^ permalink raw reply

* Re: [PATCH 2/5] MIPS: lantiq: use a generic "EBU" driver for Falcon and XWAY SoCs
From: John Crispin @ 2019-07-27 18:35 UTC (permalink / raw)
  To: Martin Blumenstingl, tglx, jason, maz, ralf, paul.burton, jhogan,
	robh+dt, linux-mips, devicetree
  Cc: linux-kernel, mark.rutland, hauke
In-Reply-To: <20190727175315.28834-3-martin.blumenstingl@googlemail.com>


On 27/07/2019 19:53, Martin Blumenstingl wrote:
> + *  Copyright (C) 2011-2012 John Crispin<blogic@openwrt.org>

could you change that to john@phrozen.org please

     John

^ permalink raw reply

* Re: [PATCH 5/6] clk: imx8mq: Remove CLK_IS_CRITICAL flag for IMX8MQ_CLK_TMU_ROOT
From: Guido Günther @ 2019-07-27 18:26 UTC (permalink / raw)
  To: Daniel Baluta
  Cc: Anson Huang, Mark Rutland, Carlo Caione, Angus Ainslie (Purism),
	Leonard Crestez, Fabio Estevam, linux-clk, Abel Vesa,
	Andrey Smirnov, daniel.lezcano, dl-linux-imx, rui.zhang,
	Michael Turquette, Devicetree List, linux-pm, Sascha Hauer,
	edubezval, Rob Herring, linux-arm-kernel, Stephen Boyd,
	Linux Kernel Mailing List
In-Reply-To: <CAEnQRZAZNMBx3ApVmRP8hYPw0XY_QgR-saE6WLcT8oZmHPCxSA@mail.gmail.com>

Hi Daniel,
On Sat, Jul 27, 2019 at 01:26:50AM +0300, Daniel Baluta wrote:
> Hi all,
> 
> latest linux-next hangs at boot.
> 
> commit fde50b96be821ac9673a7e00847cc4605bd88f34 (HEAD -> master, tag:
> next-20190726, origin/master, origin/HEAD)
> Author: Stephen Rothwell <sfr@canb.auug.org.au>
> Date:   Fri Jul 26 15:18:02 2019 +1000
> 
>     Add linux-next specific files for 20190726
> 
>     Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
> 
> 
> I know this is crazy but reverting commit:
> 
> commit 431bdd1df48ee2896ea9980d9153e3aeaf0c81ef (refs/bisect/bad)
> Author: Anson Huang <Anson.Huang@nxp.com>
> Date:   Fri Jul 5 12:56:11 2019 +0800
> 
>     clk: imx8mq: Remove CLK_IS_CRITICAL flag for IMX8MQ_CLK_TMU_ROOT
> 
>     IMX8MQ_CLK_TMU_ROOT is ONLY used for thermal module, the driver
>     should manage this clock, so no need to have CLK_IS_CRITICAL flag
>     set.
> 
> 
> 
> makes the boot work again.

I noticed a boot hang yesterday on next-20190726 when loading the
qoriq_thermal which I worked around by blacklisting it. The
fsl,imx8mq-tmu node specifies a clock (IMX8MQ_CLK_TMU_ROOT) but does not
seem to enable, shouldn't it do so?

Cheers,
 -- Guido

^ permalink raw reply

* [PATCH 5/5] MIPS: dts: lantiq: danube: easy50712: route the PCI_INTA IRQ through EBU
From: Martin Blumenstingl @ 2019-07-27 17:53 UTC (permalink / raw)
  To: tglx, jason, maz, ralf, paul.burton, jhogan, robh+dt, linux-mips,
	devicetree
  Cc: linux-kernel, mark.rutland, john, hauke, Martin Blumenstingl
In-Reply-To: <20190727175315.28834-1-martin.blumenstingl@googlemail.com>

EBU provides an interrupt line for the PCI_INTA interrupt. Route
easy50712's PCI interrupt to EBU so the interrupt line is configured
correctly (using IRQ_TYPE_LEVEL_LOW, this was previously hardcoded in
the PCI driver) and ACKed properly.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
 arch/mips/boot/dts/lantiq/easy50712.dts | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/mips/boot/dts/lantiq/easy50712.dts b/arch/mips/boot/dts/lantiq/easy50712.dts
index 1ce20b7d05cb..33c26b93cfc9 100644
--- a/arch/mips/boot/dts/lantiq/easy50712.dts
+++ b/arch/mips/boot/dts/lantiq/easy50712.dts
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 /dts-v1/;
 
+#include <dt-bindings/interrupt-controller/irq.h>
+
 /include/ "danube.dtsi"
 
 / {
@@ -105,7 +107,7 @@
 			lantiq,bus-clock = <33333333>;
 			interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 			interrupt-map = <
-				0x7000 0 0 1 &icu0 29 1 // slot 14, irq 29
+				0x7000 0 0 1 &ebu0 0 IRQ_TYPE_LEVEL_LOW // slot 14
 			>;
 			gpios-reset = <&gpio 21 0>;
 			req-mask = <0x1>;		/* GNT1 */
-- 
2.22.0

^ permalink raw reply related

* [PATCH 4/5] MIPS: dts: lantiq: danube: mark the ebu0 node as interrupt-controller
From: Martin Blumenstingl @ 2019-07-27 17:53 UTC (permalink / raw)
  To: tglx, jason, maz, ralf, paul.burton, jhogan, robh+dt, linux-mips,
	devicetree
  Cc: linux-kernel, mark.rutland, john, hauke, Martin Blumenstingl
In-Reply-To: <20190727175315.28834-1-martin.blumenstingl@googlemail.com>

The EBU IP block provides one interrupt line for PCI_INTA. Mark the ebu0
node as interrupt-controller and pass the parent interrupt from ICU so
the PCI_INTA interrupt from EBU can be used.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
 arch/mips/boot/dts/lantiq/danube.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/mips/boot/dts/lantiq/danube.dtsi b/arch/mips/boot/dts/lantiq/danube.dtsi
index 510be63c8bdf..0208174b53c8 100644
--- a/arch/mips/boot/dts/lantiq/danube.dtsi
+++ b/arch/mips/boot/dts/lantiq/danube.dtsi
@@ -89,6 +89,9 @@
 		ebu0: ebu@e105300 {
 			compatible = "lantiq,ebu-xway";
 			reg = <0xe105300 0x100>;
+			interrupt-parent = <&icu0>;
+			interrupts = <30>;
+			#interrupt-cells = <2>;
 		};
 
 		pci0: pci@e105400 {
-- 
2.22.0

^ permalink raw reply related

* [PATCH 3/5] MIPS: lantiq: add an irq_domain and irq_chip for EBU
From: Martin Blumenstingl @ 2019-07-27 17:53 UTC (permalink / raw)
  To: tglx, jason, maz, ralf, paul.burton, jhogan, robh+dt, linux-mips,
	devicetree
  Cc: linux-kernel, mark.rutland, john, hauke, Martin Blumenstingl
In-Reply-To: <20190727175315.28834-1-martin.blumenstingl@googlemail.com>

The PCI_INTA on Lantiq SoCs is a chained interrupt:
EBU configures the interrupt type, has a registers to enable/disable
and ACK the interrupt. This is chained with the ICU interrupt where the
parent interrupt of the EBU IRQ has to be ACK'ed.

Move all EBU interrupt logic into ebu.c and expose it using an
irq_domain and irq_chip.
Drop the hardcoded EBU interrupt configuration from pci-lantiq.c as this
can now be expressed in device tree by passing the EBU interrupt line to
PCI_INTA (using for example "... &ebu0 0 IRQ_TYPE_LEVEL_LOW").
Also drop the EBU interrupt masking from irq.c because that's now
managed by EBU's own irq_ack callback.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
 .../include/asm/mach-lantiq/xway/lantiq_soc.h |   3 -
 arch/mips/lantiq/ebu.c                        | 149 ++++++++++++++++++
 arch/mips/lantiq/irq.c                        |  11 --
 arch/mips/pci/pci-lantiq.c                    |   4 -
 4 files changed, 149 insertions(+), 18 deletions(-)

diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 02a64ad6c0cc..5555deb02397 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -79,9 +79,6 @@ extern __iomem void *ltq_cgu_membase;
 #define LTQ_EARLY_ASC		KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
 
 /* EBU - external bus unit */
-#define LTQ_EBU_PCC_CON		0x0090
-#define LTQ_EBU_PCC_IEN		0x00A4
-#define LTQ_EBU_PCC_ISTAT	0x00A0
 #define LTQ_EBU_BUSCON1		0x0064
 #define LTQ_EBU_ADDRSEL1	0x0024
 
diff --git a/arch/mips/lantiq/ebu.c b/arch/mips/lantiq/ebu.c
index b2e84cf83f91..12951eb3c88f 100644
--- a/arch/mips/lantiq/ebu.c
+++ b/arch/mips/lantiq/ebu.c
@@ -7,7 +7,11 @@
 #include <linux/bits.h>
 #include <linux/export.h>
 #include <linux/ioport.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
 
@@ -15,6 +19,19 @@
 
 #define LTQ_EBU_BUSCON0				0x0060
 #define LTQ_EBU_BUSCON_WRDIS			BIT(31)
+#define LTQ_EBU_PCC_CON				0x0090
+#define LTQ_EBU_PCC_CON_PCCARD_ON		BIT(0)
+#define LTQ_EBU_PCC_CON_IREQ_RISING_EDGE        0x2
+#define LTQ_EBU_PCC_CON_IREQ_FALLING_EDGE       0x4
+#define LTQ_EBU_PCC_CON_IREQ_BOTH_EDGE          0x6
+#define LTQ_EBU_PCC_CON_IREQ_DIS                0x8
+#define LTQ_EBU_PCC_CON_IREQ_HIGH_LEVEL_DETECT  0xa
+#define LTQ_EBU_PCC_CON_IREQ_LOW_LEVEL_DETECT	0xc
+#define LTQ_EBU_PCC_CON_IREQ_MASK		0xe
+#define LTQ_EBU_PCC_ISTAT			0x00a0
+#define LTQ_EBU_PCC_ISTAT_PCI			BIT(4)
+#define LTQ_EBU_PCC_IEN				0x00a4
+#define LTQ_EBU_PCC_IEN_PCI_EN			BIT(4)
 
 void __iomem *ltq_ebu_membase;
 
@@ -52,6 +69,131 @@ static const struct of_device_id of_ebu_ids[] __initconst = {
 	{ /* sentinel */ },
 };
 
+static void ltq_ebu_ack_irq(struct irq_data *d)
+{
+	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | LTQ_EBU_PCC_ISTAT_PCI,
+		    LTQ_EBU_PCC_ISTAT);
+}
+
+static void ltq_ebu_mask_irq(struct irq_data *d)
+{
+	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) & ~LTQ_EBU_PCC_IEN_PCI_EN,
+		    LTQ_EBU_PCC_IEN);
+}
+
+static void ltq_ebu_unmask_irq(struct irq_data *d)
+{
+	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | LTQ_EBU_PCC_IEN_PCI_EN,
+		    LTQ_EBU_PCC_IEN);
+}
+
+static int ltq_ebu_set_irq_type(struct irq_data *d, unsigned int flow_type)
+{
+	u32 val = ltq_ebu_r32(LTQ_EBU_PCC_CON);
+
+	val &= ~LTQ_EBU_PCC_CON_IREQ_MASK;
+
+	switch (flow_type & IRQ_TYPE_SENSE_MASK) {
+	case IRQ_TYPE_NONE:
+		val |= LTQ_EBU_PCC_CON_IREQ_DIS;
+		break;
+
+	case IRQ_TYPE_EDGE_RISING:
+		val |= LTQ_EBU_PCC_CON_IREQ_RISING_EDGE;
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+		val |= LTQ_EBU_PCC_CON_IREQ_FALLING_EDGE;
+		break;
+
+	case IRQ_TYPE_EDGE_BOTH:
+		val |= LTQ_EBU_PCC_CON_IREQ_BOTH_EDGE;
+		break;
+
+	case IRQ_TYPE_LEVEL_HIGH:
+		val |= LTQ_EBU_PCC_CON_IREQ_HIGH_LEVEL_DETECT;
+		break;
+
+	case IRQ_TYPE_LEVEL_LOW:
+		val |= LTQ_EBU_PCC_CON_IREQ_LOW_LEVEL_DETECT;
+		break;
+
+	default:
+		pr_err("Invalid trigger mode %x for IRQ %d\n", flow_type,
+		       d->irq);
+		return -EINVAL;
+	}
+
+	ltq_ebu_w32(val, LTQ_EBU_PCC_CON);
+
+	return 0;
+}
+
+static void ltq_ebu_irq_handler(struct irq_desc *desc)
+{
+	struct irq_domain *domain = irq_desc_get_handler_data(desc);
+	struct irq_chip *irqchip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(irqchip, desc);
+
+	generic_handle_irq(irq_find_mapping(domain, 0));
+
+	chained_irq_exit(irqchip, desc);
+}
+
+static struct irq_chip ltq_ebu_irq_chip = {
+	.name = "EBU",
+	.irq_ack = ltq_ebu_ack_irq,
+	.irq_mask = ltq_ebu_mask_irq,
+	.irq_unmask = ltq_ebu_unmask_irq,
+	.irq_set_type = ltq_ebu_set_irq_type,
+};
+
+static int ltq_ebu_irq_map(struct irq_domain *domain, unsigned int irq,
+			   irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(irq, &ltq_ebu_irq_chip, handle_edge_irq);
+	irq_set_chip_data(irq, domain->host_data);
+
+	return 0;
+}
+
+static const struct irq_domain_ops ltq_ebu_irqdomain_ops = {
+	.map = ltq_ebu_irq_map,
+	.xlate = irq_domain_xlate_twocell,
+};
+
+static int ltq_ebu_add_irqchip(struct device_node *np)
+{
+	struct irq_domain *parent_domain, *domain;
+	int irq;
+
+	parent_domain = irq_find_host(of_irq_find_parent(np));
+	if (!parent_domain) {
+		pr_err("%pOF: No interrupt-parent found\n", np);
+		return -EINVAL;
+	}
+
+	domain = irq_domain_add_linear(np, 1, &ltq_ebu_irqdomain_ops, NULL);
+	if (!domain) {
+		pr_err("%pOF: Could not register EBU IRQ domain\n", np);
+		return -ENOMEM;
+	}
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (!irq) {
+		pr_err("%pOF: Failed to map interrupt\n", np);
+		irq_domain_remove(domain);
+		return -EINVAL;
+	}
+
+	irq_create_mapping(domain, 0);
+
+	irq_set_chained_handler_and_data(irq, ltq_ebu_irq_handler, domain);
+
+	return 0;
+}
+
 static int __init ltq_ebu_setup(void)
 {
 	const struct ltq_ebu_data *ebu_data;
@@ -59,6 +201,7 @@ static int __init ltq_ebu_setup(void)
 	struct resource res_ebu;
 	struct device_node *np;
 	u32 val;
+	int ret;
 
 	np = of_find_matching_node_and_match(NULL, of_ebu_ids, &match);
 	if (!np)
@@ -83,6 +226,12 @@ static int __init ltq_ebu_setup(void)
 		ltq_ebu_w32(val, LTQ_EBU_BUSCON0);
 	}
 
+	if (of_property_read_bool(np, "interrupt-controller")) {
+		ret = ltq_ebu_add_irqchip(np);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index 115b417dfb8e..cb9ab51fa748 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -40,12 +40,6 @@
 /* the performance counter */
 #define LTQ_PERF_IRQ		(INT_NUM_IM4_IRL0 + 31)
 
-/*
- * irqs generated by devices attached to the EBU need to be acked in
- * a special manner
- */
-#define LTQ_ICU_EBU_IRQ		22
-
 #define ltq_icu_w32(vpe, m, x, y)	\
 	ltq_w32((x), ltq_icu_membase[vpe] + m*LTQ_ICU_IM_SIZE + (y))
 
@@ -300,11 +294,6 @@ static void ltq_hw_irq_handler(struct irq_desc *desc)
 	irq = __fls(irq);
 	hwirq = irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module);
 	generic_handle_irq(irq_linear_revmap(ltq_domain, hwirq));
-
-	/* if this is a EBU irq, we need to ack it or get a deadlock */
-	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT)
-		ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10,
-			LTQ_EBU_PCC_ISTAT);
 }
 
 static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c
index 1ca42f482130..a3f6ab94ee2c 100644
--- a/arch/mips/pci/pci-lantiq.c
+++ b/arch/mips/pci/pci-lantiq.c
@@ -190,10 +190,6 @@ static int ltq_pci_startup(struct platform_device *pdev)
 	ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_MOD) | (1 << 24), PCI_CR_PCI_MOD);
 	wmb();
 
-	/* setup irq line */
-	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_CON) | 0xc, LTQ_EBU_PCC_CON);
-	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN);
-
 	/* toggle reset pin */
 	if (gpio_is_valid(reset_gpio)) {
 		__gpio_set_value(reset_gpio, 0);
-- 
2.22.0

^ permalink raw reply related

* [PATCH 2/5] MIPS: lantiq: use a generic "EBU" driver for Falcon and XWAY SoCs
From: Martin Blumenstingl @ 2019-07-27 17:53 UTC (permalink / raw)
  To: tglx, jason, maz, ralf, paul.burton, jhogan, robh+dt, linux-mips,
	devicetree
  Cc: linux-kernel, mark.rutland, john, hauke, Martin Blumenstingl
In-Reply-To: <20190727175315.28834-1-martin.blumenstingl@googlemail.com>

Both SoC types have the EBU registers and exposing the ltq_ebu_membase
in (the SoC-independent) arch/mips/include/asm/mach-lantiq/lantiq.h.
The only difference is the initialization logic: XWAY clears the WRDIS
(write disable) bit of the BUSCON0 register, while Falcon leaves it as
is.

Move the existing EBU logic from the Falcon and XWAY SoC types into a
generic driver.
This will make it easier to add the PCI irq controller which is provided
by EBU on at least the XWAY SoCs.

No functional changes intended.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
 .../include/asm/mach-lantiq/xway/lantiq_soc.h |  2 -
 arch/mips/lantiq/Makefile                     |  2 +-
 arch/mips/lantiq/ebu.c                        | 89 +++++++++++++++++++
 arch/mips/lantiq/falcon/sysctrl.c             | 17 ++--
 arch/mips/lantiq/xway/sysctrl.c               | 21 ++---
 5 files changed, 100 insertions(+), 31 deletions(-)
 create mode 100644 arch/mips/lantiq/ebu.c

diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 4790cfa190d6..02a64ad6c0cc 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -79,13 +79,11 @@ extern __iomem void *ltq_cgu_membase;
 #define LTQ_EARLY_ASC		KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
 
 /* EBU - external bus unit */
-#define LTQ_EBU_BUSCON0		0x0060
 #define LTQ_EBU_PCC_CON		0x0090
 #define LTQ_EBU_PCC_IEN		0x00A4
 #define LTQ_EBU_PCC_ISTAT	0x00A0
 #define LTQ_EBU_BUSCON1		0x0064
 #define LTQ_EBU_ADDRSEL1	0x0024
-#define EBU_WRDIS		0x80000000
 
 /* WDT */
 #define LTQ_RST_CAUSE_WDTRST	0x20
diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile
index e7234ca093b9..e92f62f02ec1 100644
--- a/arch/mips/lantiq/Makefile
+++ b/arch/mips/lantiq/Makefile
@@ -2,7 +2,7 @@
 # Copyright (C) 2010 John Crispin <john@phrozen.org>
 #
 
-obj-y := irq.o clk.o prom.o
+obj-y := irq.o clk.o ebu.o prom.o
 
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
 
diff --git a/arch/mips/lantiq/ebu.c b/arch/mips/lantiq/ebu.c
new file mode 100644
index 000000000000..b2e84cf83f91
--- /dev/null
+++ b/arch/mips/lantiq/ebu.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  Copyright (C) 2019 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ *  Copyright (C) 2011-2012 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/bits.h>
+#include <linux/export.h>
+#include <linux/ioport.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+
+#include <lantiq_soc.h>
+
+#define LTQ_EBU_BUSCON0				0x0060
+#define LTQ_EBU_BUSCON_WRDIS			BIT(31)
+
+void __iomem *ltq_ebu_membase;
+
+struct ltq_ebu_data {
+	bool		initialize_buscon0_wrdis;
+};
+
+static const struct ltq_ebu_data ltq_ebu_falcon_data = {
+	.initialize_buscon0_wrdis = false,
+};
+
+static const struct ltq_ebu_data ltq_ebu_xway_data = {
+	.initialize_buscon0_wrdis = true,
+};
+
+static const struct of_device_id of_ebu_ids[] __initconst = {
+	{
+		/* DEPRECATED */
+		.compatible = "lantiq,ebu-falcon",
+		.data = &ltq_ebu_falcon_data,
+	},
+	{
+		.compatible = "lantiq,falcon-ebu",
+		.data = &ltq_ebu_falcon_data,
+	},
+	{
+		/* DEPRECATED */
+		.compatible = "lantiq,ebu-xway",
+		.data = &ltq_ebu_xway_data,
+	},
+	{
+		.compatible = "lantiq,xway-ebu",
+		.data = &ltq_ebu_xway_data,
+	},
+	{ /* sentinel */ },
+};
+
+static int __init ltq_ebu_setup(void)
+{
+	const struct ltq_ebu_data *ebu_data;
+	const struct of_device_id *match;
+	struct resource res_ebu;
+	struct device_node *np;
+	u32 val;
+
+	np = of_find_matching_node_and_match(NULL, of_ebu_ids, &match);
+	if (!np)
+		panic("Failed to load the EBU node from devicetree");
+
+	if (of_address_to_resource(np, 0, &res_ebu))
+		panic("Failed to get the EBU resources");
+
+	if ((request_mem_region(res_ebu.start, resource_size(&res_ebu),
+				res_ebu.name) < 0))
+		pr_err("Failed to request the EBU resources");
+
+	ltq_ebu_membase = ioremap_nocache(res_ebu.start,
+						resource_size(&res_ebu));
+	if (!ltq_ebu_membase)
+		panic("Failed to remap the EBU resources");
+
+	ebu_data = match->data;
+
+	if (ebu_data && ebu_data->initialize_buscon0_wrdis) {
+		val = ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~LTQ_EBU_BUSCON_WRDIS;
+		ltq_ebu_w32(val, LTQ_EBU_BUSCON0);
+	}
+
+	return 0;
+}
+
+arch_initcall(ltq_ebu_setup);
diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c
index 037b08f3257e..1637c6f1d8f3 100644
--- a/arch/mips/lantiq/falcon/sysctrl.c
+++ b/arch/mips/lantiq/falcon/sysctrl.c
@@ -70,7 +70,7 @@
 #define status_r32(x)		ltq_r32(status_membase + (x))
 
 static void __iomem *sysctl_membase[3], *status_membase;
-void __iomem *ltq_sys1_membase, *ltq_ebu_membase;
+void __iomem *ltq_sys1_membase;
 
 void falcon_trigger_hrst(int level)
 {
@@ -184,23 +184,20 @@ void __init ltq_soc_init(void)
 {
 	struct device_node *np_status =
 		of_find_compatible_node(NULL, NULL, "lantiq,status-falcon");
-	struct device_node *np_ebu =
-		of_find_compatible_node(NULL, NULL, "lantiq,ebu-falcon");
 	struct device_node *np_sys1 =
 		of_find_compatible_node(NULL, NULL, "lantiq,sys1-falcon");
 	struct device_node *np_syseth =
 		of_find_compatible_node(NULL, NULL, "lantiq,syseth-falcon");
 	struct device_node *np_sysgpe =
 		of_find_compatible_node(NULL, NULL, "lantiq,sysgpe-falcon");
-	struct resource res_status, res_ebu, res_sys[3];
+	struct resource res_status, res_sys[3];
 	int i;
 
 	/* check if all the core register ranges are available */
-	if (!np_status || !np_ebu || !np_sys1 || !np_syseth || !np_sysgpe)
+	if (!np_status || !np_sys1 || !np_syseth || !np_sysgpe)
 		panic("Failed to load core nodes from devicetree");
 
 	if (of_address_to_resource(np_status, 0, &res_status) ||
-			of_address_to_resource(np_ebu, 0, &res_ebu) ||
 			of_address_to_resource(np_sys1, 0, &res_sys[0]) ||
 			of_address_to_resource(np_syseth, 0, &res_sys[1]) ||
 			of_address_to_resource(np_sysgpe, 0, &res_sys[2]))
@@ -208,8 +205,6 @@ void __init ltq_soc_init(void)
 
 	if ((request_mem_region(res_status.start, resource_size(&res_status),
 				res_status.name) < 0) ||
-		(request_mem_region(res_ebu.start, resource_size(&res_ebu),
-				res_ebu.name) < 0) ||
 		(request_mem_region(res_sys[0].start,
 				resource_size(&res_sys[0]),
 				res_sys[0].name) < 0) ||
@@ -223,11 +218,9 @@ void __init ltq_soc_init(void)
 
 	status_membase = ioremap_nocache(res_status.start,
 					resource_size(&res_status));
-	ltq_ebu_membase = ioremap_nocache(res_ebu.start,
-					resource_size(&res_ebu));
 
-	if (!status_membase || !ltq_ebu_membase)
-		panic("Failed to remap core resources");
+	if (!status_membase)
+		panic("Failed to remap status resource");
 
 	for (i = 0; i < 3; i++) {
 		sysctl_membase[i] = ioremap_nocache(res_sys[i].start,
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index 156a95ac5c72..ae3f35884036 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -145,7 +145,6 @@ static u32 pmu_clk_cr_b[] = {
 
 static void __iomem *pmu_membase;
 void __iomem *ltq_cgu_membase;
-void __iomem *ltq_ebu_membase;
 
 static u32 ifccr = CGU_IFCCR;
 static u32 pcicr = CGU_PCICR;
@@ -406,42 +405,32 @@ static void clkdev_add_clkout(void)
 /* bring up all register ranges that we need for basic system control */
 void __init ltq_soc_init(void)
 {
-	struct resource res_pmu, res_cgu, res_ebu;
+	struct resource res_pmu, res_cgu;
 	struct device_node *np_pmu =
 			of_find_compatible_node(NULL, NULL, "lantiq,pmu-xway");
 	struct device_node *np_cgu =
 			of_find_compatible_node(NULL, NULL, "lantiq,cgu-xway");
-	struct device_node *np_ebu =
-			of_find_compatible_node(NULL, NULL, "lantiq,ebu-xway");
 
 	/* check if all the core register ranges are available */
-	if (!np_pmu || !np_cgu || !np_ebu)
+	if (!np_pmu || !np_cgu)
 		panic("Failed to load core nodes from devicetree");
 
 	if (of_address_to_resource(np_pmu, 0, &res_pmu) ||
-			of_address_to_resource(np_cgu, 0, &res_cgu) ||
-			of_address_to_resource(np_ebu, 0, &res_ebu))
+			of_address_to_resource(np_cgu, 0, &res_cgu))
 		panic("Failed to get core resources");
 
 	if (!request_mem_region(res_pmu.start, resource_size(&res_pmu),
 				res_pmu.name) ||
 		!request_mem_region(res_cgu.start, resource_size(&res_cgu),
-				res_cgu.name) ||
-		!request_mem_region(res_ebu.start, resource_size(&res_ebu),
-				res_ebu.name))
+				res_cgu.name))
 		pr_err("Failed to request core resources");
 
 	pmu_membase = ioremap_nocache(res_pmu.start, resource_size(&res_pmu));
 	ltq_cgu_membase = ioremap_nocache(res_cgu.start,
 						resource_size(&res_cgu));
-	ltq_ebu_membase = ioremap_nocache(res_ebu.start,
-						resource_size(&res_ebu));
-	if (!pmu_membase || !ltq_cgu_membase || !ltq_ebu_membase)
+	if (!pmu_membase || !ltq_cgu_membase)
 		panic("Failed to remap core resources");
 
-	/* make sure to unprotect the memory region where flash is located */
-	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
-
 	/* add our generic xway clocks */
 	clkdev_add_pmu("10000000.fpi", NULL, 0, 0, PMU_FPI);
 	clkdev_add_pmu("1e100a00.gptu", NULL, 1, 0, PMU_GPT);
-- 
2.22.0

^ permalink raw reply related

* [PATCH 1/5] dt-bindings: MIPS: lantiq: Add documentation for the External Bus Unit
From: Martin Blumenstingl @ 2019-07-27 17:53 UTC (permalink / raw)
  To: tglx, jason, maz, ralf, paul.burton, jhogan, robh+dt, linux-mips,
	devicetree
  Cc: linux-kernel, mark.rutland, john, hauke, Martin Blumenstingl
In-Reply-To: <20190727175315.28834-1-martin.blumenstingl@googlemail.com>

Lantiq SoCs contain a so-called External Bus Unit.

It attaches PCI memory as well as NAND and NOR flash. Additioanlly it
contains an interrupt-controller for the PCI_INTA interrupt line.

Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
 .../bindings/mips/lantiq/lantiq,ebu.yaml      | 53 +++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mips/lantiq/lantiq,ebu.yaml

diff --git a/Documentation/devicetree/bindings/mips/lantiq/lantiq,ebu.yaml b/Documentation/devicetree/bindings/mips/lantiq/lantiq,ebu.yaml
new file mode 100644
index 000000000000..0b0b27d0b64b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mips/lantiq/lantiq,ebu.yaml
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mips/lantiq/lantiq,ebu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Lantiq External Bus Unit (EBU) bindings
+
+maintainers:
+  - Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+
+properties:
+  compatible:
+    enum:
+      - lantiq,falcon-ebu
+      - lantiq,xway-ebu
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: The EBU module clock
+
+  interrupt-controller:
+    type: boolean
+
+  interrupt-cells:
+    const: 2
+
+  interrupts:
+    items:
+      - description: The EBU module interrupt line
+
+required:
+  - compatible
+  - reg
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    memory-controller@e105300 {
+        compatible = "lantiq,xway-ebu";
+        reg = <0xe105300 0x100>;
+        clocks = <&pmu 10>;
+        interrupt-controller;
+        #interrupt-cells = <2>;
+        interrupt-parent = <&icu0>;
+        interrupts = <30>;
+    };
+...
-- 
2.22.0

^ permalink raw reply related

* [PATCH 0/5] MIPS: lantiq: EBU interrupt controller and generalization
From: Martin Blumenstingl @ 2019-07-27 17:53 UTC (permalink / raw)
  To: tglx, jason, maz, ralf, paul.burton, jhogan, robh+dt, linux-mips,
	devicetree
  Cc: linux-kernel, mark.rutland, john, hauke, Martin Blumenstingl

The relevant EBU code which is touched by this series is:
- initialization of the EBU WRDIS register on XWAY SoCs (this was part
  of arch/mips/lantiq/xway/sysctrl.c)
- initialization of the global ltq_ebu_membase variable on XWAY and
  Falcon SoCs (this was part of arch/mips/lantiq/xway/sysctrl.c and
  arch/mips/lantiq/falcon/sysctrl.c)
- handling the chained PCI_INTA interrupt (which was previously managed
  by arch/mips/lantiq/irq.c)
- configuring the PCI_INTA interrupt line (which was previously done by
  arch/mips/pci/pci-lantiq.c)

Instead of having the code spread across multiple source code files
this moves them to one "EBU" driver in arch/mips/lantiq/ebu.c utilizing
the irqchip subsystem to implement the PCI_INTA interrupt line.

While here this adds the dt-bindings documentation for the EBU IP block.

I believe that this series should go through the MIPS tree. However, it
would be great to have the irqchip maintainer review patch #3.



Martin Blumenstingl (5):
  dt-bindings: MIPS: lantiq: Add documentation for the External Bus Unit
  MIPS: lantiq: use a generic "EBU" driver for Falcon and XWAY SoCs
  MIPS: lantiq: add an irq_domain and irq_chip for EBU
  MIPS: dts: lantiq: danube: mark the ebu0 node as interrupt-controller
  MIPS: dts: lantiq: danube: easy50712: route the PCI_INTA IRQ through
    EBU

 .../bindings/mips/lantiq/lantiq,ebu.yaml      |  53 ++++
 arch/mips/boot/dts/lantiq/danube.dtsi         |   3 +
 arch/mips/boot/dts/lantiq/easy50712.dts       |   4 +-
 .../include/asm/mach-lantiq/xway/lantiq_soc.h |   5 -
 arch/mips/lantiq/Makefile                     |   2 +-
 arch/mips/lantiq/ebu.c                        | 238 ++++++++++++++++++
 arch/mips/lantiq/falcon/sysctrl.c             |  17 +-
 arch/mips/lantiq/irq.c                        |  11 -
 arch/mips/lantiq/xway/sysctrl.c               |  21 +-
 arch/mips/pci/pci-lantiq.c                    |   4 -
 10 files changed, 308 insertions(+), 50 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mips/lantiq/lantiq,ebu.yaml
 create mode 100644 arch/mips/lantiq/ebu.c

-- 
2.22.0

^ permalink raw reply

* Re: [PATCH v3 4/5] iio: imu: st_lsm6dsx: add support for accel/gyro unit of lsm9sd1
From: Jonathan Cameron @ 2019-07-27 17:48 UTC (permalink / raw)
  To: Martin Kepplinger
  Cc: lorenzo.bianconi83, knaack.h, lars, pmeerw, linux-iio, devicetree,
	linux-kernel
In-Reply-To: <20190725053132.9589-5-martin.kepplinger@puri.sm>

On Thu, 25 Jul 2019 07:31:31 +0200
Martin Kepplinger <martin.kepplinger@puri.sm> wrote:

> The LSM9DS1's accelerometer / gyroscope unit and it's magnetometer (separately
> supported in iio/magnetometer/st_magn*) are located on a separate i2c addresses
> on the bus.
> 
> For the datasheet, see https://www.st.com/resource/en/datasheet/lsm9ds1.pdf
> 
> Treat it just like the LSM6* devices and, despite it's name, hook it up
> to the st_lsm6dsx driver, using it's basic functionality.
> 
> Signed-off-by: Martin Kepplinger <martin.kepplinger@puri.sm>
I'm a little confused on this hardware.

How does buffered output work if these are independently clocked?

I took a quick look at the datasheet, and 'suspect' the answer is that
it runs at the gyro frequencies if both are enable. Is that right?

Code looks fine.

Jonathan



> ---
>  drivers/iio/imu/st_lsm6dsx/Kconfig           |  1 +
>  drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h      |  2 +
>  drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 94 +++++++++++++++++++-
>  drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c  |  5 ++
>  drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c  |  5 ++
>  5 files changed, 104 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iio/imu/st_lsm6dsx/Kconfig b/drivers/iio/imu/st_lsm6dsx/Kconfig
> index 2d8b2e1edfce..4a57bfb3c12e 100644
> --- a/drivers/iio/imu/st_lsm6dsx/Kconfig
> +++ b/drivers/iio/imu/st_lsm6dsx/Kconfig
> @@ -11,6 +11,7 @@ config IIO_ST_LSM6DSX
>  	  Say yes here to build support for STMicroelectronics LSM6DSx imu
>  	  sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm,
>  	  ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr, lsm6ds3tr-c
> +	  and the accelerometer/gyroscope of lsm9ds1.
>  
>  	  To compile this driver as a module, choose M here: the module
>  	  will be called st_lsm6dsx.
> diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
> index 3c47f5d27d30..9a30cc717de2 100644
> --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
> +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
> @@ -23,6 +23,7 @@
>  #define ST_LSM6DSOX_DEV_NAME	"lsm6dsox"
>  #define ST_LSM6DSR_DEV_NAME	"lsm6dsr"
>  #define ST_LSM6DS3TRC_DEV_NAME	"lsm6ds3tr-c"
> +#define ST_LSM9DS1_DEV_NAME	"lsm9ds1"
>  
>  enum st_lsm6dsx_hw_id {
>  	ST_LSM6DS3_ID,
> @@ -35,6 +36,7 @@ enum st_lsm6dsx_hw_id {
>  	ST_LSM6DSOX_ID,
>  	ST_LSM6DSR_ID,
>  	ST_LSM6DS3TRC_ID,
> +	ST_LSM9DS1_ID,
>  	ST_LSM6DSX_MAX_ID,
>  };
>  
> diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
> index e0d2149625cc..2f3d2bf25646 100644
> --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
> +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
> @@ -10,6 +10,8 @@
>   * +-125/+-245/+-500/+-1000/+-2000 dps
>   * LSM6DSx series has an integrated First-In-First-Out (FIFO) buffer
>   * allowing dynamic batching of sensor data.
> + * LSM9DSx series is similar but includes an additional magnetometer, handled
> + * by a different driver.
>   *
>   * Supported sensors:
>   * - LSM6DS3:
> @@ -30,6 +32,13 @@
>   *   - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
>   *   - FIFO size: 3KB
>   *
> + * - LSM9DS1:
> + *   - Accelerometer supported ODR [Hz]: 10, 50, 119, 238, 476, 952
> + *   - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
> + *   - Gyroscope supported ODR [Hz]: 15, 60, 119, 238, 476, 952
> + *   - Gyroscope supported full-scale [dps]: +-245/+-500/+-2000
> + *   - FIFO size: 32
> + *
>   * Copyright 2016 STMicroelectronics Inc.
>   *
>   * Lorenzo Bianconi <lorenzo.bianconi@st.com>
> @@ -64,7 +73,72 @@
>  #define ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR	0x24
>  #define ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR	0x26
>  
> +#define ST_LSM9DSX_REG_GYRO_OUT_X_L_ADDR	0x18
> +#define ST_LSM9DSX_REG_GYRO_OUT_Y_L_ADDR	0x1a
> +#define ST_LSM9DSX_REG_GYRO_OUT_Z_L_ADDR	0x1c
> +
>  static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
> +	{
> +		.wai = 0x68,
> +		.int1_addr = 0x0c,
> +		.int2_addr = 0x0d,
> +		.reset_addr = 0x22,
> +		.max_fifo_size = 32,
> +		.id = {
> +			{
> +				.hw_id = ST_LSM9DS1_ID,
> +				.name = ST_LSM9DS1_DEV_NAME,
> +			},
> +		},
> +		.odr_table = {
> +			[ST_LSM6DSX_ID_ACC] = {
> +				.reg = {
> +					.addr = 0x20,
> +					.mask = GENMASK(7, 5),
> +				},
> +				.odr_avl[0] = {  10, 0x01 },
> +				.odr_avl[1] = {  50, 0x02 },
> +				.odr_avl[2] = { 119, 0x03 },
> +				.odr_avl[3] = { 238, 0x04 },
> +				.odr_avl[4] = { 476, 0x05 },
> +				.odr_avl[5] = { 952, 0x06 },
> +			},
> +			[ST_LSM6DSX_ID_GYRO] = {
> +				.reg = {
> +					.addr = 0x10,
> +					.mask = GENMASK(7, 5),
> +				},
> +				.odr_avl[0] = {  15, 0x01 },
> +				.odr_avl[1] = {  60, 0x02 },
> +				.odr_avl[2] = { 119, 0x03 },
> +				.odr_avl[3] = { 238, 0x04 },
> +				.odr_avl[4] = { 476, 0x05 },
> +				.odr_avl[5] = { 952, 0x06 },
> +			},
> +		},
> +		.fs_table = {
> +			[ST_LSM6DSX_ID_ACC] = {
> +				.reg = {
> +					.addr = 0x20,
> +					.mask = GENMASK(4, 3),
> +				},
> +				.fs_avl[0] = {  599, 0x0 },
> +				.fs_avl[1] = { 1197, 0x2 },
> +				.fs_avl[2] = { 2394, 0x3 },
> +				.fs_avl[3] = { 4788, 0x1 },
> +			},
> +			[ST_LSM6DSX_ID_GYRO] = {
> +				.reg = {
> +					.addr = 0x10,
> +					.mask = GENMASK(4, 3),
> +				},
> +				.fs_avl[0] = { IIO_DEGREE_TO_RAD(245), 0x0 },
> +				.fs_avl[1] = { IIO_DEGREE_TO_RAD(500), 0x1 },
> +				.fs_avl[2] = { IIO_DEGREE_TO_RAD(0), 0x2 },
> +				.fs_avl[3] = { IIO_DEGREE_TO_RAD(2000), 0x3 },
> +			},
> +		},
> +	},
>  	{
>  		.wai = 0x69,
>  		.int1_addr = 0x0d,
> @@ -733,6 +807,16 @@ static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = {
>  	IIO_CHAN_SOFT_TIMESTAMP(3),
>  };
>  
> +static const struct iio_chan_spec st_lsm9dsx_gyro_channels[] = {
> +	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM9DSX_REG_GYRO_OUT_X_L_ADDR,
> +			   IIO_MOD_X, 0),
> +	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM9DSX_REG_GYRO_OUT_Y_L_ADDR,
> +			   IIO_MOD_Y, 1),
> +	ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, ST_LSM9DSX_REG_GYRO_OUT_Z_L_ADDR,
> +			   IIO_MOD_Z, 2),
> +	IIO_CHAN_SOFT_TIMESTAMP(3),
> +};
> +
>  int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable)
>  {
>  	const struct st_lsm6dsx_shub_settings *hub_settings;
> @@ -1278,7 +1362,7 @@ static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
>  
>  static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw,
>  					       enum st_lsm6dsx_sensor_id id,
> -					       const char *name)
> +					       const char *name, int hw_id)
>  {
>  	struct st_lsm6dsx_sensor *sensor;
>  	struct iio_dev *iio_dev;
> @@ -1308,7 +1392,11 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw,
>  			  name);
>  		break;
>  	case ST_LSM6DSX_ID_GYRO:
> -		iio_dev->channels = st_lsm6dsx_gyro_channels;
> +		if (hw_id == ST_LSM9DS1_ID)
> +			iio_dev->channels = st_lsm9dsx_gyro_channels;
> +		else
> +			iio_dev->channels = st_lsm6dsx_gyro_channels;
> +
>  		iio_dev->num_channels = ARRAY_SIZE(st_lsm6dsx_gyro_channels);
>  		iio_dev->info = &st_lsm6dsx_gyro_info;
>  
> @@ -1354,7 +1442,7 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
>  		return err;
>  
>  	for (i = 0; i < ST_LSM6DSX_ID_EXT0; i++) {
> -		hw->iio_devs[i] = st_lsm6dsx_alloc_iiodev(hw, i, name);
> +		hw->iio_devs[i] = st_lsm6dsx_alloc_iiodev(hw, i, name, hw_id);
>  		if (!hw->iio_devs[i])
>  			return -ENOMEM;
>  	}
> diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
> index 28581eb0532c..c36a057c36ee 100644
> --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
> +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
> @@ -79,6 +79,10 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = {
>  		.compatible = "st,lsm6ds3tr-c",
>  		.data = (void *)ST_LSM6DS3TRC_ID,
>  	},
> +	{
> +		.compatible = "st,lsm9ds1",
> +		.data = (void *)ST_LSM9DS1_ID,
> +	},
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match);
> @@ -94,6 +98,7 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = {
>  	{ ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID },
>  	{ ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID },
>  	{ ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID },
> +	{ ST_LSM9DS1_DEV_NAME, ST_LSM9DS1_ID },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table);
> diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
> index 0371e8b94a3e..138e3b985865 100644
> --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
> +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
> @@ -79,6 +79,10 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = {
>  		.compatible = "st,lsm6ds3tr-c",
>  		.data = (void *)ST_LSM6DS3TRC_ID,
>  	},
> +	{
> +		.compatible = "st,lsm9ds1",
> +		.data = (void *)ST_LSM9DS1_ID,
> +	},
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match);
> @@ -94,6 +98,7 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = {
>  	{ ST_LSM6DSOX_DEV_NAME, ST_LSM6DSOX_ID },
>  	{ ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID },
>  	{ ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID },
> +	{ ST_LSM9DS1_DEV_NAME, ST_LSM9DS1_ID },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table);

^ permalink raw reply

* Re: [GIT PULL] Devicetree fixes for 5.3-rc, take 2
From: pr-tracker-bot @ 2019-07-27 16:35 UTC (permalink / raw)
  To: Rob Herring
  Cc: Linus Torvalds, Frank Rowand, devicetree,
	linux-kernel@vger.kernel.org, Greg Kroah-Hartman
In-Reply-To: <CAL_JsqJLB4q6wqTOX0oXAGQF4wuZ0irNT8nmpFEmuUKjvv38BQ@mail.gmail.com>

The pull request you sent on Fri, 26 Jul 2019 18:03:50 -0600:

> git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git tags/devicetree-fixes-for-5.3-2

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/5efbd93708df56e0fb92b4398960a5bb1ab62f02

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.wiki.kernel.org/userdoc/prtracker

^ permalink raw reply

* Re: [PATCH 5/6] clk: imx8mq: Remove CLK_IS_CRITICAL flag for IMX8MQ_CLK_TMU_ROOT
From: Abel Vesa @ 2019-07-27 16:17 UTC (permalink / raw)
  To: Daniel Baluta
  Cc: Anson Huang, rui.zhang@intel.com, edubezval@gmail.com,
	daniel.lezcano@linaro.org, Rob Herring, Mark Rutland, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Michael Turquette, Stephen Boyd, Lucas Stach, Andrey Smirnov,
	Angus Ainslie (Purism), Carlo Caione, Guido Günther,
	Leonard Crestez
In-Reply-To: <CAEnQRZCrZybzcy__u4p_Eq4zSVc2ESyfKLk5sPf1JYba1JSOiA@mail.gmail.com>

On 19-07-27 09:33:10, Daniel Baluta wrote:
> On Sat, Jul 27, 2019 at 9:19 AM Anson Huang <anson.huang@nxp.com> wrote:
> >
> > Hi, Daniel
> >
> > > Subject: Re: [PATCH 5/6] clk: imx8mq: Remove CLK_IS_CRITICAL flag for
> > > IMX8MQ_CLK_TMU_ROOT
> > >
> > > Hi all,
> > >
> > > latest linux-next hangs at boot.
> > >
> > > commit fde50b96be821ac9673a7e00847cc4605bd88f34 (HEAD -> master, tag:
> > > next-20190726, origin/master, origin/HEAD)
> > > Author: Stephen Rothwell <sfr@canb.auug.org.au>
> > > Date:   Fri Jul 26 15:18:02 2019 +1000
> > >
> > >     Add linux-next specific files for 20190726
> > >
> > >     Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
> > >
> > >
> > > I know this is crazy but reverting commit:
> > >
> > > commit 431bdd1df48ee2896ea9980d9153e3aeaf0c81ef (refs/bisect/bad)
> > > Author: Anson Huang <Anson.Huang@nxp.com>
> > > Date:   Fri Jul 5 12:56:11 2019 +0800
> > >
> > >     clk: imx8mq: Remove CLK_IS_CRITICAL flag for IMX8MQ_CLK_TMU_ROOT
> > >
> > >     IMX8MQ_CLK_TMU_ROOT is ONLY used for thermal module, the driver
> > >     should manage this clock, so no need to have CLK_IS_CRITICAL flag
> > >     set.
> > >
> > >
> > >
> > > makes the boot work again.
> > >
> > > Any idea?
> >
> > I just found if disabling SDMA1, then kernel can boot up, it does NOT make sense
> > TMU clock is related to SDMA1, I will check with design and get back to you soon.
> >
> 
> Hi Anson,
> 
> Applying Abel's patch:
> 
> commit 8816c47db6a82f55bb4d64f62fd9dd3af680f0e4 (HEAD -> master)
> Author: Abel Vesa <abel.vesa@nxp.com>
> Date:   Tue Jun 25 12:01:56 2019 +0300
> 
>     clk: imx8mq: Mark AHB clock as critical
> 
>     Keep the AHB clock always on since there is no driver to control it and
>     all the other clocks that use it as parent rely on it being always enabled.
> 
> 
> 
> The kernel boots up again.
> 
> It make some sense. I don't understand though why having
> IMX8MQ_CLK_TMU_ROOT as critical also "unhangs" the kernel.
> 

OK, so this is how it works.

By removing the critical flag from TMU, the AHB doesn't stay always on.
With my patch the AHB is marked as critical and therefore stays on.

The sdma1_clk has as parent the ipg_root which in turn has as parent the
ahb clock. And I think what happens is some read from the sdma registers hangs
because, for whatever reason, enabling the sdma1_clk doesn't propagate to enable
the ahb clock. I might be wrong though.

> thanks,
> Daniel.

^ permalink raw reply

* Re: [PATCH 1/2] ARM: dts: rockchip: Cleanup style around assignment operator
From: Heiko Stuebner @ 2019-07-27 15:38 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: linux-arm-kernel, linux-rockchip, devicetree, linux-kernel
In-Reply-To: <20190727142736.23188-1-krzk@kernel.org>

Am Samstag, 27. Juli 2019, 16:27:35 CEST schrieb Krzysztof Kozlowski:
> Use a space before and after assignment operator to have consistent
> style.
> 
> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>

I've adapted the patch around recent chromebook display changes
(regarding veyron-chromebook.dtsi) and applied the result for 5.4

Thanks
Heiko

^ permalink raw reply

* Re: [PATCH 2/2] ARM: dts: rockchip: Add missing unit address to memory node on rk3288-veyron
From: Heiko Stuebner @ 2019-07-27 15:33 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: linux-arm-kernel, linux-rockchip, devicetree, linux-kernel
In-Reply-To: <20190727142736.23188-2-krzk@kernel.org>

Hi Krzysztof,

Am Samstag, 27. Juli 2019, 16:27:36 CEST schrieb Krzysztof Kozlowski:
> Fix DTC warning:
> 
>     arch/arm/boot/dts/rk3288-veyron.dtsi:21.9-24.4:
>     Warning (unit_address_vs_reg): /memory: node has a reg or ranges property, but no unit name

please see the comment directly above the memory node on why that needs
to stay that way. So no, we'll keep the veyron memory node as is.


Heiko

> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
> ---
>  arch/arm/boot/dts/rk3288-veyron.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/rk3288-veyron.dtsi b/arch/arm/boot/dts/rk3288-veyron.dtsi
> index 8fc8eac699bf..02243ff46a65 100644
> --- a/arch/arm/boot/dts/rk3288-veyron.dtsi
> +++ b/arch/arm/boot/dts/rk3288-veyron.dtsi
> @@ -18,7 +18,7 @@
>  	 * The default coreboot on veyron devices ignores memory@0 nodes
>  	 * and would instead create another memory node.
>  	 */
> -	memory {
> +	memory@0 {
>  		device_type = "memory";
>  		reg = <0x0 0x0 0x0 0x80000000>;
>  	};
> 

^ permalink raw reply


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