* [PATCH 1/3] crypto: brcm: DT documentation for Broadcom SPU driver
From: Rob Rice @ 2016-11-30 20:07 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Rob Herring, Mark Rutland,
linux-crypto, devicetree, linux-kernel, Ray Jui, Scott Branden,
Jon Mason, bcm-kernel-feedback-list, Catalin Marinas, Will Deacon,
linux-arm-kernel
Cc: Steve Lin, Rob Rice
In-Reply-To: <1480536453-24781-1-git-send-email-rob.rice@broadcom.com>
Device tree documentation for Broadcom Secure Processing Unit
(SPU) crypto driver.
Signed-off-by: Steve Lin <steven.lin1@broadcom.com>
Signed-off-by: Rob Rice <rob.rice@broadcom.com>
---
.../devicetree/bindings/crypto/brcm,spu-crypto.txt | 25 ++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 Documentation/devicetree/bindings/crypto/brcm,spu-crypto.txt
diff --git a/Documentation/devicetree/bindings/crypto/brcm,spu-crypto.txt b/Documentation/devicetree/bindings/crypto/brcm,spu-crypto.txt
new file mode 100644
index 0000000..e5fe942
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/brcm,spu-crypto.txt
@@ -0,0 +1,25 @@
+The Broadcom Secure Processing Unit (SPU) driver supports symmetric
+cryptographic offload for Broadcom SoCs with SPU hardware. A SoC may have
+multiple SPU hardware blocks.
+
+Required properties:
+- compatible : Should be "brcm,spum-crypto" for devices with SPU-M hardware
+ (e.g., Northstar2) or "brcm,spum-nsp-crypto" for the Northstar Plus variant
+ of the SPU-M hardware.
+
+- reg: Should contain SPU registers location and length.
+- mboxes: A list of mailbox channels to be used by the kernel driver. Mailbox
+channels correspond to DMA rings on the device.
+
+Example:
+ spu-crypto@612d0000 {
+ compatible = "brcm,spum-crypto";
+ reg = <0 0x612d0000 0 0x900>, /* SPU 0 control regs */
+ <0 0x612f0000 0 0x900>, /* SPU 1 control regs */
+ <0 0x61310000 0 0x900>, /* SPU 2 control regs */
+ <0 0x61330000 0 0x900>; /* SPU 3 control regs */
+ mboxes = <&pdc0 0>,
+ <&pdc1 0>,
+ <&pdc2 0>,
+ <&pdc3 0>;
+ };
--
2.1.0
^ permalink raw reply related
* [PATCH 0/3] Add Broadcom SPU Crypto Driver
From: Rob Rice @ 2016-11-30 20:07 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Rob Herring, Mark Rutland,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ray Jui, Scott Branden,
Jon Mason, bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w,
Catalin Marinas, Will Deacon,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Steve Lin, Rob Rice
The Broadcom SPU crypto driver provides access to SPU hardware
for symmetric crypto offload. The driver supports ablkcipher,
ahash, and aead operations. The driver supports several
Broadcom SoCs with different revisions of the SPU hardware.
The driver supports SPU-M and SPU2 hardware revisions, and
a couple versions of each hw revision, each version with minor
differences.
The device tree entries for the SPU depends on device tree entries
for the Broadcom PDC driver. The PDC DT entries have been accepted
upstream, but are not yet included in the crypto repo. See commit
e79249143f468f8d3365dbbd1642c045bdcc98c5.
Rob Rice (3):
crypto: brcm: DT documentation for Broadcom SPU driver
crypto: brcm: Add Broadcom SPU driver
crypto: brcm: Add Broadcom SPU driver DT entry.
.../devicetree/bindings/crypto/brcm,spu-crypto.txt | 25 +
arch/arm64/boot/dts/broadcom/ns2.dtsi | 12 +
drivers/crypto/Kconfig | 10 +
drivers/crypto/Makefile | 1 +
drivers/crypto/bcm/Makefile | 15 +
drivers/crypto/bcm/cipher.c | 4943 ++++++++++++++++++++
drivers/crypto/bcm/cipher.h | 472 ++
drivers/crypto/bcm/spu.c | 1252 +++++
drivers/crypto/bcm/spu.h | 288 ++
drivers/crypto/bcm/spu2.c | 1402 ++++++
drivers/crypto/bcm/spu2.h | 228 +
drivers/crypto/bcm/spum.h | 174 +
drivers/crypto/bcm/util.c | 584 +++
drivers/crypto/bcm/util.h | 117 +
14 files changed, 9523 insertions(+)
create mode 100644 Documentation/devicetree/bindings/crypto/brcm,spu-crypto.txt
create mode 100644 drivers/crypto/bcm/Makefile
create mode 100644 drivers/crypto/bcm/cipher.c
create mode 100644 drivers/crypto/bcm/cipher.h
create mode 100644 drivers/crypto/bcm/spu.c
create mode 100644 drivers/crypto/bcm/spu.h
create mode 100644 drivers/crypto/bcm/spu2.c
create mode 100644 drivers/crypto/bcm/spu2.h
create mode 100644 drivers/crypto/bcm/spum.h
create mode 100644 drivers/crypto/bcm/util.c
create mode 100644 drivers/crypto/bcm/util.h
--
2.1.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
* [PATCH v2 2/2] Documentation: dt: iio: add st_lsm6dsx sensor device binding
From: Lorenzo Bianconi @ 2016-11-30 20:05 UTC (permalink / raw)
To: jic23-DgEjT+Ai2ygdnm+yROfE0A
Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.bianconi-qxv4g6HH51o
In-Reply-To: <20161130200559.29910-1-lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>
---
.../devicetree/bindings/iio/imu/st_lsm6dsx.txt | 24 ++++++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt
diff --git a/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt
new file mode 100644
index 0000000..ed3cdac
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt
@@ -0,0 +1,24 @@
+* ST_LSM6DSx driver for STM 6-axis (acc + gyro) imu Mems sensors
+
+Required properties:
+- compatible: must be one of:
+ "st,lsm6ds3"
+ "st,lsm6dsm"
+- reg: i2c address of the sensor / spi cs line
+
+Optional properties:
+- interrupt-parent: should be the phandle for the interrupt controller
+- interrupts: interrupt mapping for IRQ. It should be configured with
+ flags IRQ_TYPE_LEVEL_HIGH or IRQ_TYPE_EDGE_RISING.
+
+ Refer to interrupt-controller/interrupts.txt for generic interrupt
+ client node bindings.
+
+Example:
+
+lsm6dsm@6b {
+ compatible = "st,lsm6dsm";
+ reg = <0x6b>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <0 IRQ_TYPE_EDGE_RISING>;
+};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 1/2] iio: imu: add support to lsm6dsx driver
From: Lorenzo Bianconi @ 2016-11-30 20:05 UTC (permalink / raw)
To: jic23-DgEjT+Ai2ygdnm+yROfE0A
Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.bianconi-qxv4g6HH51o
In-Reply-To: <20161130200559.29910-1-lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>
Add support to STM LSM6DS3-LSM6DSM 6-axis (acc + gyro) Mems sensor
http://www.st.com/resource/en/datasheet/lsm6ds3.pdf
http://www.st.com/resource/en/datasheet/lsm6dsm.pdf
- continuous mode support
- i2c support
- spi support
- sw fifo mode support
- supported devices: lsm6ds3, lsm6dsm
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>
---
drivers/iio/imu/Kconfig | 1 +
drivers/iio/imu/Makefile | 2 +
drivers/iio/imu/st_lsm6dsx/Kconfig | 23 +
drivers/iio/imu/st_lsm6dsx/Makefile | 6 +
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 107 ++++
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 696 +++++++++++++++++++++++++++
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c | 111 +++++
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_ring.c | 401 +++++++++++++++
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c | 129 +++++
9 files changed, 1476 insertions(+)
create mode 100644 drivers/iio/imu/st_lsm6dsx/Kconfig
create mode 100644 drivers/iio/imu/st_lsm6dsx/Makefile
create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_ring.c
create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 1f1ad41..156630a 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -39,6 +39,7 @@ config KMX61
be called kmx61.
source "drivers/iio/imu/inv_mpu6050/Kconfig"
+source "drivers/iio/imu/st_lsm6dsx/Kconfig"
endmenu
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index c71bcd3..8b563c3 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -17,3 +17,5 @@ obj-y += bmi160/
obj-y += inv_mpu6050/
obj-$(CONFIG_KMX61) += kmx61.o
+
+obj-y += st_lsm6dsx/
diff --git a/drivers/iio/imu/st_lsm6dsx/Kconfig b/drivers/iio/imu/st_lsm6dsx/Kconfig
new file mode 100644
index 0000000..9a0781b
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6dsx/Kconfig
@@ -0,0 +1,23 @@
+
+config IIO_ST_LSM6DSX
+ tristate "ST_LSM6DSx driver for STM 6-axis imu Mems sensors"
+ depends on (I2C || SPI)
+ select IIO_BUFFER
+ select IIO_KFIFO_BUF
+ select IIO_ST_LSM6DSX_I2C if (I2C)
+ select IIO_ST_LSM6DSX_SPI if (SPI_MASTER)
+ help
+ Say yes here to build support for STMicroelectronics LSM6DSx imu
+ sensor. Supported devices: lsm6ds3, lsm6dsm
+
+ To compile this driver as a module, choose M here: the module
+ will be called st_lsm6dsx.
+
+config IIO_ST_LSM6DSX_I2C
+ tristate
+ depends on IIO_ST_LSM6DSX
+
+config IIO_ST_LSM6DSX_SPI
+ tristate
+ depends on IIO_ST_LSM6DSX
+
diff --git a/drivers/iio/imu/st_lsm6dsx/Makefile b/drivers/iio/imu/st_lsm6dsx/Makefile
new file mode 100644
index 0000000..812d655
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6dsx/Makefile
@@ -0,0 +1,6 @@
+st_lsm6dsx-y := st_lsm6dsx_core.o \
+ st_lsm6dsx_ring.o
+
+obj-$(CONFIG_IIO_ST_LSM6DSX) += st_lsm6dsx.o
+obj-$(CONFIG_IIO_ST_LSM6DSX_I2C) += st_lsm6dsx_i2c.o
+obj-$(CONFIG_IIO_ST_LSM6DSX_SPI) += st_lsm6dsx_spi.o
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
new file mode 100644
index 0000000..a43beab
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
@@ -0,0 +1,107 @@
+/*
+ * STMicroelectronics st_lsm6dsx sensor driver
+ *
+ * Copyright 2016 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>
+ * Denis Ciocca <denis.ciocca-qxv4g6HH51o@public.gmane.org>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef ST_LSM6DSX_H
+#define ST_LSM6DSX_H
+
+#include <linux/device.h>
+
+#define ST_LSM6DS3_DEV_NAME "lsm6ds3"
+#define ST_LSM6DSM_DEV_NAME "lsm6dsm"
+
+#define ST_LSM6DSX_CHAN_SIZE 2
+#define ST_LSM6DSX_SAMPLE_SIZE 6
+#define ST_LSM6DSX_SAMPLE_DEPTH (ST_LSM6DSX_SAMPLE_SIZE / \
+ ST_LSM6DSX_CHAN_SIZE)
+
+#if defined(CONFIG_SPI_MASTER)
+#define ST_LSM6DSX_RX_MAX_LENGTH 256
+#define ST_LSM6DSX_TX_MAX_LENGTH 8
+
+struct st_lsm6dsx_transfer_buffer {
+ u8 rx_buf[ST_LSM6DSX_RX_MAX_LENGTH];
+ u8 tx_buf[ST_LSM6DSX_TX_MAX_LENGTH] ____cacheline_aligned;
+};
+#endif /* CONFIG_SPI_MASTER */
+
+struct st_lsm6dsx_transfer_function {
+ int (*read)(struct device *dev, u8 addr, int len, u8 *data);
+ int (*write)(struct device *dev, u8 addr, int len, u8 *data);
+};
+
+struct st_lsm6dsx_reg {
+ u8 addr;
+ u8 mask;
+};
+
+struct st_lsm6dsx_settings {
+ u8 wai;
+ u16 max_fifo_size;
+};
+
+enum st_lsm6dsx_sensor_id {
+ ST_LSM6DSX_ID_ACC,
+ ST_LSM6DSX_ID_GYRO,
+ ST_LSM6DSX_ID_MAX,
+};
+
+enum st_lsm6dsx_fifo_mode {
+ ST_LSM6DSX_FIFO_BYPASS = 0x0,
+ ST_LSM6DSX_FIFO_CONT = 0x6,
+};
+
+struct st_lsm6dsx_sensor {
+ enum st_lsm6dsx_sensor_id id;
+ struct st_lsm6dsx_hw *hw;
+
+ u32 gain;
+ u16 odr;
+
+ u16 watermark;
+ u8 sip;
+ u8 decimator;
+ u8 decimator_mask;
+
+ s64 delta_ts;
+ s64 ts;
+};
+
+struct st_lsm6dsx_hw {
+ const char *name;
+ struct device *dev;
+ int irq;
+ struct mutex lock;
+
+ enum st_lsm6dsx_fifo_mode fifo_mode;
+ u8 enable_mask;
+ u8 sip;
+
+ struct iio_dev *iio_devs[ST_LSM6DSX_ID_MAX];
+
+ const struct st_lsm6dsx_settings *settings;
+
+ const struct st_lsm6dsx_transfer_function *tf;
+#if defined(CONFIG_SPI_MASTER)
+ struct st_lsm6dsx_transfer_buffer tb;
+#endif /* CONFIG_SPI_MASTER */
+};
+
+int st_lsm6dsx_probe(struct st_lsm6dsx_hw *hw);
+int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor);
+int st_lsm6dsx_sensor_disable(struct st_lsm6dsx_sensor *sensor);
+int st_lsm6dsx_allocate_rings(struct st_lsm6dsx_hw *hw);
+int st_lsm6dsx_write_with_mask(struct st_lsm6dsx_hw *hw, u8 addr, u8 mask,
+ u8 val);
+int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor,
+ u16 watermark);
+
+#endif /* ST_LSM6DSX_H */
+
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
new file mode 100644
index 0000000..ae4cf30
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -0,0 +1,696 @@
+/*
+ * STMicroelectronics st_lsm6dsx sensor driver
+ *
+ * Copyright 2016 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>
+ * Denis Ciocca <denis.ciocca-qxv4g6HH51o@public.gmane.org>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <asm/unaligned.h>
+
+#include "st_lsm6dsx.h"
+
+#define ST_LSM6DSX_REG_ACC_DEC_MASK 0x07
+#define ST_LSM6DSX_REG_GYRO_DEC_MASK 0x38
+#define ST_LSM6DSX_REG_INT1_ADDR 0x0d
+#define ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK 0x08
+#define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f
+#define ST_LSM6DSX_REG_RESET_ADDR 0x12
+#define ST_LSM6DSX_REG_RESET_MASK 0x01
+#define ST_LSM6DSX_REG_BDU_ADDR 0x12
+#define ST_LSM6DSX_REG_BDU_MASK 0x40
+#define ST_LSM6DSX_REG_INT2_ON_INT1_ADDR 0x13
+#define ST_LSM6DSX_REG_INT2_ON_INT1_MASK 0x20
+#define ST_LSM6DSX_REG_ROUNDING_ADDR 0x16
+#define ST_LSM6DSX_REG_ROUNDING_MASK 0x04
+#define ST_LSM6DSX_REG_LIR_ADDR 0x58
+#define ST_LSM6DSX_REG_LIR_MASK 0x01
+
+#define ST_LSM6DSX_REG_ACC_ODR_ADDR 0x10
+#define ST_LSM6DSX_REG_ACC_ODR_MASK 0xf0
+#define ST_LSM6DSX_REG_ACC_FS_ADDR 0x10
+#define ST_LSM6DSX_REG_ACC_FS_MASK 0x0c
+#define ST_LSM6DSX_REG_ACC_OUT_X_L_ADDR 0x28
+#define ST_LSM6DSX_REG_ACC_OUT_Y_L_ADDR 0x2a
+#define ST_LSM6DSX_REG_ACC_OUT_Z_L_ADDR 0x2c
+
+#define ST_LSM6DSX_REG_GYRO_ODR_ADDR 0x11
+#define ST_LSM6DSX_REG_GYRO_ODR_MASK 0xf0
+#define ST_LSM6DSX_REG_GYRO_FS_ADDR 0x11
+#define ST_LSM6DSX_REG_GYRO_FS_MASK 0x0c
+#define ST_LSM6DSX_REG_GYRO_OUT_X_L_ADDR 0x22
+#define ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR 0x24
+#define ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR 0x26
+
+#define ST_LSM6DS3_WHOAMI 0x69
+#define ST_LSM6DSM_WHOAMI 0x6a
+
+#define ST_LSM6DS3_MAX_FIFO_SIZE 8192
+#define ST_LSM6DSM_MAX_FIFO_SIZE 4096
+
+#define ST_LSM6DSX_ACC_FS_2G_GAIN IIO_G_TO_M_S_2(61)
+#define ST_LSM6DSX_ACC_FS_4G_GAIN IIO_G_TO_M_S_2(122)
+#define ST_LSM6DSX_ACC_FS_8G_GAIN IIO_G_TO_M_S_2(244)
+#define ST_LSM6DSX_ACC_FS_16G_GAIN IIO_G_TO_M_S_2(488)
+
+#define ST_LSM6DSX_GYRO_FS_245_GAIN IIO_DEGREE_TO_RAD(4375)
+#define ST_LSM6DSX_GYRO_FS_500_GAIN IIO_DEGREE_TO_RAD(8750)
+#define ST_LSM6DSX_GYRO_FS_1000_GAIN IIO_DEGREE_TO_RAD(17500)
+#define ST_LSM6DSX_GYRO_FS_2000_GAIN IIO_DEGREE_TO_RAD(70000)
+
+struct st_lsm6dsx_odr {
+ u16 hz;
+ u8 val;
+};
+
+#define ST_LSM6DSX_ODR_LIST_SIZE 6
+struct st_lsm6dsx_odr_table_entry {
+ struct st_lsm6dsx_reg reg;
+ struct st_lsm6dsx_odr odr_avl[ST_LSM6DSX_ODR_LIST_SIZE];
+};
+
+static const struct st_lsm6dsx_odr_table_entry st_lsm6dsx_odr_table[] = {
+ [ST_LSM6DSX_ID_ACC] = {
+ .reg = {
+ .addr = ST_LSM6DSX_REG_ACC_ODR_ADDR,
+ .mask = ST_LSM6DSX_REG_ACC_ODR_MASK,
+ },
+ .odr_avl[0] = { 13, 0x01 },
+ .odr_avl[1] = { 26, 0x02 },
+ .odr_avl[2] = { 52, 0x03 },
+ .odr_avl[3] = { 104, 0x04 },
+ .odr_avl[4] = { 208, 0x05 },
+ .odr_avl[5] = { 416, 0x06 },
+ },
+ [ST_LSM6DSX_ID_GYRO] = {
+ .reg = {
+ .addr = ST_LSM6DSX_REG_GYRO_ODR_ADDR,
+ .mask = ST_LSM6DSX_REG_GYRO_ODR_MASK,
+ },
+ .odr_avl[0] = { 13, 0x01 },
+ .odr_avl[1] = { 26, 0x02 },
+ .odr_avl[2] = { 52, 0x03 },
+ .odr_avl[3] = { 104, 0x04 },
+ .odr_avl[4] = { 208, 0x05 },
+ .odr_avl[5] = { 416, 0x06 },
+ }
+};
+
+struct st_lsm6dsx_fs {
+ u32 gain;
+ u8 val;
+};
+
+#define ST_LSM6DSX_FS_LIST_SIZE 4
+struct st_lsm6dsx_fs_table_entry {
+ struct st_lsm6dsx_reg reg;
+ struct st_lsm6dsx_fs fs_avl[ST_LSM6DSX_FS_LIST_SIZE];
+};
+
+static const struct st_lsm6dsx_fs_table_entry st_lsm6dsx_fs_table[] = {
+ [ST_LSM6DSX_ID_ACC] = {
+ .reg = {
+ .addr = ST_LSM6DSX_REG_ACC_FS_ADDR,
+ .mask = ST_LSM6DSX_REG_ACC_FS_MASK,
+ },
+ .fs_avl[0] = { ST_LSM6DSX_ACC_FS_2G_GAIN, 0x0 },
+ .fs_avl[1] = { ST_LSM6DSX_ACC_FS_4G_GAIN, 0x2 },
+ .fs_avl[2] = { ST_LSM6DSX_ACC_FS_8G_GAIN, 0x3 },
+ .fs_avl[3] = { ST_LSM6DSX_ACC_FS_16G_GAIN, 0x1 },
+ },
+ [ST_LSM6DSX_ID_GYRO] = {
+ .reg = {
+ .addr = ST_LSM6DSX_REG_GYRO_FS_ADDR,
+ .mask = ST_LSM6DSX_REG_GYRO_FS_MASK,
+ },
+ .fs_avl[0] = { ST_LSM6DSX_GYRO_FS_245_GAIN, 0x0 },
+ .fs_avl[1] = { ST_LSM6DSX_GYRO_FS_500_GAIN, 0x1 },
+ .fs_avl[2] = { ST_LSM6DSX_GYRO_FS_1000_GAIN, 0x2 },
+ .fs_avl[3] = { ST_LSM6DSX_GYRO_FS_2000_GAIN, 0x3 },
+ }
+};
+
+static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
+ {
+ .wai = ST_LSM6DS3_WHOAMI,
+ .max_fifo_size = ST_LSM6DS3_MAX_FIFO_SIZE,
+ },
+ {
+ .wai = ST_LSM6DSM_WHOAMI,
+ .max_fifo_size = ST_LSM6DSM_MAX_FIFO_SIZE,
+ },
+};
+
+static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = {
+ {
+ .type = IIO_ACCEL,
+ .address = ST_LSM6DSX_REG_ACC_OUT_X_L_ADDR,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_LE,
+ },
+ },
+ {
+ .type = IIO_ACCEL,
+ .address = ST_LSM6DSX_REG_ACC_OUT_Y_L_ADDR,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_LE,
+ },
+ },
+ {
+ .type = IIO_ACCEL,
+ .address = ST_LSM6DSX_REG_ACC_OUT_Z_L_ADDR,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .scan_index = 2,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_LE,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = {
+ {
+ .type = IIO_ANGL_VEL,
+ .address = ST_LSM6DSX_REG_GYRO_OUT_X_L_ADDR,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_LE,
+ },
+ },
+ {
+ .type = IIO_ANGL_VEL,
+ .address = ST_LSM6DSX_REG_GYRO_OUT_Y_L_ADDR,
+ .modified = 1,
+ .channel2 = IIO_MOD_Y,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_LE,
+ },
+ },
+ {
+ .type = IIO_ANGL_VEL,
+ .address = ST_LSM6DSX_REG_GYRO_OUT_Z_L_ADDR,
+ .modified = 1,
+ .channel2 = IIO_MOD_Z,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .scan_index = 2,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_LE,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+int st_lsm6dsx_write_with_mask(struct st_lsm6dsx_hw *hw, u8 addr, u8 mask,
+ u8 val)
+{
+ u8 data;
+ int err;
+
+ mutex_lock(&hw->lock);
+
+ err = hw->tf->read(hw->dev, addr, sizeof(data), &data);
+ if (err < 0) {
+ dev_err(hw->dev, "failed to read %02x register\n", addr);
+ goto out;
+ }
+
+ data = (data & ~mask) | ((val << __ffs(mask)) & mask);
+
+ err = hw->tf->write(hw->dev, addr, sizeof(data), &data);
+ if (err < 0)
+ dev_err(hw->dev, "failed to write %02x register\n", addr);
+
+out:
+ mutex_unlock(&hw->lock);
+
+ return err;
+}
+
+static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw)
+{
+ int err, i;
+ u8 data;
+
+ err = hw->tf->read(hw->dev, ST_LSM6DSX_REG_WHOAMI_ADDR, sizeof(data),
+ &data);
+ if (err < 0) {
+ dev_err(hw->dev, "failed to read whoami register\n");
+ return err;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) {
+ if (data == st_lsm6dsx_sensor_settings[i].wai) {
+ hw->settings = &st_lsm6dsx_sensor_settings[i];
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(st_lsm6dsx_sensor_settings)) {
+ dev_err(hw->dev, "unsupported whoami [%02x]\n", data);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int st_lsm6dsx_set_fs(struct st_lsm6dsx_sensor *sensor, u32 gain)
+{
+ enum st_lsm6dsx_sensor_id id = sensor->id;
+ int i, err;
+ u8 val;
+
+ for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++)
+ if (st_lsm6dsx_fs_table[id].fs_avl[i].gain == gain)
+ break;
+
+ if (i == ST_LSM6DSX_FS_LIST_SIZE)
+ return -EINVAL;
+
+ val = st_lsm6dsx_fs_table[id].fs_avl[i].val;
+ err = st_lsm6dsx_write_with_mask(sensor->hw,
+ st_lsm6dsx_fs_table[id].reg.addr,
+ st_lsm6dsx_fs_table[id].reg.mask,
+ val);
+ if (err < 0)
+ return err;
+
+ sensor->gain = gain;
+
+ return 0;
+}
+
+static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 odr)
+{
+ enum st_lsm6dsx_sensor_id id = sensor->id;
+ int i, err, val;
+
+ for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++)
+ if (st_lsm6dsx_odr_table[id].odr_avl[i].hz == odr)
+ break;
+
+ if (i == ST_LSM6DSX_ODR_LIST_SIZE)
+ return -EINVAL;
+
+ val = st_lsm6dsx_odr_table[id].odr_avl[i].val;
+ err = st_lsm6dsx_write_with_mask(sensor->hw,
+ st_lsm6dsx_odr_table[id].reg.addr,
+ st_lsm6dsx_odr_table[id].reg.mask,
+ val);
+ if (err < 0)
+ return err;
+
+ sensor->odr = odr;
+
+ return 0;
+}
+
+int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor)
+{
+ int err;
+
+ err = st_lsm6dsx_set_odr(sensor, sensor->odr);
+ if (err < 0)
+ return err;
+
+ sensor->hw->enable_mask |= BIT(sensor->id);
+
+ return 0;
+}
+
+int st_lsm6dsx_sensor_disable(struct st_lsm6dsx_sensor *sensor)
+{
+ enum st_lsm6dsx_sensor_id id = sensor->id;
+ int err;
+
+ err = st_lsm6dsx_write_with_mask(sensor->hw,
+ st_lsm6dsx_odr_table[id].reg.addr,
+ st_lsm6dsx_odr_table[id].reg.mask, 0);
+ if (err < 0)
+ return err;
+
+ sensor->hw->enable_mask &= ~BIT(id);
+
+ return 0;
+}
+
+static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor,
+ u8 addr, int *val)
+{
+ int err, delay;
+ u8 data[2];
+
+ err = st_lsm6dsx_sensor_enable(sensor);
+ if (err < 0)
+ return err;
+
+ delay = 1000000 / sensor->odr;
+ usleep_range(delay, 2 * delay);
+
+ err = sensor->hw->tf->read(sensor->hw->dev, addr, sizeof(data), data);
+ if (err < 0)
+ return err;
+
+ st_lsm6dsx_sensor_disable(sensor);
+
+ *val = (s16)get_unaligned_le16(data);
+
+ return IIO_VAL_INT;
+}
+
+static int st_lsm6dsx_read_raw(struct iio_dev *iio_dev,
+ struct iio_chan_spec const *ch,
+ int *val, int *val2, long mask)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+ int ret;
+
+ ret = iio_device_claim_direct_mode(iio_dev);
+ if (ret)
+ return ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = st_lsm6dsx_read_oneshot(sensor, ch->address, val);
+ break;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = sensor->odr;
+ ret = IIO_VAL_INT;
+ break;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ *val2 = sensor->gain;
+ ret = IIO_VAL_INT_PLUS_MICRO;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ iio_device_release_direct_mode(iio_dev);
+
+ return ret;
+}
+
+static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+ int err;
+
+ err = iio_device_claim_direct_mode(iio_dev);
+ if (err)
+ return err;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ err = st_lsm6dsx_set_fs(sensor, val2);
+ break;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ err = st_lsm6dsx_set_odr(sensor, val);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ iio_device_release_direct_mode(iio_dev);
+
+ return err;
+}
+
+static int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+ int err, max_fifo_len;
+
+ max_fifo_len = hw->settings->max_fifo_size / ST_LSM6DSX_SAMPLE_SIZE;
+ if (val < 1 || val > max_fifo_len)
+ return -EINVAL;
+
+ err = st_lsm6dsx_update_watermark(sensor, val);
+ if (err < 0)
+ return err;
+
+ sensor->watermark = val;
+
+ return 0;
+}
+
+static ssize_t
+st_lsm6dsx_sysfs_sampling_frequency_avl(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev));
+ enum st_lsm6dsx_sensor_id id = sensor->id;
+ int i, len = 0;
+
+ for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
+ st_lsm6dsx_odr_table[id].odr_avl[i].hz);
+ buf[len - 1] = '\n';
+
+ return len;
+}
+
+static ssize_t st_lsm6dsx_sysfs_scale_avail(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev));
+ enum st_lsm6dsx_sensor_id id = sensor->id;
+ int i, len = 0;
+
+ for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ",
+ st_lsm6dsx_fs_table[id].fs_avl[i].gain);
+ buf[len - 1] = '\n';
+
+ return len;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(st_lsm6dsx_sysfs_sampling_frequency_avl);
+static IIO_DEVICE_ATTR(in_accel_scale_available, 0444,
+ st_lsm6dsx_sysfs_scale_avail, NULL, 0);
+static IIO_DEVICE_ATTR(in_anglvel_scale_available, 0444,
+ st_lsm6dsx_sysfs_scale_avail, NULL, 0);
+
+static struct attribute *st_lsm6dsx_acc_attributes[] = {
+ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_dev_attr_in_accel_scale_available.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group st_lsm6dsx_acc_attribute_group = {
+ .attrs = st_lsm6dsx_acc_attributes,
+};
+
+static const struct iio_info st_lsm6dsx_acc_info = {
+ .driver_module = THIS_MODULE,
+ .attrs = &st_lsm6dsx_acc_attribute_group,
+ .read_raw = st_lsm6dsx_read_raw,
+ .write_raw = st_lsm6dsx_write_raw,
+ .hwfifo_set_watermark = st_lsm6dsx_set_watermark,
+};
+
+static struct attribute *st_lsm6dsx_gyro_attributes[] = {
+ &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group st_lsm6dsx_gyro_attribute_group = {
+ .attrs = st_lsm6dsx_gyro_attributes,
+};
+
+static const struct iio_info st_lsm6dsx_gyro_info = {
+ .driver_module = THIS_MODULE,
+ .attrs = &st_lsm6dsx_gyro_attribute_group,
+ .read_raw = st_lsm6dsx_read_raw,
+ .write_raw = st_lsm6dsx_write_raw,
+ .hwfifo_set_watermark = st_lsm6dsx_set_watermark,
+};
+
+static const unsigned long st_lsm6dsx_available_scan_masks[] = {0x7, 0x0};
+
+static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw)
+{
+ int err;
+ u8 data;
+
+ data = ST_LSM6DSX_REG_RESET_MASK;
+ err = hw->tf->write(hw->dev, ST_LSM6DSX_REG_RESET_ADDR, sizeof(data),
+ &data);
+ if (err < 0)
+ return err;
+
+ msleep(200);
+
+ /* latch interrupts */
+ err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_LIR_ADDR,
+ ST_LSM6DSX_REG_LIR_MASK, 1);
+ if (err < 0)
+ return err;
+
+ /* enable BDU */
+ err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_BDU_ADDR,
+ ST_LSM6DSX_REG_BDU_MASK, 1);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_ROUNDING_ADDR,
+ ST_LSM6DSX_REG_ROUNDING_MASK, 1);
+ if (err < 0)
+ return err;
+
+ /* enable FIFO watermak interrupt */
+ err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_INT1_ADDR,
+ ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK, 1);
+ if (err < 0)
+ return err;
+
+ /* redirect INT2 on INT1 */
+ return st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_INT2_ON_INT1_ADDR,
+ ST_LSM6DSX_REG_INT2_ON_INT1_MASK, 1);
+}
+
+static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw,
+ enum st_lsm6dsx_sensor_id id)
+{
+ struct st_lsm6dsx_sensor *sensor;
+ struct iio_dev *iio_dev;
+
+ iio_dev = devm_iio_device_alloc(hw->dev, sizeof(*sensor));
+ if (!iio_dev)
+ return NULL;
+
+ iio_dev->modes = INDIO_DIRECT_MODE;
+ iio_dev->dev.parent = hw->dev;
+ iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks;
+
+ sensor = iio_priv(iio_dev);
+ sensor->id = id;
+ sensor->hw = hw;
+ sensor->odr = st_lsm6dsx_odr_table[id].odr_avl[0].hz;
+ sensor->gain = st_lsm6dsx_fs_table[id].fs_avl[0].gain;
+ sensor->watermark = 1;
+
+ switch (id) {
+ case ST_LSM6DSX_ID_ACC:
+ iio_dev->channels = st_lsm6dsx_acc_channels;
+ iio_dev->num_channels = ARRAY_SIZE(st_lsm6dsx_acc_channels);
+ iio_dev->name = "lsm6dsx_accel";
+ iio_dev->info = &st_lsm6dsx_acc_info;
+
+ sensor->decimator_mask = ST_LSM6DSX_REG_ACC_DEC_MASK;
+ break;
+ case ST_LSM6DSX_ID_GYRO:
+ iio_dev->channels = st_lsm6dsx_gyro_channels;
+ iio_dev->num_channels = ARRAY_SIZE(st_lsm6dsx_gyro_channels);
+ iio_dev->name = "lsm6dsx_gyro";
+ iio_dev->info = &st_lsm6dsx_gyro_info;
+
+ sensor->decimator_mask = ST_LSM6DSX_REG_GYRO_DEC_MASK;
+ break;
+ default:
+ return NULL;
+ }
+
+ return iio_dev;
+}
+
+int st_lsm6dsx_probe(struct st_lsm6dsx_hw *hw)
+{
+ int i, err;
+
+ mutex_init(&hw->lock);
+
+ err = st_lsm6dsx_check_whoami(hw);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
+ hw->iio_devs[i] = st_lsm6dsx_alloc_iiodev(hw, i);
+ if (!hw->iio_devs[i])
+ return -ENOMEM;
+ }
+
+ err = st_lsm6dsx_init_device(hw);
+ if (err < 0)
+ return err;
+
+ if (hw->irq > 0) {
+ err = st_lsm6dsx_allocate_rings(hw);
+ if (err < 0)
+ return err;
+ }
+
+ for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
+ err = devm_iio_device_register(hw->dev, hw->iio_devs[i]);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(st_lsm6dsx_probe);
+
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>");
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca-qxv4g6HH51o@public.gmane.org>");
+MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
new file mode 100644
index 0000000..c80e624
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
@@ -0,0 +1,111 @@
+/*
+ * STMicroelectronics st_lsm6dsx i2c driver
+ *
+ * Copyright 2016 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>
+ * Denis Ciocca <denis.ciocca-qxv4g6HH51o@public.gmane.org>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+#include "st_lsm6dsx.h"
+
+static int st_lsm6dsx_i2c_read(struct device *dev, u8 addr, int len, u8 *data)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_msg msg[2];
+
+ msg[0].addr = client->addr;
+ msg[0].flags = client->flags;
+ msg[0].len = 1;
+ msg[0].buf = &addr;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = client->flags | I2C_M_RD;
+ msg[1].len = len;
+ msg[1].buf = data;
+
+ return i2c_transfer(client->adapter, msg, 2);
+}
+
+static int st_lsm6dsx_i2c_write(struct device *dev, u8 addr, int len, u8 *data)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_msg msg;
+ u8 send[len + 1];
+
+ send[0] = addr;
+ memcpy(&send[1], data, len * sizeof(u8));
+
+ msg.addr = client->addr;
+ msg.flags = client->flags;
+ msg.len = len + 1;
+ msg.buf = send;
+
+ return i2c_transfer(client->adapter, &msg, 1);
+}
+
+static const struct st_lsm6dsx_transfer_function st_lsm6dsx_transfer_fn = {
+ .read = st_lsm6dsx_i2c_read,
+ .write = st_lsm6dsx_i2c_write,
+};
+
+static int st_lsm6dsx_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct st_lsm6dsx_hw *hw;
+
+ hw = devm_kzalloc(&client->dev, sizeof(*hw), GFP_KERNEL);
+ if (!hw)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, hw);
+ hw->name = client->name;
+ hw->dev = &client->dev;
+ hw->irq = client->irq;
+ hw->tf = &st_lsm6dsx_transfer_fn;
+
+ return st_lsm6dsx_probe(hw);
+}
+
+static const struct of_device_id st_lsm6dsx_i2c_of_match[] = {
+ {
+ .compatible = "st,lsm6ds3",
+ .data = ST_LSM6DS3_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm6dsm",
+ .data = ST_LSM6DSM_DEV_NAME,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match);
+
+static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = {
+ { ST_LSM6DS3_DEV_NAME },
+ { ST_LSM6DSM_DEV_NAME },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table);
+
+static struct i2c_driver st_lsm6dsx_driver = {
+ .driver = {
+ .name = "st_lsm6dsx_i2c",
+ .of_match_table = of_match_ptr(st_lsm6dsx_i2c_of_match),
+ },
+ .probe = st_lsm6dsx_i2c_probe,
+ .id_table = st_lsm6dsx_i2c_id_table,
+};
+module_i2c_driver(st_lsm6dsx_driver);
+
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>");
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca-qxv4g6HH51o@public.gmane.org>");
+MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx i2c driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_ring.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_ring.c
new file mode 100644
index 0000000..9a8c503
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_ring.c
@@ -0,0 +1,401 @@
+/*
+ * STMicroelectronics st_lsm6dsx sensor driver
+ *
+ * Copyright 2016 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>
+ * Denis Ciocca <denis.ciocca-qxv4g6HH51o@public.gmane.org>
+ *
+ * Licensed under the GPL-2.
+ */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/iio/kfifo_buf.h>
+#include <asm/unaligned.h>
+
+#include "st_lsm6dsx.h"
+
+#define ST_LSM6DSX_REG_FIFO_THL_ADDR 0x06
+#define ST_LSM6DSX_REG_FIFO_THH_ADDR 0x07
+#define ST_LSM6DSX_FIFO_TH_MASK 0x0fff
+#define ST_LSM6DSX_REG_FIFO_DEC_GXL_ADDR 0x08
+#define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a
+#define ST_LSM6DSX_FIFO_MODE_MASK 0x07
+#define ST_LSM6DSX_FIFO_ODR_MASK 0x78
+#define ST_LSM6DSX_REG_FIFO_DIFFL_ADDR 0x3a
+#define ST_LSM6DSX_FIFO_DIFF_MASK 0x0f
+#define ST_LSM6DSX_FIFO_EMPTY_MASK 0x10
+#define ST_LSM6DSX_REG_FIFO_OUTL_ADDR 0x3e
+
+struct st_lsm6dsx_dec_entry {
+ u8 decimator;
+ u8 val;
+};
+
+static const struct st_lsm6dsx_dec_entry st_lsm6dsx_dec_table[] = {
+ { 0, 0x0 },
+ { 1, 0x1 },
+ { 2, 0x2 },
+ { 3, 0x3 },
+ { 4, 0x4 },
+ { 8, 0x5 },
+ { 16, 0x6 },
+ { 32, 0x7 },
+};
+
+static int st_lsm6dsx_get_decimator_val(u8 val)
+{
+ int i, max_size = ARRAY_SIZE(st_lsm6dsx_dec_table);
+
+ for (i = 0; i < max_size; i++)
+ if (st_lsm6dsx_dec_table[i].decimator == val)
+ break;
+
+ return i == max_size ? 0 : st_lsm6dsx_dec_table[i].val;
+}
+
+static void st_lsm6dsx_get_max_min_odr(struct st_lsm6dsx_hw *hw,
+ u16 *max_odr, u16 *min_odr)
+{
+ struct st_lsm6dsx_sensor *sensor;
+ int i;
+
+ *max_odr = 0, *min_odr = ~0;
+ for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
+ sensor = iio_priv(hw->iio_devs[i]);
+
+ if (!(hw->enable_mask & BIT(sensor->id)))
+ continue;
+
+ *max_odr = max_t(u16, *max_odr, sensor->odr);
+ *min_odr = min_t(u16, *min_odr, sensor->odr);
+ }
+}
+
+static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw)
+{
+ struct st_lsm6dsx_sensor *sensor;
+ u16 max_odr, min_odr, sip = 0;
+ int err, i;
+ u8 data;
+
+ st_lsm6dsx_get_max_min_odr(hw, &max_odr, &min_odr);
+
+ for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
+ sensor = iio_priv(hw->iio_devs[i]);
+
+ /* update fifo decimators and sample in pattern */
+ if (hw->enable_mask & BIT(sensor->id)) {
+ sensor->sip = sensor->odr / min_odr;
+ sensor->decimator = max_odr / sensor->odr;
+ data = st_lsm6dsx_get_decimator_val(sensor->decimator);
+ } else {
+ sensor->sip = 0;
+ sensor->decimator = 0;
+ data = 0;
+ }
+
+ err = st_lsm6dsx_write_with_mask(hw,
+ ST_LSM6DSX_REG_FIFO_DEC_GXL_ADDR,
+ sensor->decimator_mask, data);
+ if (err < 0)
+ return err;
+
+ sip += sensor->sip;
+ }
+ hw->sip = sip;
+
+ return 0;
+}
+
+static int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
+ enum st_lsm6dsx_fifo_mode fifo_mode)
+{
+ u8 data;
+ int err;
+
+ switch (fifo_mode) {
+ case ST_LSM6DSX_FIFO_BYPASS:
+ data = fifo_mode;
+ break;
+ case ST_LSM6DSX_FIFO_CONT:
+ data = fifo_mode | 0x40;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = hw->tf->write(hw->dev, ST_LSM6DSX_REG_FIFO_MODE_ADDR,
+ sizeof(data), &data);
+ if (err < 0)
+ return err;
+
+ hw->fifo_mode = fifo_mode;
+
+ return 0;
+}
+
+int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark)
+{
+ u16 fifo_watermark = ~0, cur_watermark, sip = 0;
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+ struct st_lsm6dsx_sensor *cur_sensor;
+ int i, err;
+ u8 data;
+
+ for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
+ cur_sensor = iio_priv(hw->iio_devs[i]);
+
+ if (!(hw->enable_mask & BIT(cur_sensor->id)))
+ continue;
+
+ cur_watermark = (cur_sensor == sensor) ? watermark
+ : cur_sensor->watermark;
+
+ fifo_watermark = min_t(u16, fifo_watermark, cur_watermark);
+ sip += cur_sensor->sip;
+ }
+
+ if (!sip)
+ return 0;
+
+ fifo_watermark = max_t(u16, fifo_watermark, sip);
+ fifo_watermark = (fifo_watermark / sip) * sip;
+ fifo_watermark = fifo_watermark * ST_LSM6DSX_SAMPLE_DEPTH;
+
+ mutex_lock(&hw->lock);
+
+ err = hw->tf->read(hw->dev, ST_LSM6DSX_REG_FIFO_THH_ADDR,
+ sizeof(data), &data);
+ if (err < 0)
+ goto out;
+
+ fifo_watermark = ((data & ~ST_LSM6DSX_FIFO_TH_MASK) << 8) |
+ (fifo_watermark & ST_LSM6DSX_FIFO_TH_MASK);
+
+ err = hw->tf->write(hw->dev, ST_LSM6DSX_REG_FIFO_THL_ADDR,
+ sizeof(fifo_watermark), (u8 *)&fifo_watermark);
+out:
+ mutex_unlock(&hw->lock);
+
+ return err < 0 ? err : 0;
+}
+
+static int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
+{
+ u16 fifo_len, pattern_len = hw->sip * ST_LSM6DSX_SAMPLE_SIZE;
+ int err, acc_sip, gyro_sip, read_len, offset, samples;
+ struct st_lsm6dsx_sensor *acc_sensor, *gyro_sensor;
+ s64 acc_ts, acc_delta_ts, gyro_ts, gyro_delta_ts;
+ u8 iio_buf[ALIGN(ST_LSM6DSX_SAMPLE_SIZE, sizeof(s64)) + sizeof(s64)];
+ u8 fifo_status[2], buf[pattern_len];
+
+ err = hw->tf->read(hw->dev, ST_LSM6DSX_REG_FIFO_DIFFL_ADDR,
+ sizeof(fifo_status), fifo_status);
+ if (err < 0)
+ return err;
+
+ if (fifo_status[1] & ST_LSM6DSX_FIFO_EMPTY_MASK)
+ return 0;
+
+ fifo_status[1] &= ST_LSM6DSX_FIFO_DIFF_MASK;
+ fifo_len = (u16)get_unaligned_le16(fifo_status) * ST_LSM6DSX_CHAN_SIZE;
+ samples = fifo_len / ST_LSM6DSX_SAMPLE_SIZE;
+ fifo_len = (fifo_len / pattern_len) * pattern_len;
+ /*
+ * leave one complete pattern in FIFO to guarantee
+ * proper alignment
+ */
+ fifo_len -= pattern_len;
+
+ /* compute delta timestamp */
+ acc_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
+ acc_ts = acc_sensor->ts - acc_sensor->delta_ts;
+ acc_delta_ts = div_s64(acc_sensor->delta_ts * acc_sensor->decimator,
+ samples);
+
+ gyro_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_GYRO]);
+ gyro_ts = gyro_sensor->ts - gyro_sensor->delta_ts;
+ gyro_delta_ts = div_s64(gyro_sensor->delta_ts * gyro_sensor->decimator,
+ samples);
+
+ for (read_len = 0; read_len < fifo_len; read_len += pattern_len) {
+ err = hw->tf->read(hw->dev, ST_LSM6DSX_REG_FIFO_OUTL_ADDR,
+ sizeof(buf), buf);
+ if (err < 0)
+ return err;
+
+ gyro_sip = gyro_sensor->sip;
+ acc_sip = acc_sensor->sip;
+ offset = 0;
+
+ while (acc_sip > 0 || gyro_sip > 0) {
+ if (gyro_sip-- > 0) {
+ memcpy(iio_buf, &buf[offset],
+ ST_LSM6DSX_SAMPLE_SIZE);
+ iio_push_to_buffers_with_timestamp(
+ hw->iio_devs[ST_LSM6DSX_ID_GYRO],
+ iio_buf, gyro_ts);
+ offset += ST_LSM6DSX_SAMPLE_SIZE;
+ gyro_ts += gyro_delta_ts;
+ }
+
+ if (acc_sip-- > 0) {
+ memcpy(iio_buf, &buf[offset],
+ ST_LSM6DSX_SAMPLE_SIZE);
+ iio_push_to_buffers_with_timestamp(
+ hw->iio_devs[ST_LSM6DSX_ID_ACC],
+ iio_buf, acc_ts);
+ offset += ST_LSM6DSX_SAMPLE_SIZE;
+ acc_ts += acc_delta_ts;
+ }
+ }
+ }
+
+ return read_len;
+}
+
+static int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw)
+{
+ int err;
+
+ disable_irq(hw->irq);
+
+ st_lsm6dsx_read_fifo(hw);
+ err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_BYPASS);
+
+ enable_irq(hw->irq);
+
+ return err;
+}
+
+static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+ int err;
+
+ if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS) {
+ err = st_lsm6dsx_flush_fifo(hw);
+ if (err < 0)
+ return err;
+ }
+
+ err = enable ? st_lsm6dsx_sensor_enable(sensor)
+ : st_lsm6dsx_sensor_disable(sensor);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6dsx_update_decimators(hw);
+ if (err < 0)
+ return err;
+
+ err = st_lsm6dsx_update_watermark(sensor, sensor->watermark);
+ if (err < 0)
+ return err;
+
+ if (hw->enable_mask) {
+ err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
+ if (err < 0)
+ return err;
+
+ sensor->ts = iio_get_time_ns(iio_dev);
+ }
+
+ return 0;
+}
+
+static irqreturn_t st_lsm6dsx_ring_handler_irq(int irq, void *private)
+{
+ struct st_lsm6dsx_hw *hw = (struct st_lsm6dsx_hw *)private;
+ struct st_lsm6dsx_sensor *sensor;
+ int i;
+
+ if (!hw->sip)
+ return IRQ_NONE;
+
+ for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
+ sensor = iio_priv(hw->iio_devs[i]);
+
+ if (sensor->sip > 0) {
+ s64 timestamp;
+
+ timestamp = iio_get_time_ns(hw->iio_devs[i]);
+ sensor->delta_ts = timestamp - sensor->ts;
+ sensor->ts = timestamp;
+ }
+ }
+
+ return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t st_lsm6dsx_ring_handler_thread(int irq, void *private)
+{
+ struct st_lsm6dsx_hw *hw = (struct st_lsm6dsx_hw *)private;
+ int count;
+
+ count = st_lsm6dsx_read_fifo(hw);
+
+ return !count ? IRQ_NONE : IRQ_HANDLED;
+}
+
+static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev)
+{
+ return st_lsm6dsx_update_fifo(iio_dev, true);
+}
+
+static int st_lsm6dsx_buffer_postdisable(struct iio_dev *iio_dev)
+{
+ return st_lsm6dsx_update_fifo(iio_dev, false);
+}
+
+static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = {
+ .preenable = st_lsm6dsx_buffer_preenable,
+ .postdisable = st_lsm6dsx_buffer_postdisable,
+};
+
+int st_lsm6dsx_allocate_rings(struct st_lsm6dsx_hw *hw)
+{
+ struct iio_buffer *buffer;
+ unsigned long irq_type;
+ int i, err;
+
+ irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
+
+ switch (irq_type) {
+ case IRQF_TRIGGER_HIGH:
+ case IRQF_TRIGGER_RISING:
+ break;
+ default:
+ dev_info(hw->dev,
+ "mode %lx unsupported, using IRQF_TRIGGER_HIGH\n",
+ irq_type);
+ irq_type = IRQF_TRIGGER_HIGH;
+ break;
+ }
+
+ err = devm_request_threaded_irq(hw->dev, hw->irq,
+ st_lsm6dsx_ring_handler_irq,
+ st_lsm6dsx_ring_handler_thread,
+ irq_type | IRQF_ONESHOT,
+ hw->name, hw);
+ if (err) {
+ dev_err(hw->dev, "failed to request trigger irq %d\n",
+ hw->irq);
+ return err;
+ }
+
+ for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
+ buffer = devm_iio_kfifo_allocate(hw->dev);
+ if (!buffer)
+ return -ENOMEM;
+
+ iio_device_attach_buffer(hw->iio_devs[i], buffer);
+ hw->iio_devs[i]->modes |= INDIO_BUFFER_SOFTWARE;
+ hw->iio_devs[i]->setup_ops = &st_lsm6dsx_buffer_ops;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
new file mode 100644
index 0000000..262eae6
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
@@ -0,0 +1,129 @@
+/*
+ * STMicroelectronics st_lsm6dsx spi driver
+ *
+ * Copyright 2016 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>
+ * Denis Ciocca <denis.ciocca-qxv4g6HH51o@public.gmane.org>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+#include "st_lsm6dsx.h"
+
+#define SENSORS_SPI_READ 0x80
+
+static int st_lsm6dsx_spi_read(struct device *dev, u8 addr, int len,
+ u8 *data)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct st_lsm6dsx_hw *hw = spi_get_drvdata(spi);
+ int err;
+
+ struct spi_transfer xfers[] = {
+ {
+ .tx_buf = hw->tb.tx_buf,
+ .bits_per_word = 8,
+ .len = 1,
+ },
+ {
+ .rx_buf = hw->tb.rx_buf,
+ .bits_per_word = 8,
+ .len = len,
+ }
+ };
+
+ hw->tb.tx_buf[0] = addr | SENSORS_SPI_READ;
+
+ err = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers));
+ if (err < 0)
+ return err;
+
+ memcpy(data, hw->tb.rx_buf, len * sizeof(u8));
+
+ return len;
+}
+
+static int st_lsm6dsx_spi_write(struct device *dev, u8 addr, int len,
+ u8 *data)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct st_lsm6dsx_hw *hw = spi_get_drvdata(spi);
+
+ struct spi_transfer xfers = {
+ .tx_buf = hw->tb.tx_buf,
+ .bits_per_word = 8,
+ .len = len + 1,
+ };
+
+ if (len >= ST_LSM6DSX_TX_MAX_LENGTH)
+ return -ENOMEM;
+
+ hw->tb.tx_buf[0] = addr;
+ memcpy(&hw->tb.tx_buf[1], data, len);
+
+ return spi_sync_transfer(spi, &xfers, 1);
+}
+
+static const struct st_lsm6dsx_transfer_function st_lsm6dsx_transfer_fn = {
+ .read = st_lsm6dsx_spi_read,
+ .write = st_lsm6dsx_spi_write,
+};
+
+static int st_lsm6dsx_spi_probe(struct spi_device *spi)
+{
+ struct st_lsm6dsx_hw *hw;
+
+ hw = devm_kzalloc(&spi->dev, sizeof(*hw), GFP_KERNEL);
+ if (!hw)
+ return -ENOMEM;
+
+ spi_set_drvdata(spi, hw);
+ hw->name = spi->modalias;
+ hw->dev = &spi->dev;
+ hw->irq = spi->irq;
+ hw->tf = &st_lsm6dsx_transfer_fn;
+
+ return st_lsm6dsx_probe(hw);
+}
+
+static const struct of_device_id st_lsm6dsx_spi_of_match[] = {
+ {
+ .compatible = "st,lsm6ds3",
+ .data = ST_LSM6DS3_DEV_NAME,
+ },
+ {
+ .compatible = "st,lsm6dsm",
+ .data = ST_LSM6DSM_DEV_NAME,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match);
+
+static const struct spi_device_id st_lsm6dsx_spi_id_table[] = {
+ { ST_LSM6DS3_DEV_NAME },
+ { ST_LSM6DSM_DEV_NAME },
+ {},
+};
+MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table);
+
+static struct spi_driver st_lsm6dsx_driver = {
+ .driver = {
+ .name = "st_lsm6dsx_spi",
+ .of_match_table = of_match_ptr(st_lsm6dsx_spi_of_match),
+ },
+ .probe = st_lsm6dsx_spi_probe,
+ .id_table = st_lsm6dsx_spi_id_table,
+};
+module_spi_driver(st_lsm6dsx_driver);
+
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi-qxv4g6HH51o@public.gmane.org>");
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca-qxv4g6HH51o@public.gmane.org>");
+MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx spi driver");
+MODULE_LICENSE("GPL v2");
--
2.9.3
^ permalink raw reply related
* [PATCH v2 0/2] add support to STM LSM6DS3-LSM6DSM 6-axis Mems sensor
From: Lorenzo Bianconi @ 2016-11-30 20:05 UTC (permalink / raw)
To: jic23-DgEjT+Ai2ygdnm+yROfE0A
Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, lorenzo.bianconi-qxv4g6HH51o
Changes since v1:
- add sw fifo support
- drop trigger dependency
- use iio_claim_direct_mode() routine instead of grabbing the mutex directly
- use more unique prefix for all defines
- use info_mask_shared_by_all element for sampling_frequency
- use devm_iio_* routines
- use of_match_ptr instead of access directly to of_match_table
- fix device tree binding
- rename st_lsm6dsx_dev in st_lsm6dsx_hw
- cosmetics
Lorenzo Bianconi (2):
iio: imu: add support to lsm6dsx driver
Documentation: dt: iio: add st_lsm6dsx sensor device binding
.../devicetree/bindings/iio/imu/st_lsm6dsx.txt | 24 +
drivers/iio/imu/Kconfig | 1 +
drivers/iio/imu/Makefile | 2 +
drivers/iio/imu/st_lsm6dsx/Kconfig | 23 +
drivers/iio/imu/st_lsm6dsx/Makefile | 6 +
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 107 ++++
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 696 +++++++++++++++++++++
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c | 111 ++++
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_ring.c | 401 ++++++++++++
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c | 129 ++++
10 files changed, 1500 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt
create mode 100644 drivers/iio/imu/st_lsm6dsx/Kconfig
create mode 100644 drivers/iio/imu/st_lsm6dsx/Makefile
create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_ring.c
create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
--
2.9.3
^ permalink raw reply
* Re: Re: [RFC PATCH] ARM: dts: sun8i: add simplefb node for H3
From: Jean-Francois Moine @ 2016-11-30 19:37 UTC (permalink / raw)
To: Jernej Škrabec
Cc: Icenowy Zheng, devicetree-u79uwXL29TY76Z2rM5mHXA,
wens-jdAy2FN1RRM, linux-kernel, linux-sunxi,
maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <2717236.xBNAaGdqdc@jernej-laptop>
On Wed, 30 Nov 2016 20:14:11 +0100
Jernej Škrabec <jernej.skrabec-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> Dne četrtek, 01. december 2016 ob 03:03:14 CET je Icenowy Zheng napisal(a):
> > 2016年12月1日 02:49于 Jernej Skrabec <jernej.skrabec-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>写道:
> >
> > > Hi Jean-François,
> > >
> > > Dne sreda, 30. november 2016 10.35.08 UTC+1 je oseba Jean-François Moine
> napisala:
> > >> On Tue, 29 Nov 2016 22:59:32 +0100
> > >>
> > >> Maxime Ripard <maxime...-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> > >> > > > I'm still not sure which pipeline should I use.
> > >> > > >
> > >> > > > And, it seems that HDMI Slow Clock is not needed?
> > >> > > >
> > >> > > > (seems that it's only for EDID, but simplefb won't use EDID)
> > >> > >
> > >> > > So, I don't see how this may work.
> > >> > > How can the u-boot know the resolutions of the HDMI display device?
> > >> > >
> > >> > > In other words: I have a new H3 board with the last u-boot and
> > >> > > kernel.
> > >> > > I plug my (rather old or brand new) HDMI display device.
> > >> > > After powering on the system, I hope to get something on the screen.
> > >> > > How?
> > >> >
> > >> > If it works like the driver for the first display engine in U-Boot, it
> > >> > will use the preferred mode reported by the EDID, and will fallback to
> > >> > 1024x768 if it cannot access it.
> > >>
> > >> Icenowy wrote: "simplefb won't use EDID"
> > >>
> > >> Then, if it is like in the kernel, the 1024x768 mode is VGA. It does
> > >> not work with HDMI (different timings).
> > >
> > > U-Boot driver now accept any timings recommended by EDID. So far it
> > > was tested with at least following resolutions:
> > > - 1920x1080 @ 60 Hz
> > > - 1280x1024 @ 60 Hz
> > > - 1280x800 @ 60 Hz (slight clock difference)
> > > - 800x480 (not sure about frame rate)
> > > - 3840x2160 @ 30 Hz (4K)
> >
> > I tested on 1024x600 (If my memory is right, it's @ 60Hz)
> >
> > > and nobody complained so far. I'm pretty sure 1024x768 would work.
Check the timings offered by the DRM core.
> > >
> > >> > Maybe it would be worth exchanging on the EDID code that has been done
> > >> > for the u-boot driver too, so that it can be fixed in your driver.
> > >>
> > >> The u-boot got my code, and, up to now, I could not fix the random or
> > >> permanent failures of EDID reading in some boards.
> > >
> > > I only have one OPi2, but as I said, EDID always worked for me.
Happy guy!
> > > The only
> > > code left from you is for DE2. HDMI stuff is basically copied from Rockhip
> > > driver (including EDID reading), TCON code is now reverted to the same as
> > > it is in sunxi_display.c. I think it is worth to take a look at EDID code
> > > and compare it.
> >
> > So is the TCON of DE 2.0 identical to the original TCON?
> >
> > If so, we should reuse sun4i-tcon ...
>
> Well, TCON is splitted in two parts (two base addresses), one for HDMI and one
> for TV. However, register offsets are same as before, so I guess driver
> reusage make sense. I think that there are few additional registers, but they
> can be ignored for simplefb.
The TCON1 of the H3 is not usable (no ckock). Analog TV has its own
clock and I/O area.
--
Ken ar c'hentañ | ** Breizh ha Linux atav! **
Jef | http://moinejf.free.fr/
--
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply
* Re: [PATCH v3 3/3] fpga manager: Add cyclone-ps-spi driver for Altera FPGAs
From: atull @ 2016-11-30 19:23 UTC (permalink / raw)
To: Joshua Clayton
Cc: Mark Rutland, Moritz Fischer, devicetree, Russell King,
linux-kernel, Rob Herring, linux-arm-kernel
In-Reply-To: <6989b2ee-9caf-81b3-2328-9d4e287794cb@gmail.com>
On Wed, 30 Nov 2016, Joshua Clayton wrote:
Hi Joshua,
> Hi Alan,
>
> On 11/30/2016 09:45 AM, atull wrote:
> > On Wed, 30 Nov 2016, Joshua Clayton wrote:
> >
> > Hi Clayton,
> >
> > I just have a few minor one line changes below. Only one
> > is operational, I should have caught that earlier.
> >
> Thanks for the speedy review.
> >> +};
> >> +MODULE_DEVICE_TABLE(of, of_ef_match);
> >> +
> >> +static enum fpga_mgr_states cyclonespi_state(struct fpga_manager *mgr)
> >> +{
> >> + return mgr->state;
> >> +}
> > This function gets called once to initialize mgr->state in
> > fpga_mgr_register(). So it should at least return the state the FPGA
> > is at then. If it is unknown, it can just return
> > FPGA_MGR_STATE_UNKNOWN.
> >
> I guess I didn't understand the purpose of this function.
> The driver has access to the status pin at this phase, so I can return
> FPGA_MGR_STATE_UNKNOWN or FPGA_MGR_STATE_RESET depending
> on the state of that pin.
>
> >> +
> >> +static int cyclonespi_write_init(struct fpga_manager *mgr, u32 flags,
> >> + const char *buf, size_t count)
> > Minor, but please fix the indentation of 'const' to match that of
> > 'struct' above. checkpatch.pl is probably issuing warnings
> > about that.
> I double checked. The indentation is correct here. It only has
> The appearance of being off by one due to the diff format.
Yes, I understand.
> >> +{
> >> + struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
> >> + int i;
> >> +
> >> + if (flags & FPGA_MGR_PARTIAL_RECONFIG) {
> >> + dev_err(&mgr->dev, "Partial reconfiguration not supported.\n");
> >> + return -EINVAL;
> >> + }
> >> +
> >> + gpiod_set_value(conf->config, 0);
> >> + usleep_range(FPGA_RESET_TIME, FPGA_RESET_TIME + 20);
> >> + if (gpiod_get_value(conf->status) == 1) {
> >> + dev_err(&mgr->dev, "Status pin should be low.\n");
> >> + return -EIO;
> >> + }
> >> +
> >> + gpiod_set_value(conf->config, 1);
> >> + for (i = 0; i < (FPGA_MAX_DELAY / FPGA_MIN_DELAY); i++) {
> >> + usleep_range(FPGA_MIN_DELAY, FPGA_MIN_DELAY + 20);
> >> + if (gpiod_get_value(conf->status))
> >> + return 0;
> >> + }
> >> +
> >> + dev_err(&mgr->dev, "Status pin not ready.\n");
> >> + return -EIO;
> >> +}
> >> +
> >> +static void rev_buf(void *buf, size_t len)
> >> +{
> >> + u32 *fw32 = (u32 *)buf;
> >> + const u32 *fw_end = (u32 *)(buf + len);
> >> +
> >> + /* set buffer to lsb first */
> >> + while (fw32 < fw_end) {
> >> + *fw32 = bitrev8x4(*fw32);
> >> + fw32++;
> >> + }
> >> +}
> >> +
> >> +static int cyclonespi_write(struct fpga_manager *mgr, const char *buf,
> >> + size_t count)
> > Please fix alignment here also.
> Same as above. Indentation is OK.
>
>
> I'll get a v4 turned around soon.
No rush since the other two patches need acks from
their respective maintainers and this won't be able
to go in without them. But with that one change
it looks good to me.
Alan
> Thanks,
> Joshua
>
^ permalink raw reply
* Re: Re: [RFC PATCH] ARM: dts: sun8i: add simplefb node for H3
From: Jernej Škrabec @ 2016-11-30 19:14 UTC (permalink / raw)
To: Icenowy Zheng
Cc: linux-sunxi, linux-kernel,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, wens-jdAy2FN1RRM,
maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
In-Reply-To: <20161130220324.3Kg4VPEw-3YhIAYTWRJA0PDqKvflMoHmW9unr2Ajn@public.gmane.org>
Dne četrtek, 01. december 2016 ob 03:03:14 CET je Icenowy Zheng napisal(a):
> 2016年12月1日 02:49于 Jernej Skrabec <jernej.skrabec-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>写道:
>
> > Hi Jean-François,
> >
> > Dne sreda, 30. november 2016 10.35.08 UTC+1 je oseba Jean-François Moine
napisala:
> >> On Tue, 29 Nov 2016 22:59:32 +0100
> >>
> >> Maxime Ripard <maxime...-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> >> > > > I'm still not sure which pipeline should I use.
> >> > > >
> >> > > > And, it seems that HDMI Slow Clock is not needed?
> >> > > >
> >> > > > (seems that it's only for EDID, but simplefb won't use EDID)
> >> > >
> >> > > So, I don't see how this may work.
> >> > > How can the u-boot know the resolutions of the HDMI display device?
> >> > >
> >> > > In other words: I have a new H3 board with the last u-boot and
> >> > > kernel.
> >> > > I plug my (rather old or brand new) HDMI display device.
> >> > > After powering on the system, I hope to get something on the screen.
> >> > > How?
> >> >
> >> > If it works like the driver for the first display engine in U-Boot, it
> >> > will use the preferred mode reported by the EDID, and will fallback to
> >> > 1024x768 if it cannot access it.
> >>
> >> Icenowy wrote: "simplefb won't use EDID"
> >>
> >> Then, if it is like in the kernel, the 1024x768 mode is VGA. It does
> >> not work with HDMI (different timings).
> >
> > U-Boot driver now accept any timings recommended by EDID. So far it
> > was tested with at least following resolutions:
> > - 1920x1080 @ 60 Hz
> > - 1280x1024 @ 60 Hz
> > - 1280x800 @ 60 Hz (slight clock difference)
> > - 800x480 (not sure about frame rate)
> > - 3840x2160 @ 30 Hz (4K)
>
> I tested on 1024x600 (If my memory is right, it's @ 60Hz)
>
> > and nobody complained so far. I'm pretty sure 1024x768 would work.
> >
> >> > Maybe it would be worth exchanging on the EDID code that has been done
> >> > for the u-boot driver too, so that it can be fixed in your driver.
> >>
> >> The u-boot got my code, and, up to now, I could not fix the random or
> >> permanent failures of EDID reading in some boards.
> >
> > I only have one OPi2, but as I said, EDID always worked for me. The only
> > code left from you is for DE2. HDMI stuff is basically copied from Rockhip
> > driver (including EDID reading), TCON code is now reverted to the same as
> > it is in sunxi_display.c. I think it is worth to take a look at EDID code
> > and compare it.
>
> So is the TCON of DE 2.0 identical to the original TCON?
>
> If so, we should reuse sun4i-tcon ...
>
Well, TCON is splitted in two parts (two base addresses), one for HDMI and one
for TV. However, register offsets are same as before, so I guess driver
reusage make sense. I think that there are few additional registers, but they
can be ignored for simplefb.
> >
> >
> >> --
> >> Ken ar c'hentañ | ** Breizh ha Linux atav! **
> >> Jef | http://moinejf.free.fr/
> >
> > Best regards,
> > Jernej Škrabec
> >
> > --
> > You received this message because you are subscribed to the Google Groups
> > "linux-sunxi" group. To unsubscribe from this group and stop receiving
> > emails from it, send an email to
> > linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit
> > https://groups.google.com/d/optout.
Best regards,
Jernej Škrabec
--
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply
* Re: [PATCH v2 3/4] dt-bindings: phy: Add support for QMP phy
From: Stephen Boyd @ 2016-11-30 19:12 UTC (permalink / raw)
To: Vivek Gautam
Cc: kishon, robh+dt, Mark Rutland, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, Srinivas Kandagatla, linux-arm-msm
In-Reply-To: <CAFp+6iGeNQKuP=WmshPG0088CNy8hosdfN+unuS6bhYqJJaKRQ@mail.gmail.com>
On 11/29, Vivek Gautam wrote:
> On Tue, Nov 29, 2016 at 4:25 AM, Stephen Boyd <sboyd@codeaurora.org> wrote:
> > On 11/22, Vivek Gautam wrote:
> >> diff --git a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
> >> new file mode 100644
> >> index 0000000..ffb173b
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
> >> @@ -0,0 +1,74 @@
>
> >
> >> + "pipe<port-number>" for pipe clock specific to
> >> + each port/lane (Optional).
> >
> > The pipe clocks are orphaned right now. We should add an output
> > clock from the phy to go into the controller and back into the
> > phy if I recall correctly. The phy should be a clock provider
> > itself so it can output the pipe clock source into GCC and back
> > into the phy and controller.
> >
> >> + - resets: a list of phandles and reset controller specifier pairs,
> >> + one for each entry in reset-names.
> >> + - reset-names: must be "phy" for reset of phy block,
> >> + "common" for phy common block reset,
> >> + "cfg" for phy's ahb cfg block reset (Optional).
> >> + "port<port-number>" for reset specific to
> >> + each port/lane (Optional).
> >> + - vdda-phy-supply: Phandle to a regulator supply to PHY core block.
> >> + - vdda-pll-supply: Phandle to 1.8V regulator supply to PHY refclk pll block.
> >> +
> >> +Optional properties:
> >> + - vddp-ref-clk-supply: Phandle to a regulator supply to any specific refclk
> >> + pll block.
> >> +
> >> +Example:
> >> + pcie_phy: pciephy@34000 {
> >
> > pcie-phy or just phy as the node name?
>
> How about just 'phy'? The label pcie_phy anyways explains the use.
>
>
phy is a great color choice for the shed.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* Re: Re: [RFC PATCH] ARM: dts: sun8i: add simplefb node for H3
From: Icenowy Zheng @ 2016-11-30 19:03 UTC (permalink / raw)
To: Jernej Skrabec
Cc: linux-sunxi, linux-kernel,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, jernej.skrabec-gGgVlfcn5nU,
wens-jdAy2FN1RRM, maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
[-- Attachment #1: Type: text/html, Size: 4545 bytes --]
^ permalink raw reply
* Re: [PATCH v3 3/3] fpga manager: Add cyclone-ps-spi driver for Altera FPGAs
From: Joshua Clayton @ 2016-11-30 18:59 UTC (permalink / raw)
To: atull
Cc: Moritz Fischer, Rob Herring, Mark Rutland, Russell King,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <alpine.DEB.2.10.1611301122470.2617@atull-730U3E-740U3E>
Hi Alan,
On 11/30/2016 09:45 AM, atull wrote:
> On Wed, 30 Nov 2016, Joshua Clayton wrote:
>
> Hi Clayton,
>
> I just have a few minor one line changes below. Only one
> is operational, I should have caught that earlier.
>
Thanks for the speedy review.
>> +};
>> +MODULE_DEVICE_TABLE(of, of_ef_match);
>> +
>> +static enum fpga_mgr_states cyclonespi_state(struct fpga_manager *mgr)
>> +{
>> + return mgr->state;
>> +}
> This function gets called once to initialize mgr->state in
> fpga_mgr_register(). So it should at least return the state the FPGA
> is at then. If it is unknown, it can just return
> FPGA_MGR_STATE_UNKNOWN.
>
I guess I didn't understand the purpose of this function.
The driver has access to the status pin at this phase, so I can return
FPGA_MGR_STATE_UNKNOWN or FPGA_MGR_STATE_RESET depending
on the state of that pin.
>> +
>> +static int cyclonespi_write_init(struct fpga_manager *mgr, u32 flags,
>> + const char *buf, size_t count)
> Minor, but please fix the indentation of 'const' to match that of
> 'struct' above. checkpatch.pl is probably issuing warnings
> about that.
I double checked. The indentation is correct here. It only has
The appearance of being off by one due to the diff format.
>> +{
>> + struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
>> + int i;
>> +
>> + if (flags & FPGA_MGR_PARTIAL_RECONFIG) {
>> + dev_err(&mgr->dev, "Partial reconfiguration not supported.\n");
>> + return -EINVAL;
>> + }
>> +
>> + gpiod_set_value(conf->config, 0);
>> + usleep_range(FPGA_RESET_TIME, FPGA_RESET_TIME + 20);
>> + if (gpiod_get_value(conf->status) == 1) {
>> + dev_err(&mgr->dev, "Status pin should be low.\n");
>> + return -EIO;
>> + }
>> +
>> + gpiod_set_value(conf->config, 1);
>> + for (i = 0; i < (FPGA_MAX_DELAY / FPGA_MIN_DELAY); i++) {
>> + usleep_range(FPGA_MIN_DELAY, FPGA_MIN_DELAY + 20);
>> + if (gpiod_get_value(conf->status))
>> + return 0;
>> + }
>> +
>> + dev_err(&mgr->dev, "Status pin not ready.\n");
>> + return -EIO;
>> +}
>> +
>> +static void rev_buf(void *buf, size_t len)
>> +{
>> + u32 *fw32 = (u32 *)buf;
>> + const u32 *fw_end = (u32 *)(buf + len);
>> +
>> + /* set buffer to lsb first */
>> + while (fw32 < fw_end) {
>> + *fw32 = bitrev8x4(*fw32);
>> + fw32++;
>> + }
>> +}
>> +
>> +static int cyclonespi_write(struct fpga_manager *mgr, const char *buf,
>> + size_t count)
> Please fix alignment here also.
Same as above. Indentation is OK.
I'll get a v4 turned around soon.
Thanks,
Joshua
--
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] ARM: dts: sun8i: add simplefb node for H3
From: Jernej Skrabec @ 2016-11-30 18:49 UTC (permalink / raw)
To: linux-sunxi
Cc: maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
icenowy-ymACFijhrKM, wens-jdAy2FN1RRM, jernej.skrabec-gGgVlfcn5nU,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20161130103503.01061303ace71c74e1cac66f-GANU6spQydw@public.gmane.org>
[-- Attachment #1.1: Type: text/plain, Size: 2662 bytes --]
Hi Jean-François,
Dne sreda, 30. november 2016 10.35.08 UTC+1 je oseba Jean-François Moine
napisala:
>
> On Tue, 29 Nov 2016 22:59:32 +0100
> Maxime Ripard <maxime...-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org <javascript:>> wrote:
>
> > > > I'm still not sure which pipeline should I use.
> > > >
> > > > And, it seems that HDMI Slow Clock is not needed?
> > > >
> > > > (seems that it's only for EDID, but simplefb won't use EDID)
> > >
> > > So, I don't see how this may work.
> > > How can the u-boot know the resolutions of the HDMI display device?
> > >
> > > In other words: I have a new H3 board with the last u-boot and kernel.
> > > I plug my (rather old or brand new) HDMI display device.
> > > After powering on the system, I hope to get something on the screen.
> > > How?
> >
> > If it works like the driver for the first display engine in U-Boot, it
> > will use the preferred mode reported by the EDID, and will fallback to
> > 1024x768 if it cannot access it.
>
> Icenowy wrote: "simplefb won't use EDID"
>
> Then, if it is like in the kernel, the 1024x768 mode is VGA. It does
> not work with HDMI (different timings).
>
U-Boot driver now accept any timings recommended by EDID. So far it
was tested with at least following resolutions:
- 1920x1080 @ 60 Hz
- 1280x1024 @ 60 Hz
- 1280x800 @ 60 Hz (slight clock difference)
- 800x480 (not sure about frame rate)
- 3840x2160 @ 30 Hz (4K)
and nobody complained so far. I'm pretty sure 1024x768 would work.
> > Maybe it would be worth exchanging on the EDID code that has been done
> > for the u-boot driver too, so that it can be fixed in your driver.
>
> The u-boot got my code, and, up to now, I could not fix the random or
> permanent failures of EDID reading in some boards.
>
>
I only have one OPi2, but as I said, EDID always worked for me. The only
code left from you is for DE2. HDMI stuff is basically copied from Rockhip
driver (including EDID reading), TCON code is now reverted to the same as
it is in sunxi_display.c. I think it is worth to take a look at EDID code
and
compare it.
> --
> Ken ar c'hentañ | ** Breizh ha Linux atav! **
> Jef | http://moinejf.free.fr/
Best regards,
Jernej Škrabec
--
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
[-- Attachment #1.2: Type: text/html, Size: 4177 bytes --]
^ permalink raw reply
* Re: [PATCH 4/6] net: ethernet: ti: cpts: add ptp pps support
From: Richard Cochran @ 2016-11-30 18:45 UTC (permalink / raw)
To: Grygorii Strashko
Cc: David S. Miller, netdev, Mugunthan V N, Sekhar Nori, linux-kernel,
linux-omap, Rob Herring, devicetree, Murali Karicheri,
Wingman Kwok
In-Reply-To: <20161128230428.6872-5-grygorii.strashko@ti.com>
On Mon, Nov 28, 2016 at 05:04:26PM -0600, Grygorii Strashko wrote:
> +static cycle_t cpts_cc_ns2cyc(struct cpts *cpts, u64 nsecs)
> +{
> + cycle_t cyc = (nsecs << cpts->cc.shift) + nsecs;
> +
> + do_div(cyc, cpts->cc.mult);
> +
> + return cyc;
> +}
So you set the comparison value once per second, based on cc.mult.
But when the clock is being actively synchronized, user space calls to
clock_adjtimex() will change cc.mult. This can happen several times
per second, depending on the PTP Sync rate.
In order to produce the PPS edge correctly, you would have to adjust
the comparison value whenever cc.mult changes, but of course this is
unworkable.
So I'll have to say NAK for this patch.
Thanks,
Richard
^ permalink raw reply
* Re: [PATCH v2 07/13] net: ethernet: ti: cpts: rework initialization/deinitialization
From: Grygorii Strashko @ 2016-11-30 18:30 UTC (permalink / raw)
To: Richard Cochran
Cc: David S. Miller, netdev-u79uwXL29TY76Z2rM5mHXA, Mugunthan V N,
Sekhar Nori, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA, Murali Karicheri, Wingman Kwok
In-Reply-To: <2037427d-0ab6-9446-450d-21c34123c03b-l0cyMroinI0@public.gmane.org>
Hi Richard,
On 11/29/2016 09:50 AM, Grygorii Strashko wrote:
> On 11/29/2016 04:07 AM, Richard Cochran wrote:
>> On Mon, Nov 28, 2016 at 05:03:31PM -0600, Grygorii Strashko wrote:
>>> +int cpts_register(struct cpts *cpts)
>>> {
>>> int err, i;
>>>
>>> - cpts->info = cpts_info;
>>> - spin_lock_init(&cpts->lock);
>>> -
>>> - cpts->cc.read = cpts_systim_read;
>>> - cpts->cc.mask = CLOCKSOURCE_MASK(32);
>>> - cpts->cc_mult = mult;
>>> - cpts->cc.mult = mult;
>>> - cpts->cc.shift = shift;
>>> -
>>> INIT_LIST_HEAD(&cpts->events);
>>> INIT_LIST_HEAD(&cpts->pool);
>>> for (i = 0; i < CPTS_MAX_EVENTS; i++)
>>> list_add(&cpts->pool_data[i].list, &cpts->pool);
>>>
>>> - cpts_clk_init(dev, cpts);
>>> + clk_enable(cpts->refclk);
>>> +
>>> cpts_write32(cpts, CPTS_EN, control);
>>> cpts_write32(cpts, TS_PEND_EN, int_enable);
>>>
>>> + cpts->cc.mult = cpts->cc_mult;
>>
>> It is not clear why you set cc.mult in a different place than
>> cc.shift. That isn't logical, but maybe later patches make it
>> clear...
>
> cc.mult has to be reloaded to original value each time CPTS is registered(restarted)
> as it can be modified by cpts_ptp_adjfreq().
>
> While cc.shift is static.
>
>
Will it ok if i will add comment here and re-send series?
--
regards,
-grygorii
--
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 net-next v4 0/4] Fix OdroidC2 Gigabit Tx link issue
From: Florian Fainelli @ 2016-11-30 18:28 UTC (permalink / raw)
To: Jerome Brunet, netdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: Carlo Caione, Kevin Hilman, Giuseppe Cavallaro, Alexandre TORGUE,
Martin Blumenstingl, Andre Roth, Andrew Lunn, Neil Armstrong,
linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Julia Lawall, Yegor Yefremov,
Andreas Färber
In-Reply-To: <1480499246.17538.208.camel-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
On 11/30/2016 01:47 AM, Jerome Brunet wrote:
>> If we start supporting generic "enable", "disable" type of properties
>> with values that map directly to register definitions of the HW, we
>> leave too much room for these properties to be utilized to implement
>> a
>> specific policy, and this is not acceptable.
>
> Florian,
>
> I agree that DT should not be used to setup a policy, but to describe
> what the HW is.
>
> I tried to implement it the way you suggested, using phy fixup, too see
> what it looks like.
> There is 2 places in the code that seems (remotely) linked to the
> issue:
> - meson8b_dwmac driver : if the mac, regardless of the board/platform,
> could not tolerate to have EEE activated, it would make sense to have
> the fixup here. It can provide a C callback for such case.
> - realtek phy driver: philosophy is kind of the same
>
> To be clear, it is doable and it works that way, but I don't think
> embedding this directly in the code is the right way to do it. It seems
> we are hiding an information specific about the board inside a generic
> driver.
So there are a few things about that:
- if we were not on ARM64, there would be possibly a remote chance of
having some concept of a board file which would be where such a PHY
fixup, or fixup of any kind would reside
- having the PHY fixup in the PHY driver gated by both an exact match on
the PHY OUI *and* the specific affected board makes it reasonably easy
to locate it
>
> We have several amlogic's design with the same MAC, sometimes with the
> same PHY, which have no problem with EEE at all. The issue is really
> about the board design.
OK, not a problem then: of_machine_is_compatible() should help you here?
>
> What I propose is not an enable/disable configuration switch, but to
> clearly state that a particular mode of operation is broken. Like the
> "max-speed" property, it setup a restriction. IMO, this is a
> description of what the HW is and is capable of, and as such it should
> be part of the DT.
Sure, there is a fine line between describing what's broken, and being
able to use that to actually configure non-broken hardware the way you want.
>
> Yes the property directly map to a register, but it does let you
> directly manipulate it (you can't pass the value you want to write in
> the register). Having it this way just makes the code simple on both
> ends (user and driver).
That's exactly the part that is giving me the creeps, any property that
directly maps to a register value has a chance of a) leading to hard to
debug problem if mis-configured, and b) being used as a policy as
opposed to purely describing what is going on with the HW.
>
> Yes people could start abusing this to setup policy. In the end, it is
> our responsibility, as community, to make sure APIs are used in a
> proper way, and not let it be used that way.
>
> I'm open to suggestion on how improve the solution, maybe something
> which could bring more confidence that property won't be misused.
Once the binding lands in the kernel, there is absolutely zero guarantee
nor visibility in how people end-up using in e.g: DT aware bootloader,
and I am one of these people. Since there is a binding, there is
consumer code in the kernel that needs to behave properly with respect
to how the binding is defined. This is the same problem as with any kind
of ABI, and a diverse range of consumers.
--
Florian
--
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/6] net: ethernet: ti: netcp: add support of cpts
From: Richard Cochran @ 2016-11-30 18:22 UTC (permalink / raw)
To: Grygorii Strashko
Cc: David S. Miller, netdev, Mugunthan V N, Sekhar Nori, linux-kernel,
linux-omap, Rob Herring, devicetree, Murali Karicheri,
Wingman Kwok
In-Reply-To: <4d69aff4-70a0-e6b8-38b0-8e95cfea7601@ti.com>
On Wed, Nov 30, 2016 at 11:31:56AM -0600, Grygorii Strashko wrote:
> ok. Seems my assumption that ndo_open/ndo_close serialized by
> rtnl_lock is incorrect. Right?
No, you were right in the first place. The open/close are indeed
serialized by the rtnl lock.
Sorry for the noise,
Richard
^ permalink raw reply
* Re: [PATCH v2] ALSA SoC MAX98927 driver - Revision
From: Mark Brown @ 2016-11-30 18:15 UTC (permalink / raw)
To: Ryan Lee
Cc: yesanishhere-Re5JQEeQqe8AvxtiuMwx3w,
lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, perex-/Fr2/VpizcU, tiwai-IBi9RG/b67k,
arnd-r2nGTMty4D4, michael-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/,
oder_chiou-Rasf1IRRPZFBDgjK7y7TUQ,
jacob-EZCvousvhKUZux3j3Bed6dkegs52MxvZ,
Damien.Horsley-1AXoQHu6uovQT0dZR+AlfA,
bardliao-Rasf1IRRPZFBDgjK7y7TUQ,
kuninori.morimoto.gx-zM6kxYcvzFBBDgjK7y7TUQ,
petr-Qh/3xLP0EvwAvxtiuMwx3w, lars-Qo5EllUWu/uELgA04lAiVw,
nh6z-fFIq/eER6g8, alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1480050167-83444-1-git-send-email-RyanS.Lee-zxKO94PEStzToO697jQleEEOCMrvLtNR@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 660 bytes --]
On Fri, Nov 25, 2016 at 02:02:47PM +0900, Ryan Lee wrote:
> Signed-off-by: Ryan Lee <RyanS.Lee-zxKO94PEStzToO697jQleEEOCMrvLtNR@public.gmane.org>
> ---
> .../devicetree/bindings/sound/max98927.txt | 33 +-
> sound/soc/codecs/max98927.c | 839 +++++------
> sound/soc/codecs/max98927.h | 1463 ++++----------------
This is modifying existing code, you need to at least attempt to supply
a description of the changes you are trying to make and most likely send
a series of individual, split out changes. Please, review the patch
submission process in SubmittingPatches before sending anything further.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
^ permalink raw reply
* Applied "ASoC: sun4i-codec: Add support for A23 codec" to the asoc tree
From: Mark Brown @ 2016-11-30 18:07 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: Rob Herring, Maxime Ripard, Mark Brown, Liam Girdwood
In-Reply-To: <20161112064648.26779-5-wens-jdAy2FN1RRM@public.gmane.org>
The patch
ASoC: sun4i-codec: Add support for A23 codec
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From dac5f86bc9e60eae87a28512f025362d1e2574e3 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
Date: Fri, 25 Nov 2016 20:34:36 +0800
Subject: [PATCH] ASoC: sun4i-codec: Add support for A23 codec
The codec in the A23 is similar to the one found on the A31. One key
difference is the analog path controls are routed through the PRCM
block. This is supported by the sun8i-codec-analog driver, and tied
into this codec driver with the audio card's aux_dev.
In addition, the A23 does not have LINEOUT, and it does not support
headset jack detection or buttons.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
.../devicetree/bindings/sound/sun4i-codec.txt | 11 ++-
sound/soc/sunxi/sun4i-codec.c | 108 +++++++++++++++++++++
2 files changed, 117 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/sun4i-codec.txt b/Documentation/devicetree/bindings/sound/sun4i-codec.txt
index d91a95377f49..f7a548b604fc 100644
--- a/Documentation/devicetree/bindings/sound/sun4i-codec.txt
+++ b/Documentation/devicetree/bindings/sound/sun4i-codec.txt
@@ -5,6 +5,7 @@ Required properties:
- "allwinner,sun4i-a10-codec"
- "allwinner,sun6i-a31-codec"
- "allwinner,sun7i-a20-codec"
+ - "allwinner,sun8i-a23-codec"
- reg: must contain the registers location and length
- interrupts: must contain the codec interrupt
- dmas: DMA channels for tx and rx dma. See the DMA client binding,
@@ -21,6 +22,7 @@ Optional properties:
Required properties for the following compatibles:
- "allwinner,sun6i-a31-codec"
+ - "allwinner,sun8i-a23-codec"
- resets: phandle to the reset control for this device
- allwinner,audio-routing: A list of the connections between audio components.
Each entry is a pair of strings, the first being the
@@ -31,10 +33,10 @@ Required properties for the following compatibles:
"HP"
"HPCOM"
"LINEIN"
- "LINEOUT"
+ "LINEOUT" (not on sun8i-a23)
"MIC1"
"MIC2"
- "MIC3"
+ "MIC3" (sun6i-a31 only)
Microphone biases from the SoC:
"HBIAS"
@@ -48,6 +50,11 @@ Required properties for the following compatibles:
"Mic"
"Speaker"
+Required properties for the following compatibles:
+ - "allwinner,sun8i-a23-codec"
+- allwinner,codec-analog-controls: A phandle to the codec analog controls
+ block in the PRCM.
+
Example:
codec: codec@01c22c00 {
#sound-dai-cells = <0>;
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index 092fdcf6de95..ada5fa055950 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -213,6 +213,10 @@
/* TODO sun6i DAP (Digital Audio Processing) bits */
+/* FIFO counters moved on A23 */
+#define SUN8I_A23_CODEC_DAC_TXCNT (0x1c)
+#define SUN8I_A23_CODEC_ADC_RXCNT (0x20)
+
struct sun4i_codec {
struct device *dev;
struct regmap *regmap;
@@ -1067,6 +1071,32 @@ static struct snd_soc_codec_driver sun6i_codec_codec = {
},
};
+/* sun8i A23 codec */
+static const struct snd_kcontrol_new sun8i_a23_codec_codec_controls[] = {
+ SOC_SINGLE_TLV("DAC Playback Volume", SUN4I_CODEC_DAC_DPC,
+ SUN4I_CODEC_DAC_DPC_DVOL, 0x3f, 1,
+ sun6i_codec_dvol_scale),
+};
+
+static const struct snd_soc_dapm_widget sun8i_a23_codec_codec_widgets[] = {
+ /* Digital parts of the ADCs */
+ SND_SOC_DAPM_SUPPLY("ADC Enable", SUN6I_CODEC_ADC_FIFOC,
+ SUN6I_CODEC_ADC_FIFOC_EN_AD, 0, NULL, 0),
+ /* Digital parts of the DACs */
+ SND_SOC_DAPM_SUPPLY("DAC Enable", SUN4I_CODEC_DAC_DPC,
+ SUN4I_CODEC_DAC_DPC_EN_DA, 0, NULL, 0),
+
+};
+
+static struct snd_soc_codec_driver sun8i_a23_codec_codec = {
+ .component_driver = {
+ .controls = sun8i_a23_codec_codec_controls,
+ .num_controls = ARRAY_SIZE(sun8i_a23_codec_codec_controls),
+ .dapm_widgets = sun8i_a23_codec_codec_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sun8i_a23_codec_codec_widgets),
+ },
+};
+
static const struct snd_soc_component_driver sun4i_codec_component = {
.name = "sun4i-codec",
};
@@ -1206,6 +1236,63 @@ static struct snd_soc_card *sun6i_codec_create_card(struct device *dev)
return card;
};
+/* Connect digital side enables to analog side widgets */
+static const struct snd_soc_dapm_route sun8i_codec_card_routes[] = {
+ /* ADC Routes */
+ { "Left ADC", NULL, "ADC Enable" },
+ { "Right ADC", NULL, "ADC Enable" },
+ { "Codec Capture", NULL, "Left ADC" },
+ { "Codec Capture", NULL, "Right ADC" },
+
+ /* DAC Routes */
+ { "Left DAC", NULL, "DAC Enable" },
+ { "Right DAC", NULL, "DAC Enable" },
+ { "Left DAC", NULL, "Codec Playback" },
+ { "Right DAC", NULL, "Codec Playback" },
+};
+
+static struct snd_soc_aux_dev aux_dev = {
+ .name = "Codec Analog Controls",
+};
+
+static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev)
+{
+ struct snd_soc_card *card;
+ int ret;
+
+ card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
+ if (!card)
+ return ERR_PTR(-ENOMEM);
+
+ aux_dev.codec_of_node = of_parse_phandle(dev->of_node,
+ "allwinner,codec-analog-controls",
+ 0);
+ if (!aux_dev.codec_of_node) {
+ dev_err(dev, "Can't find analog controls for codec.\n");
+ return ERR_PTR(-EINVAL);
+ };
+
+ card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
+ if (!card->dai_link)
+ return ERR_PTR(-ENOMEM);
+
+ card->dev = dev;
+ card->name = "A23 Audio Codec";
+ card->dapm_widgets = sun6i_codec_card_dapm_widgets;
+ card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
+ card->dapm_routes = sun8i_codec_card_routes;
+ card->num_dapm_routes = ARRAY_SIZE(sun8i_codec_card_routes);
+ card->aux_dev = &aux_dev;
+ card->num_aux_devs = 1;
+ card->fully_routed = true;
+
+ ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
+ if (ret)
+ dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
+
+ return card;
+};
+
static const struct regmap_config sun4i_codec_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -1227,6 +1314,13 @@ static const struct regmap_config sun7i_codec_regmap_config = {
.max_register = SUN7I_CODEC_AC_MIC_PHONE_CAL,
};
+static const struct regmap_config sun8i_a23_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = SUN8I_A23_CODEC_ADC_RXCNT,
+};
+
struct sun4i_codec_quirks {
const struct regmap_config *regmap_config;
const struct snd_soc_codec_driver *codec;
@@ -1265,6 +1359,16 @@ static const struct sun4i_codec_quirks sun7i_codec_quirks = {
.reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA,
};
+static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = {
+ .regmap_config = &sun8i_a23_codec_regmap_config,
+ .codec = &sun8i_a23_codec_codec,
+ .create_card = sun8i_a23_codec_create_card,
+ .reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
+ .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
+ .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
+ .has_reset = true,
+};
+
static const struct of_device_id sun4i_codec_of_match[] = {
{
.compatible = "allwinner,sun4i-a10-codec",
@@ -1278,6 +1382,10 @@ static const struct of_device_id sun4i_codec_of_match[] = {
.compatible = "allwinner,sun7i-a20-codec",
.data = &sun7i_codec_quirks,
},
+ {
+ .compatible = "allwinner,sun8i-a23-codec",
+ .data = &sun8i_a23_codec_quirks,
+ },
{}
};
MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
--
2.10.2
--
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
* Applied "ASoC: sun4i-codec: Add support for H3 codec" to the asoc tree
From: Mark Brown @ 2016-11-30 18:07 UTC (permalink / raw)
To: Chen-Yu Tsai; +Cc: Rob Herring, Maxime Ripard, Mark Brown, Liam Girdwood
In-Reply-To: <20161112064648.26779-9-wens-jdAy2FN1RRM@public.gmane.org>
The patch
ASoC: sun4i-codec: Add support for H3 codec
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From 4a15b24a65f13778f7616ad0a65be78d8ec0b45a Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
Date: Fri, 25 Nov 2016 20:34:40 +0800
Subject: [PATCH] ASoC: sun4i-codec: Add support for H3 codec
The codec on the H3 is similar to the one found on the A31. One key
difference is the analog path controls are routed through the PRCM
block. This is supported by the sun8i-codec-analog driver, and tied
into this codec driver with the audio card's aux_dev.
In addition, the H3 has no HP (headphone) and HBIAS support, and no
MIC3 input. The FIFO related registers are slightly rearranged.
Signed-off-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
.../devicetree/bindings/sound/sun4i-codec.txt | 3 +
sound/soc/sunxi/sun4i-codec.c | 71 ++++++++++++++++++++++
2 files changed, 74 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/sun4i-codec.txt b/Documentation/devicetree/bindings/sound/sun4i-codec.txt
index f7a548b604fc..3033bd8aab0f 100644
--- a/Documentation/devicetree/bindings/sound/sun4i-codec.txt
+++ b/Documentation/devicetree/bindings/sound/sun4i-codec.txt
@@ -6,6 +6,7 @@ Required properties:
- "allwinner,sun6i-a31-codec"
- "allwinner,sun7i-a20-codec"
- "allwinner,sun8i-a23-codec"
+ - "allwinner,sun8i-h3-codec"
- reg: must contain the registers location and length
- interrupts: must contain the codec interrupt
- dmas: DMA channels for tx and rx dma. See the DMA client binding,
@@ -23,6 +24,7 @@ Optional properties:
Required properties for the following compatibles:
- "allwinner,sun6i-a31-codec"
- "allwinner,sun8i-a23-codec"
+ - "allwinner,sun8i-h3-codec"
- resets: phandle to the reset control for this device
- allwinner,audio-routing: A list of the connections between audio components.
Each entry is a pair of strings, the first being the
@@ -52,6 +54,7 @@ Required properties for the following compatibles:
Required properties for the following compatibles:
- "allwinner,sun8i-a23-codec"
+ - "allwinner,sun8i-h3-codec"
- allwinner,codec-analog-controls: A phandle to the codec analog controls
block in the PRCM.
diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index ada5fa055950..848af01692a0 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -217,6 +217,13 @@
#define SUN8I_A23_CODEC_DAC_TXCNT (0x1c)
#define SUN8I_A23_CODEC_ADC_RXCNT (0x20)
+/* TX FIFO moved on H3 */
+#define SUN8I_H3_CODEC_DAC_TXDATA (0x20)
+#define SUN8I_H3_CODEC_DAC_DBG (0x48)
+#define SUN8I_H3_CODEC_ADC_DBG (0x4c)
+
+/* TODO H3 DAP (Digital Audio Processing) bits */
+
struct sun4i_codec {
struct device *dev;
struct regmap *regmap;
@@ -1293,6 +1300,44 @@ static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev)
return card;
};
+static struct snd_soc_card *sun8i_h3_codec_create_card(struct device *dev)
+{
+ struct snd_soc_card *card;
+ int ret;
+
+ card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
+ if (!card)
+ return ERR_PTR(-ENOMEM);
+
+ aux_dev.codec_of_node = of_parse_phandle(dev->of_node,
+ "allwinner,codec-analog-controls",
+ 0);
+ if (!aux_dev.codec_of_node) {
+ dev_err(dev, "Can't find analog controls for codec.\n");
+ return ERR_PTR(-EINVAL);
+ };
+
+ card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
+ if (!card->dai_link)
+ return ERR_PTR(-ENOMEM);
+
+ card->dev = dev;
+ card->name = "H3 Audio Codec";
+ card->dapm_widgets = sun6i_codec_card_dapm_widgets;
+ card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
+ card->dapm_routes = sun8i_codec_card_routes;
+ card->num_dapm_routes = ARRAY_SIZE(sun8i_codec_card_routes);
+ card->aux_dev = &aux_dev;
+ card->num_aux_devs = 1;
+ card->fully_routed = true;
+
+ ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
+ if (ret)
+ dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
+
+ return card;
+};
+
static const struct regmap_config sun4i_codec_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -1321,6 +1366,13 @@ static const struct regmap_config sun8i_a23_codec_regmap_config = {
.max_register = SUN8I_A23_CODEC_ADC_RXCNT,
};
+static const struct regmap_config sun8i_h3_codec_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = SUN8I_H3_CODEC_ADC_DBG,
+};
+
struct sun4i_codec_quirks {
const struct regmap_config *regmap_config;
const struct snd_soc_codec_driver *codec;
@@ -1369,6 +1421,21 @@ static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = {
.has_reset = true,
};
+static const struct sun4i_codec_quirks sun8i_h3_codec_quirks = {
+ .regmap_config = &sun8i_h3_codec_regmap_config,
+ /*
+ * TODO Share the codec structure with A23 for now.
+ * This should be split out when adding digital audio
+ * processing support for the H3.
+ */
+ .codec = &sun8i_a23_codec_codec,
+ .create_card = sun8i_h3_codec_create_card,
+ .reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
+ .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
+ .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
+ .has_reset = true,
+};
+
static const struct of_device_id sun4i_codec_of_match[] = {
{
.compatible = "allwinner,sun4i-a10-codec",
@@ -1386,6 +1453,10 @@ static const struct of_device_id sun4i_codec_of_match[] = {
.compatible = "allwinner,sun8i-a23-codec",
.data = &sun8i_a23_codec_quirks,
},
+ {
+ .compatible = "allwinner,sun8i-h3-codec",
+ .data = &sun8i_h3_codec_quirks,
+ },
{}
};
MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
--
2.10.2
--
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 v7 0/8] drm: sun8i: Add DE2 HDMI video support
From: Jernej Skrabec @ 2016-11-30 18:04 UTC (permalink / raw)
To: linux-sunxi
Cc: jernej.skrabec-Re5JQEeQqe8AvxtiuMwx3w, moinejf-GANU6spQydw,
airlied-cv59FeDIM0c, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
devicetree-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
kieran.bingham-ryLnwIuWjnjg/C1BVhZhaw,
laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw
In-Reply-To: <3152670.pRMCOA29o4@avalon>
[-- Attachment #1.1: Type: text/plain, Size: 4453 bytes --]
Hi Laurent,
Dne sreda, 30. november 2016 09.08.22 UTC+1 je oseba Laurent Pinchart
napisala:
>
> Hi Jernej,
>
> On Tuesday 29 Nov 2016 15:24:25 Jernej Skrabec wrote:
> > Dne torek, 29. november 2016 23.56.31 UTC+1 je oseba Laurent Pinchart
> > napisala:
> > > On Tuesday 29 Nov 2016 14:47:20 Jernej Skrabec wrote:
> > >> Dne torek, 29. november 2016 22.37.03 UTC+1 je oseba Maxime Ripard
> > > napisala:
> > >>> On Tue, Nov 29, 2016 at 11:18:35AM +0100, Jean-Francois Moine wrote:
> > >>>> This patchset series adds HDMI video support to the Allwinner
> > >>>> sun8i SoCs which include the display engine 2 (DE2).
> > >>>> The driver contains the code for the A83T and H3 SoCs, and
> > >>>> some H3 boards, but it could be used/extended for other SoCs
> > >>>> (A64, H2, H5) and boards (Banana PIs, Orange PIs).
> > >>>
> > >>> Honestly, I'm getting a bit worried by the fact that you ignore
> > >>> reviews.
> > >>>
> > >>> On the important reviews that you got that are to be seen as major
> > >>> issues that block the inclusion, we have:
> > >>> - The fact that the HDMI driver is actually just a designware IP,
> > >>> and while you should use the driver that already exists, you
> just
> > >>> duplicated all that code.
> > >>
> > >> That might be hard thing to do. A83T fits perfectly, but H3 and newer
> > >> SoCs do not. They are using completely different HDMI phy. Decoupling
> > >> controller and phy code means rewritting a good portion of the code,
> > >> unless some tricks are applied, like calling phy function pointers,
> if
> > >> they are defined.
> > >
> > > Same HDMI TX but different HDMI TX PHY ? Kieran is working on
> decoupling
> > > the PHY configuration code for a Renesas SoC, that might be of
> interest to
> > > you.
> >
> > Exactly. I'm developing only U-Boot driver, but Jean-Francois will
> probably
> > have more interest in this.
>
> We'll post patches as soon as they're ready.
>
Great. Is datasheet public? I'm curious if HDMI PHY is by any chance
similar.
>
> By the way, do you know if the H3 and newer SoCs use a different PHY from
> Synopsys, or a custom PHY developed by Allwinner ?
>
>
Unfortunatelly, noone managed to identify PHY and Alliwinner never released
a
bit of information about HDMI. Does config2_id code 0xFE (PHY type) tell you
anything?
> > >> Register addresses also differ, but that can be easily solved by
> using
> > >> undocumented magic value to restore them.
> > >
> > > I love that :-)
> >
> > Is it allowed to use magic number which was found in binary blob? I'm
> new in
> > all this.
>
> I don't really see a problem with that, we have many drivers in the kernel
> that have been developed through reverse-engineering. You should not
> include
> large pieces of code that have been obtained through decompilation of a
> proprietary binary blob as those could be protected by copyright, but
> writing
> to undocumented registers based on information found through usage of a
> binary
> driver isn't a problem. (Please remember that I'm not a lawyer though)
>
> > >>> - The fact that you ignored Rob (v6) and I (v5) comment on using
> OF
> > >>> graph to model the connection between the display engine and the
> > >>> TCON. Something that Laurent also pointed out in this version.
> > >>>
> > >>> - The fact that you ignored that you needed an HDMI connector node
> > >>> as a child of the HDMI controller. This has been reported by Rob
> > >>> (v6) and yet again in this version by Laurent.
> > >>>
> > >>> - And finally the fact that we can't have several display engine
> in
> > >>> parallel, if needs be. This has happened in the past already on
> > >>> Allwinner SoCs, so it's definitely something we should consider
> in
> > >>> the DT bindings, since we can't break them.
> > >>>
> > >>> Until those are fixed, I cannot see how this driver can be merged,
> > >>> unfortunately.
>
Best regards,
Jernej Škrabec
--
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
[-- Attachment #1.2: Type: text/html, Size: 5701 bytes --]
^ permalink raw reply
* Re: [PATCH v3 0/3] Altera Cyclone Passive Serial SPI FPGA Manager
From: atull @ 2016-11-30 18:01 UTC (permalink / raw)
To: Joshua Clayton
Cc: Moritz Fischer, Rob Herring, Mark Rutland, Russell King,
devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <cover.1480467185.git.stillcompiling@gmail.com>
On Wed, 30 Nov 2016, Joshua Clayton wrote:
Hi Joshua,
The DT bindings will need Rob Herring's ack. The bitrev.h
changes will need Russell King's ack.
I've made some comments on patch 3/3 but it looks good to me
besides that.
Once we have those other acks, please submit your v4 including fixes
for my comments and whatever else comes up. I'm hoping it will be
minor and with that done, v4 can go in.
When you send in v4, please also cc our new mailing list that Moritz
made: linux-fpga@vger.kernel.org
Alan
> This series adds an FPGA manager for Altera cyclone FPGAs
> that can program them using an spi port and a couple of gpios, using
> Alteras passive serial protocol.
>
> Changes from v2:
>
> - Merged patch 3 and 4 as suggested in review by Moritz Fischer
> - Changed FPGA_MIN_DELAY from 250 to 50 ms is the time advertized by
> Altera. This now works, as we don't assume it is done
>
> Changes from v1:
> - Changed the name from cyclone-spi-fpga-mgr to cyclone-ps-spi-fpga-mgr
> This name change was requested by Alan Tull, to be specific about which
> programming method is being employed on the fpga.
> - Changed the name of the reset-gpio to config-gpio to closer match the
> way the pins are described in the Altera manual
> - Moved MODULE_LICENCE, _AUTHOR, and _DESCRIPTION to the bottom
>
> - Added a bitrev8x4() function to the bitrev headers and implemented ARM
> const, runtime, and ARM specific faster versions (This may end up
> needing to be a standalone patch)
>
> - Moved the bitswapping into cyclonespi_write(), as requested.
> This falls short of my desired generic lsb first spi support, but is a step
> in that direction.
>
> - Fixed whitespace problems introduced during refactoring
>
> - Replaced magic number for initial delay with a descriptive macro
> - Poll the fpga to see when it is ready rather than a fixed 1 ms sleep
>
> Joshua Clayton (3):
> lib: add bitrev8x4()
> doc: dt: add cyclone-spi binding document
> fpga manager: Add cyclone-ps-spi driver for Altera FPGAs
>
> .../bindings/fpga/cyclone-ps-spi-fpga-mgr.txt | 23 +++
> arch/arm/include/asm/bitrev.h | 5 +
> drivers/fpga/Kconfig | 7 +
> drivers/fpga/Makefile | 1 +
> drivers/fpga/cyclone-ps-spi.c | 176 +++++++++++++++++++++
> include/linux/bitrev.h | 26 +++
> 6 files changed, 238 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/fpga/cyclone-ps-spi-fpga-mgr.txt
> create mode 100644 drivers/fpga/cyclone-ps-spi.c
>
> --
> 2.9.3
>
>
^ permalink raw reply
* [PATCH] ARM: omap3: beagleboard-xm: dt: Add ethernet to the device tree
From: Laurent Pinchart @ 2016-11-30 17:58 UTC (permalink / raw)
To: linux-omap-u79uwXL29TY76Z2rM5mHXA
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Tony Lindgren,
Benoît Cousson
The Beagleboard-xM has a LAN9514 USB hub and ethernet controller,
connected to port 2 of the OMAP EHCI controller. The board however has
no EEPROM to store the ethernet MAC address, which is programmed by the
boot loader.
To allow Linux to use the same MAC address as the boot loader (or for
that matter any fixed MAC address), we need a node in the device tree
for the ethernet controller that the boot loader can update at runtime
with a local-mac-address property. Add it, along with an alias for the
ethernet controller to let the boot loader locate it easily.
Signed-off-by: Laurent Pinchart <laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>
---
arch/arm/boot/dts/omap3-beagle-xm.dts | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts b/arch/arm/boot/dts/omap3-beagle-xm.dts
index 85e297ed0ea1..75ac56cdf954 100644
--- a/arch/arm/boot/dts/omap3-beagle-xm.dts
+++ b/arch/arm/boot/dts/omap3-beagle-xm.dts
@@ -27,6 +27,7 @@
aliases {
display0 = &dvi0;
display1 = &tv0;
+ ethernet = ðernet;
};
leds {
@@ -348,6 +349,21 @@
&usbhsehci {
phys = <0 &hsusb2_phy>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb2@2 {
+ compatible = "usb424,9514";
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet: usbether@1 {
+ compatible = "usb424,ec00";
+ reg = <1>;
+ };
+ };
};
&vaux2 {
--
Regards,
Laurent Pinchart
--
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 v3 3/3] fpga manager: Add cyclone-ps-spi driver for Altera FPGAs
From: atull @ 2016-11-30 17:45 UTC (permalink / raw)
To: Joshua Clayton
Cc: Mark Rutland, Moritz Fischer, devicetree, Russell King,
linux-kernel, Rob Herring, linux-arm-kernel
In-Reply-To: <e193572d7746e6f6b8666da7ac0f54031fed5214.1480467185.git.stillcompiling@gmail.com>
On Wed, 30 Nov 2016, Joshua Clayton wrote:
Hi Clayton,
I just have a few minor one line changes below. Only one
is operational, I should have caught that earlier.
> cyclone-ps-spi loads FPGA firmware over spi, using the "passive serial"
> interface on Altera Cyclone FPGAS.
>
> This is one of the simpler ways to set up an FPGA at runtime.
> The signal interface is close to unidirectional spi with lsb first.
>
> Signed-off-by: Joshua Clayton <stillcompiling@gmail.com>
> ---
> drivers/fpga/Kconfig | 7 ++
> drivers/fpga/Makefile | 1 +
> drivers/fpga/cyclone-ps-spi.c | 176 ++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 184 insertions(+)
> create mode 100644 drivers/fpga/cyclone-ps-spi.c
>
> diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
> index cd84934..2462707 100644
> --- a/drivers/fpga/Kconfig
> +++ b/drivers/fpga/Kconfig
> @@ -13,6 +13,13 @@ config FPGA
>
> if FPGA
>
> +config FPGA_MGR_CYCLONE_PS_SPI
> + tristate "Altera Cyclone FPGA Passive Serial over SPI"
> + depends on SPI
> + help
> + FPGA manager driver support for Altera Cyclone using the
> + passive serial interface over SPI
> +
> config FPGA_MGR_SOCFPGA
> tristate "Altera SOCFPGA FPGA Manager"
> depends on ARCH_SOCFPGA
> diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
> index 8d83fc6..8f93930 100644
> --- a/drivers/fpga/Makefile
> +++ b/drivers/fpga/Makefile
> @@ -6,5 +6,6 @@
> obj-$(CONFIG_FPGA) += fpga-mgr.o
>
> # FPGA Manager Drivers
> +obj-$(CONFIG_FPGA_MGR_CYCLONE_PS_SPI) += cyclone-ps-spi.o
> obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o
> obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o
> diff --git a/drivers/fpga/cyclone-ps-spi.c b/drivers/fpga/cyclone-ps-spi.c
> new file mode 100644
> index 0000000..57a520d
> --- /dev/null
> +++ b/drivers/fpga/cyclone-ps-spi.c
> @@ -0,0 +1,176 @@
> +/**
> + * Copyright (c) 2015 United Western Technologies, Corporation
> + *
> + * Joshua Clayton <stillcompiling@gmail.com>
> + *
> + * Manage Altera fpga firmware that is loaded over spi.
> + * Firmware must be in binary "rbf" format.
> + * Works on Cyclone V. Should work on cyclone series.
> + * May work on other Altera fpgas.
> + *
> + */
> +
> +#include <linux/bitrev.h>
> +#include <linux/delay.h>
> +#include <linux/fpga/fpga-mgr.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/module.h>
> +#include <linux/of_gpio.h>
> +#include <linux/spi/spi.h>
> +#include <linux/sizes.h>
> +
> +#define FPGA_RESET_TIME 50 /* time in usecs to trigger FPGA config */
> +#define FPGA_MIN_DELAY 50 /* min usecs to wait for config status */
> +#define FPGA_MAX_DELAY 1000 /* max usecs to wait for config status */
> +
> +struct cyclonespi_conf {
> + struct gpio_desc *config;
> + struct gpio_desc *status;
> + struct spi_device *spi;
> +};
> +
> +static const struct of_device_id of_ef_match[] = {
> + { .compatible = "altr,cyclone-ps-spi-fpga-mgr", },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, of_ef_match);
> +
> +static enum fpga_mgr_states cyclonespi_state(struct fpga_manager *mgr)
> +{
> + return mgr->state;
> +}
This function gets called once to initialize mgr->state in
fpga_mgr_register(). So it should at least return the state the FPGA
is at then. If it is unknown, it can just return
FPGA_MGR_STATE_UNKNOWN.
> +
> +static int cyclonespi_write_init(struct fpga_manager *mgr, u32 flags,
> + const char *buf, size_t count)
Minor, but please fix the indentation of 'const' to match that of
'struct' above. checkpatch.pl is probably issuing warnings
about that.
> +{
> + struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
> + int i;
> +
> + if (flags & FPGA_MGR_PARTIAL_RECONFIG) {
> + dev_err(&mgr->dev, "Partial reconfiguration not supported.\n");
> + return -EINVAL;
> + }
> +
> + gpiod_set_value(conf->config, 0);
> + usleep_range(FPGA_RESET_TIME, FPGA_RESET_TIME + 20);
> + if (gpiod_get_value(conf->status) == 1) {
> + dev_err(&mgr->dev, "Status pin should be low.\n");
> + return -EIO;
> + }
> +
> + gpiod_set_value(conf->config, 1);
> + for (i = 0; i < (FPGA_MAX_DELAY / FPGA_MIN_DELAY); i++) {
> + usleep_range(FPGA_MIN_DELAY, FPGA_MIN_DELAY + 20);
> + if (gpiod_get_value(conf->status))
> + return 0;
> + }
> +
> + dev_err(&mgr->dev, "Status pin not ready.\n");
> + return -EIO;
> +}
> +
> +static void rev_buf(void *buf, size_t len)
> +{
> + u32 *fw32 = (u32 *)buf;
> + const u32 *fw_end = (u32 *)(buf + len);
> +
> + /* set buffer to lsb first */
> + while (fw32 < fw_end) {
> + *fw32 = bitrev8x4(*fw32);
> + fw32++;
> + }
> +}
> +
> +static int cyclonespi_write(struct fpga_manager *mgr, const char *buf,
> + size_t count)
Please fix alignment here also.
> +{
> + struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
> + const char *fw_data = buf;
> + const char *fw_data_end = fw_data + count;
> +
> + while (fw_data < fw_data_end) {
> + int ret;
> + size_t stride = min(fw_data_end - fw_data, SZ_4K);
> +
> + rev_buf((void *)fw_data, stride);
> + ret = spi_write(conf->spi, fw_data, stride);
> + if (ret) {
> + dev_err(&mgr->dev, "spi error in firmware write: %d\n",
> + ret);
> + return ret;
> + }
> + fw_data += stride;
> + }
> +
> + return 0;
> +}
> +
> +static int cyclonespi_write_complete(struct fpga_manager *mgr, u32 flags)
> +{
> + struct cyclonespi_conf *conf = (struct cyclonespi_conf *)mgr->priv;
> +
> + if (gpiod_get_value(conf->status) == 0) {
> + dev_err(&mgr->dev, "Error during configuration.\n");
> + return -EIO;
> + }
> +
> + return 0;
> +}
> +
> +static const struct fpga_manager_ops cyclonespi_ops = {
> + .state = cyclonespi_state,
> + .write_init = cyclonespi_write_init,
> + .write = cyclonespi_write,
> + .write_complete = cyclonespi_write_complete,
> +};
> +
> +static int cyclonespi_probe(struct spi_device *spi)
> +{
> + struct cyclonespi_conf *conf = devm_kzalloc(&spi->dev, sizeof(*conf),
> + GFP_KERNEL);
> +
> + if (!conf)
> + return -ENOMEM;
> +
> + conf->spi = spi;
> + conf->config = devm_gpiod_get(&spi->dev, "config", GPIOD_OUT_LOW);
> + if (IS_ERR(conf->config)) {
> + dev_err(&spi->dev, "Failed to get config gpio: %ld\n",
> + PTR_ERR(conf->config));
> + return PTR_ERR(conf->config);
> + }
> +
> + conf->status = devm_gpiod_get(&spi->dev, "status", GPIOD_IN);
> + if (IS_ERR(conf->status)) {
> + dev_err(&spi->dev, "Failed to get status gpio: %ld\n",
> + PTR_ERR(conf->status));
> + return PTR_ERR(conf->status);
> + }
> +
> + return fpga_mgr_register(&spi->dev,
> + "Altera Cyclone PS SPI FPGA Manager",
> + &cyclonespi_ops, conf);
> +}
> +
> +static int cyclonespi_remove(struct spi_device *spi)
> +{
> + fpga_mgr_unregister(&spi->dev);
> +
> + return 0;
> +}
> +
> +static struct spi_driver cyclonespi_driver = {
> + .driver = {
> + .name = "cyclone-ps-spi",
> + .owner = THIS_MODULE,
> + .of_match_table = of_match_ptr(of_ef_match),
> + },
> + .probe = cyclonespi_probe,
> + .remove = cyclonespi_remove,
> +};
> +
> +module_spi_driver(cyclonespi_driver)
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Joshua Clayton <stillcompiling@gmail.com>");
> +MODULE_DESCRIPTION("Module to load Altera FPGA firmware over spi");
> --
> 2.9.3
>
>
Thanks,
Alan
^ permalink raw reply
* Re: [PATCH 2/6] net: ethernet: ti: cpts: add support for ext rftclk selection
From: Grygorii Strashko @ 2016-11-30 17:35 UTC (permalink / raw)
To: Richard Cochran
Cc: David S. Miller, netdev-u79uwXL29TY76Z2rM5mHXA, Mugunthan V N,
Sekhar Nori, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA, Murali Karicheri, Wingman Kwok
In-Reply-To: <20161130095632.GC28680-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
On 11/30/2016 03:56 AM, Richard Cochran wrote:
> On Mon, Nov 28, 2016 at 05:04:24PM -0600, Grygorii Strashko wrote:
>> Some CPTS instances, which can be found on KeyStone 2 1/10G Ethernet
>> Switch Subsystems, can control an external multiplexer that selects
>> one of up to 32 clocks for time sync reference (RFTCLK). This feature
>> can be configured through CPTS_RFTCLK_SEL register (offset: x08).
>>
>> Hence, introduce optional DT cpts_rftclk_sel poperty wich, if present,
>> will specify CPTS reference clock. The cpts_rftclk_sel should be
>> omitted in DT if HW doesn't support this feature. The external fixed
>> rate clocks can be defined in board files as "fixed-clock".
>
> Can't you implement this using the clock tree, rather than an ad-hoc
> DT property?
>
I've thought about this, but decided to move forward with this impl
which is pretty simple. I will try.
--
regards,
-grygorii
--
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: Re: [PATCH v7 4/8] drm/sunxi: Add DT bindings documentation of Allwinner HDMI
From: Icenowy Zheng @ 2016-11-30 17:33 UTC (permalink / raw)
To: moinejf-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org, Laurent Pinchart
Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
Dave Airlie, Maxime Ripard, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <20161130114415.2280151e2965280733a629e5-GANU6spQydw@public.gmane.org>
30.11.2016, 18:44, "Jean-Francois Moine" <moinejf-GANU6spQydw@public.gmane.org>:
> On Wed, 30 Nov 2016 11:52:25 +0200
> Laurent Pinchart <laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org> wrote:
>
>> Hi Jean-François,
>>
>> On Wednesday 30 Nov 2016 10:27:57 Jean-Francois Moine wrote:
>> > On Wed, 30 Nov 2016 10:20:21 +0200 Laurent Pinchart wrote:
>> > >> Well, I don't see what this connector can be.
>> > >> May you give me a DT example?
>> > >
>> > > Sure.
>> > >
>> > > arch/arm/boot/dts/r8a7791-koelsch.dts
>> > >
>> > > /* HDMI encoder */
>
> [snip]
>> > > /* HDMI connector */
>> > >
>> > > hdmi-out {
>> > > compatible = "hdmi-connector";
>> > > type = "a";
>> > >
>> > > port {
>> > > hdmi_con: endpoint {
>> > > remote-endpoint = <&adv7511_out>;
>> > > };
>> > > };
>> > > };
>
> [snip]
>> > - what does the software do with the connector type?
>>
>> That's up to the software to decide, the DT bindings should describe the
>> hardware in the most accurate and usable way for the OS as possible. One of my
>> longer term goals is to add connector drivers to handle DDC and HPD when
>> they're not handled by the encoder (they are in the above example).
>>
>> If the DDC was connected to a general-purpose I2C bus of the SoC, and the HPD
>> to a GPIO, we would have
>>
>> hdmi-out {
>> compatible = "hdmi-connector";
>> type = "a";
>> /* I2C bus and GPIO references are made up for the example */
>> ddc-i2c-bus = <&i2c4>;
>> hpd-gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>
>>
>> port {
>> hdmi_con: endpoint {
>> remote-endpoint = <&adv7511_out>;
>> };
>> };
>> };
>>
>> and both HPD and EDID reading should be handled by the connector driver.
>
> [snip]
>
> Hi Laurent,
>
> OK. I understand. This connector complexity should be added in all DTs,
> and the same code would be used.
>
> Actually, for component binding, I use drm_of_component_probe():
>
> - from the DRM master, loop on the "ports" phandle array and bind the
> CRTCs,
>
> - for each CRTC, loop on the first remote port level and bind the
> encoders/connectors
>
> Now, this should be:
>
> - from the DRM master, loop on the first remote ports level and bind
> the CRTCs,
>
> - for each CRTC, loop on the second remote port level and bind the
> encoders (and bridges?),
>
> - for each encoder, loop on the third remote port level and bind the
> connectors.
>
> Then, it would be nice to have a generic function for doing this job.
>
> Otherwise, from your description:
>
>> hdmi-out {
>> compatible = "hdmi-connector";
>> type = "a";
>> /* I2C bus and GPIO references are made up for the example */
>> ddc-i2c-bus = <&i2c4>;
>> hpd-gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>
>
> the "hdmi-connector" is a big piece of software. It must handle a lot
> of more and more exotic connectors.
> So, I hope that you have written a "simple-hdmi-connector" which does
> nothing but setting the connector type.
> Where is it?
I suddenly thought about something...
If a DVI connector instead of a HDMI connector is soldered, how should such a
device tree be written?
How about solder a HDMI-to-VGA bridge on the board? (Maybe there should be
"dumb-hdmi-dvi-bridge" and "dumb-hdmi-vga-bridge" drivers?)
>
> --
> Ken ar c'hentañ | ** Breizh ha Linux atav! **
> Jef | http://moinejf.free.fr/
>
> --
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
> For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ 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