* [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi
@ 2024-08-29 12:31 Angelo Dureghello
2024-08-29 12:31 ` [PATCH RFC 1/8] dt-bindings: iio: dac: ad3552r: add io-backend property Angelo Dureghello
` (8 more replies)
0 siblings, 9 replies; 54+ messages in thread
From: Angelo Dureghello @ 2024-08-29 12:31 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan
Cc: linux-iio, devicetree, linux-kernel, dlechner, Angelo Dureghello
Hi, asking for comments for this patchset, that is mostly
ready, at least feature-complete and functionally tested.
I am introducing ad3552r-axi variant, controlled from a fpga-based
AXI IP, as a platform driver, using the DAC backend. The patchset is
actually based on linux-iio, since some needed DAC backend features
was already there on that repo only, still to be merged in mainline.
Comments i would like to ask are:
- i added some devicetree bindings inside current ad3552r yaml,
device is the same, so i wouldn't create a different yaml file.
- if it's ok adding the bus-type property in the DAC backend:
actually, this platform driver uses a 4 lanes parallel bus, plus
a clock line, similar to a qspi. This to read an write registers
and as well to send samples at double data rate. Other DAC may
need "parallel" or "lvds" in the future.
- adding the bus-type property vs. a boolean property vs. adding
a new compatible string.
- how external synchronization should be handled. Actually, i added
2 backend calls to enable or disable this external trigger.
- is a read-only sampling-frequency useful ?
Thanks a lot for your feedbacks.
To: Lars-Peter Clausen <lars@metafoo.de>
To: Michael Hennerich <Michael.Hennerich@analog.com>
To: Nuno Sá <nuno.sa@analog.com>
To: Jonathan Cameron <jic23@kernel.org>
To: Rob Herring <robh@kernel.org>
To: Krzysztof Kozlowski <krzk+dt@kernel.org>
To: Conor Dooley <conor+dt@kernel.org>
To: Olivier Moysan <olivier.moysan@foss.st.com>
Cc: linux-iio@vger.kernel.org
Cc: devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: dlechner@baylibre.com
Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
---
Angelo Dureghello (8):
dt-bindings: iio: dac: ad3552r: add io-backend property
iio: backend: extend features
iio: backend adi-axi-dac: backend features
dt-bindings: iio: dac: add adi axi-dac bus property
iio: dac: ad3552r: changes to use FIELD_PREP
iio: dac: ad3552r: extract common code (no changes in behavior intended)
iio: dac: ad3552r: add axi platform driver
iio: ABI: add DAC sysfs synchronous_mode parameter
Documentation/ABI/testing/sysfs-bus-iio-dac | 7 +
.../devicetree/bindings/iio/dac/adi,ad3552r.yaml | 39 +-
.../devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9 +
drivers/iio/dac/Kconfig | 11 +
drivers/iio/dac/Makefile | 3 +-
drivers/iio/dac/ad3552r-axi.c | 572 +++++++++++++++++++++
drivers/iio/dac/ad3552r-common.c | 163 ++++++
drivers/iio/dac/ad3552r.c | 394 +++-----------
drivers/iio/dac/ad3552r.h | 199 +++++++
drivers/iio/dac/adi-axi-dac.c | 250 ++++++++-
drivers/iio/industrialio-backend.c | 151 ++++++
include/linux/iio/backend.h | 24 +
12 files changed, 1494 insertions(+), 328 deletions(-)
---
base-commit: 7ccb2c2db44572deadb795c4637273cdabbe8b66
change-id: 20240829-wip-bl-ad3552r-axi-v0-b1e379c986d3
Best regards,
--
o/ QW5nZWxvIER1cmVnaGVsbG8=
www.kernel-space.org
e: angelo at kernel-space.org
c: +39 388 8550663
^ permalink raw reply [flat|nested] 54+ messages in thread
* [PATCH RFC 1/8] dt-bindings: iio: dac: ad3552r: add io-backend property
2024-08-29 12:31 [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Angelo Dureghello
@ 2024-08-29 12:31 ` Angelo Dureghello
2024-08-29 12:32 ` [PATCH RFC 2/8] iio: backend: extend features Angelo Dureghello
` (7 subsequent siblings)
8 siblings, 0 replies; 54+ messages in thread
From: Angelo Dureghello @ 2024-08-29 12:31 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan
Cc: linux-iio, devicetree, linux-kernel, dlechner, Angelo Dureghello
From: Angelo Dureghello <adureghello@baylibre.com>
There is a version AXI DAC IP block (for FPGAs) that provides
a physical bus for AD3552R and similar chips. This can be used
instead of a typical SPI controller to be able to use the chip
in ways that typical SPI controllers are not capable of.
The binding is modified so that either the device is a SPI
peripheral or it uses an io-backend.
Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
---
.../devicetree/bindings/iio/dac/adi,ad3552r.yaml | 39 ++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
index fc8b97f82077..1874486229ad 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
@@ -60,12 +60,34 @@ properties:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 3]
+ io-backends:
+ description: The iio backend reference.
+ An example backend can be found at
+ https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
+ maxItems: 1
+
'#address-cells':
const: 1
'#size-cells':
const: 0
+if:
+ required:
+ - reg
+
+then:
+ $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+ properties:
+ io-backends: false
+
+ required: [ spi-max-frequency ]
+
+else:
+ required:
+ - io-backends
+
patternProperties:
"^channel@([0-1])$":
type: object
@@ -207,8 +229,6 @@ allOf:
required:
- compatible
- - reg
- - spi-max-frequency
additionalProperties: false
@@ -238,4 +258,19 @@ examples:
};
};
};
+
+ - |
+ fpga_axi {
+ ad3552r {
+ compatible = "adi,ad3552r";
+ reset-gpios = <&gpio0 92 1>;
+ io-backends = <&backend>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ channel@0 {
+ reg = <0>;
+ adi,output-range-microvolt = <(-5000000) (5000000)>;
+ };
+ };
+ };
...
--
2.45.0.rc1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH RFC 2/8] iio: backend: extend features
2024-08-29 12:31 [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Angelo Dureghello
2024-08-29 12:31 ` [PATCH RFC 1/8] dt-bindings: iio: dac: ad3552r: add io-backend property Angelo Dureghello
@ 2024-08-29 12:32 ` Angelo Dureghello
2024-08-31 11:23 ` Jonathan Cameron
2024-08-29 12:32 ` [PATCH RFC 3/8] iio: backend adi-axi-dac: backend features Angelo Dureghello
` (6 subsequent siblings)
8 siblings, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-08-29 12:32 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan
Cc: linux-iio, devicetree, linux-kernel, dlechner, Angelo Dureghello
From: Angelo Dureghello <adureghello@baylibre.com>
Extend backend features with new calls needed later on this
patchset from axi version of ad3552r.
A bus type property has been added to the devicetree to
inform the backend about the type of bus (interface) in use
bu the IP.
The follwoing calls are added:
iio_backend_ext_sync_enable
enable synchronize channels on external trigger
iio_backend_ext_sync_disable
disable synchronize channels on external trigger
iio_backend_ddr_enable
enable ddr bus transfer
iio_backend_ddr_disable
disable ddr bus transfer
iio_backend_set_bus_mode
select the type of bus, so that specific read / write
operations are performed accordingly
iio_backend_buffer_enable
enable buffer
iio_backend_buffer_disable
disable buffer
iio_backend_data_transfer_addr
define the target register address where the DAC sample
will be written.
iio_backend_bus_reg_read
generic bus read, bus-type dependent
iio_backend_bus_read_write
generic bus write, bus-type dependent
Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
---
drivers/iio/industrialio-backend.c | 151 +++++++++++++++++++++++++++++++++++++
include/linux/iio/backend.h | 24 ++++++
2 files changed, 175 insertions(+)
diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
index a52a6b61c8b5..1f60c8626be7 100644
--- a/drivers/iio/industrialio-backend.c
+++ b/drivers/iio/industrialio-backend.c
@@ -718,6 +718,157 @@ static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back)
return 0;
}
+/**
+ * iio_backend_ext_sync_enable - Enable external synchronization
+ * @back: Backend device
+ *
+ * Enable synchronization by external signal.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_ext_sync_enable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, ext_sync_enable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_ext_sync_enable, IIO_BACKEND);
+
+/**
+ * iio_backend_ext_sync_disable - Disable external synchronization
+ * @back: Backend device
+ *
+ * Disable synchronization by external signal.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_ext_sync_disable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, ext_sync_disable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_ext_sync_disable, IIO_BACKEND);
+
+/**
+ * iio_backend_ddr_enable - Enable interface DDR (Double Data Rate) mode
+ * @back: Backend device
+ *
+ * Enabling DDR, data is generated by the IP at each front
+ * (raising and falling) of the bus clock signal.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_ddr_enable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, ddr_enable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_ddr_enable, IIO_BACKEND);
+
+/**
+ * iio_backend_ddr_disable - Disable interface DDR (Double Data Rate) mode
+ * @back: Backend device
+ *
+ * Disabling DDR data is generated byt the IP at rising or falling front
+ * of the interface clock signal (SDR, Single Data Rate).
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_ddr_disable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, ddr_disable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_ddr_disable, IIO_BACKEND);
+
+/**
+ * iio_backend_buffer_enable - Enable data buffering
+ * @back: Backend device
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_buffer_enable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, buffer_enable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_buffer_enable, IIO_BACKEND);
+
+/**
+ * iio_backend_set_buffer_disable - Disable data buffering
+ * @back: Backend device
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_buffer_disable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, buffer_disable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_buffer_disable, IIO_BACKEND);
+
+/**
+ * iio_backend_buffer_transfer_addr - Set data address.
+ * @back: Backend device
+ * @chan_address: Channel register address
+ *
+ * Some devices may need to inform the backend about an address/location
+ * where to read or write the data.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_data_transfer_addr(struct iio_backend *back, u32 address)
+{
+ return iio_backend_op_call(back, data_transfer_addr, address);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_transfer_addr, IIO_BACKEND);
+
+/**
+ * iio_backend_bus_reg_read - Read from the interface bus
+ * @back: Backend device
+ * @reg: Register valule
+ * @val: Pointer to register value
+ * @size: Size, in bytes
+ *
+ * A backend may operate on a specific interface with a related bus.
+ * Read from the interface bus.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_bus_reg_read(struct iio_backend *back,
+ u32 reg, void *val, size_t size)
+{
+ if (!size)
+ return -EINVAL;
+
+ return iio_backend_op_call(back, bus_reg_read, reg, val, size);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_bus_reg_read, IIO_BACKEND);
+
+/**
+ * iio_backend_bus_reg_write - Write on the interface bus
+ * @back: Backend device
+ * @reg: Register value
+ * @val: Register Value
+ * @size: Size in bytes
+ *
+ * A backend may operate on a specific interface with a related bus.
+ * Write to the interface bus.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_bus_reg_write(struct iio_backend *back,
+ u32 reg, void *val, size_t size)
+{
+ if (!size)
+ return -EINVAL;
+
+ return iio_backend_op_call(back, bus_reg_write, reg, val, size);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_bus_reg_write, IIO_BACKEND);
+
static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, const char *name,
struct fwnode_handle *fwnode)
{
diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h
index 37d56914d485..6f56bbb9e391 100644
--- a/include/linux/iio/backend.h
+++ b/include/linux/iio/backend.h
@@ -14,12 +14,14 @@ struct iio_dev;
enum iio_backend_data_type {
IIO_BACKEND_TWOS_COMPLEMENT,
IIO_BACKEND_OFFSET_BINARY,
+ IIO_BACKEND_DATA_UNSIGNED,
IIO_BACKEND_DATA_TYPE_MAX
};
enum iio_backend_data_source {
IIO_BACKEND_INTERNAL_CONTINUOUS_WAVE,
IIO_BACKEND_EXTERNAL,
+ IIO_BACKEND_INTERNAL_RAMP_16,
IIO_BACKEND_DATA_SOURCE_MAX
};
@@ -129,6 +131,17 @@ struct iio_backend_ops {
size_t len);
int (*debugfs_reg_access)(struct iio_backend *back, unsigned int reg,
unsigned int writeval, unsigned int *readval);
+ int (*ext_sync_enable)(struct iio_backend *back);
+ int (*ext_sync_disable)(struct iio_backend *back);
+ int (*ddr_enable)(struct iio_backend *back);
+ int (*ddr_disable)(struct iio_backend *back);
+ int (*buffer_enable)(struct iio_backend *back);
+ int (*buffer_disable)(struct iio_backend *back);
+ int (*data_transfer_addr)(struct iio_backend *back, u32 address);
+ int (*bus_reg_read)(struct iio_backend *back, u32 reg, void *val,
+ size_t size);
+ int (*bus_reg_write)(struct iio_backend *back, u32 reg, void *val,
+ size_t size);
};
/**
@@ -164,6 +177,17 @@ int iio_backend_data_sample_trigger(struct iio_backend *back,
int devm_iio_backend_request_buffer(struct device *dev,
struct iio_backend *back,
struct iio_dev *indio_dev);
+int iio_backend_ext_sync_enable(struct iio_backend *back);
+int iio_backend_ext_sync_disable(struct iio_backend *back);
+int iio_backend_ddr_enable(struct iio_backend *back);
+int iio_backend_ddr_disable(struct iio_backend *back);
+int iio_backend_buffer_enable(struct iio_backend *back);
+int iio_backend_buffer_disable(struct iio_backend *back);
+int iio_backend_data_transfer_addr(struct iio_backend *back, u32 address);
+int iio_backend_bus_reg_read(struct iio_backend *back,
+ u32 reg, void *val, size_t size);
+int iio_backend_bus_reg_write(struct iio_backend *back,
+ u32 reg, void *val, size_t size);
ssize_t iio_backend_ext_info_set(struct iio_dev *indio_dev, uintptr_t private,
const struct iio_chan_spec *chan,
const char *buf, size_t len);
--
2.45.0.rc1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH RFC 3/8] iio: backend adi-axi-dac: backend features
2024-08-29 12:31 [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Angelo Dureghello
2024-08-29 12:31 ` [PATCH RFC 1/8] dt-bindings: iio: dac: ad3552r: add io-backend property Angelo Dureghello
2024-08-29 12:32 ` [PATCH RFC 2/8] iio: backend: extend features Angelo Dureghello
@ 2024-08-29 12:32 ` Angelo Dureghello
2024-08-31 11:34 ` Jonathan Cameron
2024-08-29 12:32 ` [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property Angelo Dureghello
` (5 subsequent siblings)
8 siblings, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-08-29 12:32 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan
Cc: linux-iio, devicetree, linux-kernel, dlechner, Angelo Dureghello
From: Angelo Dureghello <adureghello@baylibre.com>
Extend DAC backend with new features required for the AXI driver
version for the a3552r DAC.
Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
---
drivers/iio/dac/adi-axi-dac.c | 250 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 248 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
index 0cb00f3bec04..395f222e254d 100644
--- a/drivers/iio/dac/adi-axi-dac.c
+++ b/drivers/iio/dac/adi-axi-dac.c
@@ -44,11 +44,34 @@
#define AXI_DAC_RSTN_MMCM_RSTN BIT(1)
#define AXI_DAC_RSTN_RSTN BIT(0)
#define AXI_DAC_REG_CNTRL_1 0x0044
+#define AXI_DAC_EXT_SYNC_ARM BIT(1)
+#define AXI_DAC_EXT_SYNC_DISARM BIT(2)
#define AXI_DAC_SYNC BIT(0)
#define AXI_DAC_REG_CNTRL_2 0x0048
-#define ADI_DAC_R1_MODE BIT(4)
+#define AXI_DAC_SDR_DDR_N BIT(16)
+#define AXI_DAC_SYMB_8B BIT(14)
+#define ADI_DAC_R1_MODE BIT(5)
+#define AXI_DAC_UNSIGNED_DATA BIT(4)
+#define AXI_DAC_REG_STATUS_1 0x54
+#define AXI_DAC_REG_STATUS_2 0x58
#define AXI_DAC_DRP_STATUS 0x0074
#define AXI_DAC_DRP_LOCKED BIT(17)
+#define AXI_DAC_CNTRL_DATA_RD 0x0080
+#define AXI_DAC_DATA_RD_8 GENMASK(7, 0)
+#define AXI_DAC_DATA_RD_16 GENMASK(15, 0)
+#define AXI_DAC_CNTRL_DATA_WR 0x0084
+#define AXI_DAC_DATA_WR_8 GENMASK(23, 16)
+#define AXI_DAC_DATA_WR_16 GENMASK(23, 8)
+#define AXI_DAC_UI_STATUS 0x0088
+#define AXI_DAC_BUSY BIT(4)
+#define AXI_DAC_REG_CUSTOM_CTRL 0x008C
+#define AXI_DAC_ADDRESS GENMASK(31, 24)
+#define AXI_DAC_SYNCED_TRANSFER BIT(2)
+#define AXI_DAC_STREAM BIT(1)
+#define AXI_DAC_TRANSFER_DATA BIT(0)
+
+#define AXI_DAC_STREAM_ENABLE (AXI_DAC_TRANSFER_DATA | AXI_DAC_STREAM)
+
/* DAC Channel controls */
#define AXI_DAC_REG_CHAN_CNTRL_1(c) (0x0400 + (c) * 0x40)
#define AXI_DAC_REG_CHAN_CNTRL_3(c) (0x0408 + (c) * 0x40)
@@ -62,11 +85,20 @@
#define AXI_DAC_REG_CHAN_CNTRL_7(c) (0x0418 + (c) * 0x40)
#define AXI_DAC_DATA_SEL GENMASK(3, 0)
+#define AXI_DAC_RD_ADDR(x) (BIT(7) | (x))
+
/* 360 degrees in rad */
#define AXI_DAC_2_PI_MEGA 6283190
+
enum {
AXI_DAC_DATA_INTERNAL_TONE,
AXI_DAC_DATA_DMA = 2,
+ AXI_DAC_DATA_INTERNAL_RAMP_16 = 11,
+};
+
+enum {
+ AXI_DAC_BUS_TYPE_NONE,
+ AXI_DAC_BUS_TYPE_QSPI,
};
struct axi_dac_state {
@@ -80,6 +112,7 @@ struct axi_dac_state {
u64 dac_clk;
u32 reg_config;
bool int_tone;
+ int bus_type;
};
static int axi_dac_enable(struct iio_backend *back)
@@ -460,7 +493,13 @@ static int axi_dac_data_source_set(struct iio_backend *back, unsigned int chan,
case IIO_BACKEND_EXTERNAL:
return regmap_update_bits(st->regmap,
AXI_DAC_REG_CHAN_CNTRL_7(chan),
- AXI_DAC_DATA_SEL, AXI_DAC_DATA_DMA);
+ AXI_DAC_DATA_SEL,
+ AXI_DAC_DATA_DMA);
+ case IIO_BACKEND_INTERNAL_RAMP_16:
+ return regmap_update_bits(st->regmap,
+ AXI_DAC_REG_CHAN_CNTRL_7(chan),
+ AXI_DAC_DATA_SEL,
+ AXI_DAC_DATA_INTERNAL_RAMP_16);
default:
return -EINVAL;
}
@@ -518,9 +557,204 @@ static int axi_dac_reg_access(struct iio_backend *back, unsigned int reg,
return regmap_write(st->regmap, reg, writeval);
}
+static int axi_dac_ext_sync_enable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1,
+ AXI_DAC_EXT_SYNC_ARM);
+}
+
+static int axi_dac_ext_sync_disable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_clear_bits(st->regmap, AXI_DAC_REG_CNTRL_1,
+ AXI_DAC_EXT_SYNC_DISARM);
+}
+
+static int axi_dac_ddr_enable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_clear_bits(st->regmap, AXI_DAC_REG_CNTRL_2,
+ AXI_DAC_SDR_DDR_N);
+}
+
+static int axi_dac_ddr_disable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_2,
+ AXI_DAC_SDR_DDR_N);
+}
+
+static int axi_dac_buffer_enable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_set_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
+ AXI_DAC_STREAM_ENABLE);
+}
+
+static int axi_dac_buffer_disable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_clear_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
+ AXI_DAC_STREAM_ENABLE);
+}
+
+static int axi_dac_data_transfer_addr(struct iio_backend *back, u32 address)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ /*
+ * Sample register address, when the DAC is configured, or stream
+ * start address when the FSM is in stream state.
+ */
+ return regmap_update_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
+ AXI_DAC_ADDRESS,
+ FIELD_PREP(AXI_DAC_ADDRESS, address));
+}
+
+static int axi_dac_data_format_set(struct iio_backend *back, unsigned int ch,
+ const struct iio_backend_data_fmt *data)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ if (data->type == IIO_BACKEND_DATA_UNSIGNED)
+ return regmap_clear_bits(st->regmap, AXI_DAC_REG_CNTRL_2,
+ AXI_DAC_UNSIGNED_DATA);
+
+ return -EINVAL;
+}
+
+static int axi_dac_read_raw(struct iio_backend *back,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_FREQUENCY:
+ *val = clk_get_rate(devm_clk_get(st->dev, 0));
+
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int axi_dac_bus_reg_write(struct iio_backend *back,
+ u32 reg, void *val, size_t size)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ if (!st->bus_type)
+ return -EOPNOTSUPP;
+
+ if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
+ int ret;
+ u32 ival;
+
+ if (size != 1 && size != 2)
+ return -EINVAL;
+
+ switch (size) {
+ case 1:
+ ival = FIELD_PREP(AXI_DAC_DATA_WR_8, *(u8 *)val);
+ break;
+ case 2:
+ ival = FIELD_PREP(AXI_DAC_DATA_WR_16, *(u16 *)val);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_write(st->regmap, AXI_DAC_CNTRL_DATA_WR, ival);
+ if (ret)
+ return ret;
+
+ /*
+ * Both REG_CNTRL_2 and AXI_DAC_CNTRL_DATA_WR need to know
+ * the data size. So keeping data size control here only,
+ * since data size is mandatory for to the current transfer.
+ * DDR state handled separately by specific backend calls,
+ * generally all raw register writes are SDR.
+ */
+ if (size == 1)
+ ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_2,
+ AXI_DAC_SYMB_8B);
+ else
+ ret = regmap_clear_bits(st->regmap, AXI_DAC_REG_CNTRL_2,
+ AXI_DAC_SYMB_8B);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
+ AXI_DAC_ADDRESS,
+ FIELD_PREP(AXI_DAC_ADDRESS, reg));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
+ AXI_DAC_TRANSFER_DATA,
+ AXI_DAC_TRANSFER_DATA);
+ if (ret)
+ return ret;
+
+ ret = regmap_read_poll_timeout(st->regmap,
+ AXI_DAC_REG_CUSTOM_CTRL, ival,
+ ival & AXI_DAC_TRANSFER_DATA,
+ 10, 100 * KILO);
+ if (ret)
+ return ret;
+
+ return regmap_clear_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
+ AXI_DAC_TRANSFER_DATA);
+ }
+
+ return -EINVAL;
+}
+
+static int axi_dac_bus_reg_read(struct iio_backend *back,
+ u32 reg, void *val, size_t size)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ if (!st->bus_type)
+ return -EOPNOTSUPP;
+
+ if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
+ int ret;
+ u32 bval;
+
+ if (size != 1 && size != 2)
+ return -EINVAL;
+
+ bval = 0;
+ ret = axi_dac_bus_reg_write(back,
+ AXI_DAC_RD_ADDR(reg), &bval, size);
+ if (ret)
+ return ret;
+
+ ret = regmap_read_poll_timeout(st->regmap, AXI_DAC_UI_STATUS,
+ bval, bval != AXI_DAC_BUSY,
+ 10, 100);
+ if (ret)
+ return ret;
+
+ return regmap_read(st->regmap, AXI_DAC_CNTRL_DATA_RD, val);
+ }
+
+ return -EINVAL;
+}
+
static const struct iio_backend_ops axi_dac_generic_ops = {
.enable = axi_dac_enable,
.disable = axi_dac_disable,
+ .read_raw = axi_dac_read_raw,
.request_buffer = axi_dac_request_buffer,
.free_buffer = axi_dac_free_buffer,
.extend_chan_spec = axi_dac_extend_chan,
@@ -528,6 +762,16 @@ static const struct iio_backend_ops axi_dac_generic_ops = {
.ext_info_get = axi_dac_ext_info_get,
.data_source_set = axi_dac_data_source_set,
.set_sample_rate = axi_dac_set_sample_rate,
+ .ext_sync_enable = axi_dac_ext_sync_enable,
+ .ext_sync_disable = axi_dac_ext_sync_disable,
+ .ddr_enable = axi_dac_ddr_enable,
+ .ddr_disable = axi_dac_ddr_disable,
+ .buffer_enable = axi_dac_buffer_enable,
+ .buffer_disable = axi_dac_buffer_disable,
+ .data_format_set = axi_dac_data_format_set,
+ .data_transfer_addr = axi_dac_data_transfer_addr,
+ .bus_reg_read = axi_dac_bus_reg_read,
+ .bus_reg_write = axi_dac_bus_reg_write,
.debugfs_reg_access = iio_backend_debugfs_ptr(axi_dac_reg_access),
};
@@ -576,6 +820,8 @@ static int axi_dac_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(st->regmap),
"failed to init register map\n");
+ device_property_read_u32(st->dev, "bus-type", &st->bus_type);
+
/*
* Force disable the core. Up to the frontend to enable us. And we can
* still read/write registers...
--
2.45.0.rc1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-08-29 12:31 [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Angelo Dureghello
` (2 preceding siblings ...)
2024-08-29 12:32 ` [PATCH RFC 3/8] iio: backend adi-axi-dac: backend features Angelo Dureghello
@ 2024-08-29 12:32 ` Angelo Dureghello
2024-08-29 13:39 ` Rob Herring (Arm)
2024-08-29 15:46 ` Conor Dooley
2024-08-29 12:32 ` [PATCH RFC 5/8] iio: dac: ad3552r: changes to use FIELD_PREP Angelo Dureghello
` (4 subsequent siblings)
8 siblings, 2 replies; 54+ messages in thread
From: Angelo Dureghello @ 2024-08-29 12:32 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan
Cc: linux-iio, devicetree, linux-kernel, dlechner, Angelo Dureghello
From: Angelo Dureghello <adureghello@baylibre.com>
Add bus property.
Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
---
Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
index a55e9bfc66d7..a7ce72e1cd81 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
@@ -38,6 +38,15 @@ properties:
clocks:
maxItems: 1
+ bus-type:
+ maxItems: 1
+ description: |
+ Configure bus type:
+ - 0: none
+ - 1: qspi
+ enum: [0, 1]
+ default: 0
+
'#io-backend-cells':
const: 0
--
2.45.0.rc1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH RFC 5/8] iio: dac: ad3552r: changes to use FIELD_PREP
2024-08-29 12:31 [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Angelo Dureghello
` (3 preceding siblings ...)
2024-08-29 12:32 ` [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property Angelo Dureghello
@ 2024-08-29 12:32 ` Angelo Dureghello
2024-08-31 11:48 ` Jonathan Cameron
2024-08-29 12:32 ` [PATCH RFC 6/8] iio: dac: ad3552r: extract common code (no changes in behavior intended) Angelo Dureghello
` (3 subsequent siblings)
8 siblings, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-08-29 12:32 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan
Cc: linux-iio, devicetree, linux-kernel, dlechner, Angelo Dureghello
From: Angelo Dureghello <adureghello@baylibre.com>
Changes to use FIELD_PREP, so that driver-specific ad3552r_field_prep
is removed. Variables (arrays) that was used to call ad3552r_field_prep
are removerd too.
Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
---
drivers/iio/dac/ad3552r.c | 126 ++++++++++++++++++----------------------------
1 file changed, 49 insertions(+), 77 deletions(-)
diff --git a/drivers/iio/dac/ad3552r.c b/drivers/iio/dac/ad3552r.c
index bd37d304ca70..d867de7c90d1 100644
--- a/drivers/iio/dac/ad3552r.c
+++ b/drivers/iio/dac/ad3552r.c
@@ -285,45 +285,6 @@ struct ad3552r_desc {
unsigned int num_ch;
};
-static const u16 addr_mask_map[][2] = {
- [AD3552R_ADDR_ASCENSION] = {
- AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
- AD3552R_MASK_ADDR_ASCENSION
- },
- [AD3552R_SDO_DRIVE_STRENGTH] = {
- AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
- AD3552R_MASK_SDO_DRIVE_STRENGTH
- },
- [AD3552R_VREF_SELECT] = {
- AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
- AD3552R_MASK_REFERENCE_VOLTAGE_SEL
- },
-};
-
-/* 0 -> reg addr, 1->ch0 mask, 2->ch1 mask */
-static const u16 addr_mask_map_ch[][3] = {
- [AD3552R_CH_DAC_POWERDOWN] = {
- AD3552R_REG_ADDR_POWERDOWN_CONFIG,
- AD3552R_MASK_CH_DAC_POWERDOWN(0),
- AD3552R_MASK_CH_DAC_POWERDOWN(1)
- },
- [AD3552R_CH_AMPLIFIER_POWERDOWN] = {
- AD3552R_REG_ADDR_POWERDOWN_CONFIG,
- AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(0),
- AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(1)
- },
- [AD3552R_CH_OUTPUT_RANGE_SEL] = {
- AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
- AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0),
- AD3552R_MASK_CH_OUTPUT_RANGE_SEL(1)
- },
- [AD3552R_CH_SELECT] = {
- AD3552R_REG_ADDR_CH_SELECT_16B,
- AD3552R_MASK_CH(0),
- AD3552R_MASK_CH(1)
- }
-};
-
static u8 _ad3552r_reg_len(u8 addr)
{
switch (addr) {
@@ -399,11 +360,6 @@ static int ad3552r_read_reg(struct ad3552r_desc *dac, u8 addr, u16 *val)
return 0;
}
-static u16 ad3552r_field_prep(u16 val, u16 mask)
-{
- return (val << __ffs(mask)) & mask;
-}
-
/* Update field of a register, shift val if needed */
static int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask,
u16 val)
@@ -416,21 +372,11 @@ static int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask,
return ret;
reg &= ~mask;
- reg |= ad3552r_field_prep(val, mask);
+ reg |= val;
return ad3552r_write_reg(dac, addr, reg);
}
-static int ad3552r_set_ch_value(struct ad3552r_desc *dac,
- enum ad3552r_ch_attributes attr,
- u8 ch,
- u16 val)
-{
- /* Update register related to attributes in chip */
- return ad3552r_update_reg_field(dac, addr_mask_map_ch[attr][0],
- addr_mask_map_ch[attr][ch + 1], val);
-}
-
#define AD3552R_CH_DAC(_idx) ((struct iio_chan_spec) { \
.type = IIO_VOLTAGE, \
.output = true, \
@@ -510,8 +456,14 @@ static int ad3552r_write_raw(struct iio_dev *indio_dev,
val);
break;
case IIO_CHAN_INFO_ENABLE:
- err = ad3552r_set_ch_value(dac, AD3552R_CH_DAC_POWERDOWN,
- chan->channel, !val);
+ if (chan->channel == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH_DAC_POWERDOWN(0), !val);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH_DAC_POWERDOWN(1), !val);
+
+ err = ad3552r_update_reg_field(dac, AD3552R_REG_ADDR_POWERDOWN_CONFIG,
+ AD3552R_MASK_CH_DAC_POWERDOWN(chan->channel),
+ val);
break;
default:
err = -EINVAL;
@@ -715,9 +667,9 @@ static int ad3552r_reset(struct ad3552r_desc *dac)
}
return ad3552r_update_reg_field(dac,
- addr_mask_map[AD3552R_ADDR_ASCENSION][0],
- addr_mask_map[AD3552R_ADDR_ASCENSION][1],
- val);
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
+ AD3552R_MASK_ADDR_ASCENSION,
+ FIELD_PREP(AD3552R_MASK_ADDR_ASCENSION, val));
}
static void ad3552r_get_custom_range(struct ad3552r_desc *dac, s32 i, s32 *v_min,
@@ -812,20 +764,20 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
"mandatory custom-output-range-config property missing\n");
dac->ch_data[ch].range_override = 1;
- reg |= ad3552r_field_prep(1, AD3552R_MASK_CH_RANGE_OVERRIDE);
+ reg |= FIELD_PREP(AD3552R_MASK_CH_RANGE_OVERRIDE, 1);
err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val);
if (err)
return dev_err_probe(dev, err,
"mandatory adi,gain-scaling-p property missing\n");
- reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_P);
+ reg |= FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_P, val);
dac->ch_data[ch].p = val;
err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val);
if (err)
return dev_err_probe(dev, err,
"mandatory adi,gain-scaling-n property missing\n");
- reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_N);
+ reg |= FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_N, val);
dac->ch_data[ch].n = val;
err = fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val);
@@ -841,9 +793,9 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
dac->ch_data[ch].gain_offset = val;
offset = abs((s32)val);
- reg |= ad3552r_field_prep((offset >> 8), AD3552R_MASK_CH_OFFSET_BIT_8);
+ reg |= FIELD_PREP(AD3552R_MASK_CH_OFFSET_BIT_8, (offset >> 8));
- reg |= ad3552r_field_prep((s32)val < 0, AD3552R_MASK_CH_OFFSET_POLARITY);
+ reg |= FIELD_PREP(AD3552R_MASK_CH_OFFSET_POLARITY, (s32)val < 0);
addr = AD3552R_REG_ADDR_CH_GAIN(ch);
err = ad3552r_write_reg(dac, addr,
offset & AD3552R_MASK_CH_OFFSET_BITS_0_7);
@@ -886,9 +838,9 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
}
err = ad3552r_update_reg_field(dac,
- addr_mask_map[AD3552R_VREF_SELECT][0],
- addr_mask_map[AD3552R_VREF_SELECT][1],
- val);
+ AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
+ AD3552R_MASK_REFERENCE_VOLTAGE_SEL,
+ FIELD_PREP(AD3552R_MASK_REFERENCE_VOLTAGE_SEL, val));
if (err)
return err;
@@ -900,9 +852,9 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
}
err = ad3552r_update_reg_field(dac,
- addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][0],
- addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][1],
- val);
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SDO_DRIVE_STRENGTH,
+ FIELD_PREP(AD3552R_MASK_SDO_DRIVE_STRENGTH, val));
if (err)
return err;
}
@@ -938,9 +890,15 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
"Invalid adi,output-range-microvolt value\n");
val = err;
- err = ad3552r_set_ch_value(dac,
- AD3552R_CH_OUTPUT_RANGE_SEL,
- ch, val);
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0), val);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(1), val);
+
+ err = ad3552r_update_reg_field(dac,
+ AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
+ AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch),
+ val);
if (err)
return err;
@@ -958,7 +916,14 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
ad3552r_calc_gain_and_offset(dac, ch);
dac->enabled_ch |= BIT(ch);
- err = ad3552r_set_ch_value(dac, AD3552R_CH_SELECT, ch, 1);
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH(0), 1);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH(1), 1);
+
+ err = ad3552r_update_reg_field(dac,
+ AD3552R_REG_ADDR_CH_SELECT_16B,
+ AD3552R_MASK_CH(ch), val);
if (err < 0)
return err;
@@ -970,8 +935,15 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
/* Disable unused channels */
for_each_clear_bit(ch, &dac->enabled_ch,
dac->model_data->num_hw_channels) {
- err = ad3552r_set_ch_value(dac, AD3552R_CH_AMPLIFIER_POWERDOWN,
- ch, 1);
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0), 1);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(1), 1);
+
+ err = ad3552r_update_reg_field(dac,
+ AD3552R_REG_ADDR_POWERDOWN_CONFIG,
+ AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch),
+ val);
if (err)
return err;
}
--
2.45.0.rc1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH RFC 6/8] iio: dac: ad3552r: extract common code (no changes in behavior intended)
2024-08-29 12:31 [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Angelo Dureghello
` (4 preceding siblings ...)
2024-08-29 12:32 ` [PATCH RFC 5/8] iio: dac: ad3552r: changes to use FIELD_PREP Angelo Dureghello
@ 2024-08-29 12:32 ` Angelo Dureghello
2024-08-29 12:32 ` [PATCH RFC 7/8] iio: dac: ad3552r: add axi platform driver Angelo Dureghello
` (2 subsequent siblings)
8 siblings, 0 replies; 54+ messages in thread
From: Angelo Dureghello @ 2024-08-29 12:32 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan
Cc: linux-iio, devicetree, linux-kernel, dlechner, Angelo Dureghello
From: Angelo Dureghello <adureghello@baylibre.com>
Extracting common code, to share common code to be used later
by the AXI driver version (ad3552r-axi.c).
Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
---
drivers/iio/dac/Makefile | 2 +-
drivers/iio/dac/ad3552r-common.c | 163 +++++++++++++++++++++++
drivers/iio/dac/ad3552r.c | 276 ++++-----------------------------------
drivers/iio/dac/ad3552r.h | 199 ++++++++++++++++++++++++++++
4 files changed, 389 insertions(+), 251 deletions(-)
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 2cf148f16306..56a125f56284 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -4,7 +4,7 @@
#
# When adding new entries keep the list in alphabetical order
-obj-$(CONFIG_AD3552R) += ad3552r.o
+obj-$(CONFIG_AD3552R) += ad3552r.o ad3552r-common.o
obj-$(CONFIG_AD5360) += ad5360.o
obj-$(CONFIG_AD5380) += ad5380.o
obj-$(CONFIG_AD5421) += ad5421.o
diff --git a/drivers/iio/dac/ad3552r-common.c b/drivers/iio/dac/ad3552r-common.c
new file mode 100644
index 000000000000..c8ccfbe2e95e
--- /dev/null
+++ b/drivers/iio/dac/ad3552r-common.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (c) 2010-2024 Analog Devices Inc.
+// Copyright (c) 2024 Baylibre, SAS
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regulator/consumer.h>
+
+#include "ad3552r.h"
+
+static const s32 ad3552r_ch_ranges[][2] = {
+ [AD3552R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500},
+ [AD3552R_CH_OUTPUT_RANGE_0__5V] = {0, 5000},
+ [AD3552R_CH_OUTPUT_RANGE_0__10V] = {0, 10000},
+ [AD3552R_CH_OUTPUT_RANGE_NEG_5__5V] = {-5000, 5000},
+ [AD3552R_CH_OUTPUT_RANGE_NEG_10__10V] = {-10000, 10000}
+};
+
+static const s32 ad3542r_ch_ranges[][2] = {
+ [AD3542R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500},
+ [AD3542R_CH_OUTPUT_RANGE_0__3V] = {0, 3000},
+ [AD3542R_CH_OUTPUT_RANGE_0__5V] = {0, 5000},
+ [AD3542R_CH_OUTPUT_RANGE_0__10V] = {0, 10000},
+ [AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V] = {-2500, 7500},
+ [AD3542R_CH_OUTPUT_RANGE_NEG_5__5V] = {-5000, 5000}
+};
+
+void ad3552r_calc_custom_gain(u8 p, u8 n, s16 goffs, u16 *reg)
+{
+ *reg = FIELD_PREP(AD3552R_MASK_CH_RANGE_OVERRIDE, 1);
+ *reg |= FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_P, p);
+ *reg |= FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_N, n);
+ *reg |= FIELD_PREP(AD3552R_MASK_CH_OFFSET_BIT_8, abs((s32)goffs) >> 8);
+ *reg |= FIELD_PREP(AD3552R_MASK_CH_OFFSET_POLARITY, (s32)goffs < 0);
+}
+
+int ad3552r_get_ref_voltage(struct device *dev, u32 *val)
+{
+ int voltage, delta = 100000;
+
+ voltage = devm_regulator_get_enable_read_voltage(dev, "vref");
+ if (voltage < 0 && voltage != -ENODEV)
+ return dev_err_probe(dev, voltage,
+ "Error getting vref voltage\n");
+
+ if (voltage == -ENODEV) {
+ if (device_property_read_bool(dev, "adi,vref-out-en"))
+ *val = AD3552R_INTERNAL_VREF_PIN_2P5V;
+ else
+ *val = AD3552R_INTERNAL_VREF_PIN_FLOATING;
+ } else {
+ if (voltage > 2500000 + delta || voltage < 2500000 - delta) {
+ dev_warn(dev, "vref-supply must be 2.5V");
+ return -EINVAL;
+ }
+ *val = AD3552R_EXTERNAL_VREF_PIN_INPUT;
+ }
+
+ return 0;
+}
+
+int ad3552r_get_drive_strength(struct device *dev, u32 *val)
+{
+ int err;
+
+ err = device_property_read_u32(dev, "adi,sdo-drive-strength", val);
+ if (!err && *val > 3) {
+ dev_err(dev,
+ "adi,sdo-drive-strength must be less than 4\n");
+ return -EINVAL;
+ }
+
+ return err;
+}
+
+int ad3552r_get_custom_gain(struct device *dev, struct fwnode_handle *child,
+ u8 *gs_p, u8 *gs_n, u16 *rfb, s16 *goffs)
+{
+ int err;
+ u32 val;
+ struct fwnode_handle *gain_child __free(fwnode_handle)
+ = fwnode_get_named_child_node(child,
+ "custom-output-range-config");
+
+ if (!gain_child)
+ return dev_err_probe(dev, -EINVAL,
+ "custom-output-range-config mandatory\n");
+
+ err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,gain-scaling-p mandatory\n");
+ *gs_p = val;
+
+ err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,gain-scaling-n property mandatory\n");
+ *gs_n = val;
+
+ err = fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,rfb-ohms mandatoryn");
+ *rfb = val;
+
+ err = fwnode_property_read_u32(gain_child, "adi,gain-offset", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,gain-offset mandatory\n");
+ *goffs = val;
+
+ return 0;
+}
+
+static int ad3552r_find_range(u16 id, s32 *vals)
+{
+ int i, len;
+ const s32 (*ranges)[2];
+
+ if (id == AD3542R_ID) {
+ len = ARRAY_SIZE(ad3542r_ch_ranges);
+ ranges = ad3542r_ch_ranges;
+ } else {
+ len = ARRAY_SIZE(ad3552r_ch_ranges);
+ ranges = ad3552r_ch_ranges;
+ }
+
+ for (i = 0; i < len; i++)
+ if (vals[0] == ranges[i][0] * 1000 &&
+ vals[1] == ranges[i][1] * 1000)
+ return i;
+
+ return -EINVAL;
+}
+
+int ad3552r_get_output_range(struct device *dev, enum ad3552r_id chip_id,
+ struct fwnode_handle *child, u32 *val)
+{
+ int ret;
+ s32 vals[2];
+
+ if (!fwnode_property_present(child, "adi,output-range-microvolt"))
+ return -ENOENT;
+
+ ret = fwnode_property_read_u32_array(child,
+ "adi,output-range-microvolt",
+ vals, 2);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "invalid adi,output-range-microvolt\n");
+
+ ret = ad3552r_find_range(chip_id, vals);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "invalid adi,output-range-microvolt value\n");
+
+ *val = ret;
+
+ return 0;
+}
diff --git a/drivers/iio/dac/ad3552r.c b/drivers/iio/dac/ad3552r.c
index d867de7c90d1..c149be9c8c7d 100644
--- a/drivers/iio/dac/ad3552r.c
+++ b/drivers/iio/dac/ad3552r.c
@@ -11,153 +11,9 @@
#include <linux/iio/trigger_consumer.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
-#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
-/* Register addresses */
-/* Primary address space */
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_A 0x00
-#define AD3552R_MASK_SOFTWARE_RESET (BIT(7) | BIT(0))
-#define AD3552R_MASK_ADDR_ASCENSION BIT(5)
-#define AD3552R_MASK_SDO_ACTIVE BIT(4)
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_B 0x01
-#define AD3552R_MASK_SINGLE_INST BIT(7)
-#define AD3552R_MASK_SHORT_INSTRUCTION BIT(3)
-#define AD3552R_REG_ADDR_DEVICE_CONFIG 0x02
-#define AD3552R_MASK_DEVICE_STATUS(n) BIT(4 + (n))
-#define AD3552R_MASK_CUSTOM_MODES GENMASK(3, 2)
-#define AD3552R_MASK_OPERATING_MODES GENMASK(1, 0)
-#define AD3552R_REG_ADDR_CHIP_TYPE 0x03
-#define AD3552R_MASK_CLASS GENMASK(7, 0)
-#define AD3552R_REG_ADDR_PRODUCT_ID_L 0x04
-#define AD3552R_REG_ADDR_PRODUCT_ID_H 0x05
-#define AD3552R_REG_ADDR_CHIP_GRADE 0x06
-#define AD3552R_MASK_GRADE GENMASK(7, 4)
-#define AD3552R_MASK_DEVICE_REVISION GENMASK(3, 0)
-#define AD3552R_REG_ADDR_SCRATCH_PAD 0x0A
-#define AD3552R_REG_ADDR_SPI_REVISION 0x0B
-#define AD3552R_REG_ADDR_VENDOR_L 0x0C
-#define AD3552R_REG_ADDR_VENDOR_H 0x0D
-#define AD3552R_REG_ADDR_STREAM_MODE 0x0E
-#define AD3552R_MASK_LENGTH GENMASK(7, 0)
-#define AD3552R_REG_ADDR_TRANSFER_REGISTER 0x0F
-#define AD3552R_MASK_MULTI_IO_MODE GENMASK(7, 6)
-#define AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE BIT(2)
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_C 0x10
-#define AD3552R_MASK_CRC_ENABLE (GENMASK(7, 6) |\
- GENMASK(1, 0))
-#define AD3552R_MASK_STRICT_REGISTER_ACCESS BIT(5)
-#define AD3552R_REG_ADDR_INTERFACE_STATUS_A 0x11
-#define AD3552R_MASK_INTERFACE_NOT_READY BIT(7)
-#define AD3552R_MASK_CLOCK_COUNTING_ERROR BIT(5)
-#define AD3552R_MASK_INVALID_OR_NO_CRC BIT(3)
-#define AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER BIT(2)
-#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS BIT(1)
-#define AD3552R_MASK_REGISTER_ADDRESS_INVALID BIT(0)
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_D 0x14
-#define AD3552R_MASK_ALERT_ENABLE_PULLUP BIT(6)
-#define AD3552R_MASK_MEM_CRC_EN BIT(4)
-#define AD3552R_MASK_SDO_DRIVE_STRENGTH GENMASK(3, 2)
-#define AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN BIT(1)
-#define AD3552R_MASK_SPI_CONFIG_DDR BIT(0)
-#define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG 0x15
-#define AD3552R_MASK_IDUMP_FAST_MODE BIT(6)
-#define AD3552R_MASK_SAMPLE_HOLD_DIFFERENTIAL_USER_EN BIT(5)
-#define AD3552R_MASK_SAMPLE_HOLD_USER_TRIM GENMASK(4, 3)
-#define AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE BIT(2)
-#define AD3552R_MASK_REFERENCE_VOLTAGE_SEL GENMASK(1, 0)
-#define AD3552R_REG_ADDR_ERR_ALARM_MASK 0x16
-#define AD3552R_MASK_REF_RANGE_ALARM BIT(6)
-#define AD3552R_MASK_CLOCK_COUNT_ERR_ALARM BIT(5)
-#define AD3552R_MASK_MEM_CRC_ERR_ALARM BIT(4)
-#define AD3552R_MASK_SPI_CRC_ERR_ALARM BIT(3)
-#define AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM BIT(2)
-#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM BIT(1)
-#define AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM BIT(0)
-#define AD3552R_REG_ADDR_ERR_STATUS 0x17
-#define AD3552R_MASK_REF_RANGE_ERR_STATUS BIT(6)
-#define AD3552R_MASK_DUAL_SPI_STREAM_EXCEEDS_DAC_ERR_STATUS BIT(5)
-#define AD3552R_MASK_MEM_CRC_ERR_STATUS BIT(4)
-#define AD3552R_MASK_RESET_STATUS BIT(0)
-#define AD3552R_REG_ADDR_POWERDOWN_CONFIG 0x18
-#define AD3552R_MASK_CH_DAC_POWERDOWN(ch) BIT(4 + (ch))
-#define AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch) BIT(ch)
-#define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE 0x19
-#define AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch) ((ch) ? GENMASK(7, 4) :\
- GENMASK(3, 0))
-#define AD3552R_REG_ADDR_CH_OFFSET(ch) (0x1B + (ch) * 2)
-#define AD3552R_MASK_CH_OFFSET_BITS_0_7 GENMASK(7, 0)
-#define AD3552R_REG_ADDR_CH_GAIN(ch) (0x1C + (ch) * 2)
-#define AD3552R_MASK_CH_RANGE_OVERRIDE BIT(7)
-#define AD3552R_MASK_CH_GAIN_SCALING_N GENMASK(6, 5)
-#define AD3552R_MASK_CH_GAIN_SCALING_P GENMASK(4, 3)
-#define AD3552R_MASK_CH_OFFSET_POLARITY BIT(2)
-#define AD3552R_MASK_CH_OFFSET_BIT_8 BIT(0)
-/*
- * Secondary region
- * For multibyte registers specify the highest address because the access is
- * done in descending order
- */
-#define AD3552R_SECONDARY_REGION_START 0x28
-#define AD3552R_REG_ADDR_HW_LDAC_16B 0x28
-#define AD3552R_REG_ADDR_CH_DAC_16B(ch) (0x2C - (1 - ch) * 2)
-#define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B 0x2E
-#define AD3552R_REG_ADDR_CH_SELECT_16B 0x2F
-#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B 0x31
-#define AD3552R_REG_ADDR_SW_LDAC_16B 0x32
-#define AD3552R_REG_ADDR_CH_INPUT_16B(ch) (0x36 - (1 - ch) * 2)
-/* 3 bytes registers */
-#define AD3552R_REG_START_24B 0x37
-#define AD3552R_REG_ADDR_HW_LDAC_24B 0x37
-#define AD3552R_REG_ADDR_CH_DAC_24B(ch) (0x3D - (1 - ch) * 3)
-#define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B 0x40
-#define AD3552R_REG_ADDR_CH_SELECT_24B 0x41
-#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B 0x44
-#define AD3552R_REG_ADDR_SW_LDAC_24B 0x45
-#define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - ch) * 3)
-
-/* Useful defines */
-#define AD3552R_MAX_CH 2
-#define AD3552R_MASK_CH(ch) BIT(ch)
-#define AD3552R_MASK_ALL_CH GENMASK(1, 0)
-#define AD3552R_MAX_REG_SIZE 3
-#define AD3552R_READ_BIT BIT(7)
-#define AD3552R_ADDR_MASK GENMASK(6, 0)
-#define AD3552R_MASK_DAC_12B 0xFFF0
-#define AD3552R_DEFAULT_CONFIG_B_VALUE 0x8
-#define AD3552R_SCRATCH_PAD_TEST_VAL1 0x34
-#define AD3552R_SCRATCH_PAD_TEST_VAL2 0xB2
-#define AD3552R_GAIN_SCALE 1000
-#define AD3552R_LDAC_PULSE_US 100
-
-enum ad3552r_ch_vref_select {
- /* Internal source with Vref I/O floating */
- AD3552R_INTERNAL_VREF_PIN_FLOATING,
- /* Internal source with Vref I/O at 2.5V */
- AD3552R_INTERNAL_VREF_PIN_2P5V,
- /* External source with Vref I/O as input */
- AD3552R_EXTERNAL_VREF_PIN_INPUT
-};
-
-enum ad3552r_id {
- AD3541R_ID = 0x400b,
- AD3542R_ID = 0x4009,
- AD3551R_ID = 0x400a,
- AD3552R_ID = 0x4008,
-};
-
-enum ad3552r_ch_output_range {
- /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
- AD3552R_CH_OUTPUT_RANGE_0__2P5V,
- /* Range from 0 V to 5 V. Requires Rfb1x connection */
- AD3552R_CH_OUTPUT_RANGE_0__5V,
- /* Range from 0 V to 10 V. Requires Rfb2x connection */
- AD3552R_CH_OUTPUT_RANGE_0__10V,
- /* Range from -5 V to 5 V. Requires Rfb2x connection */
- AD3552R_CH_OUTPUT_RANGE_NEG_5__5V,
- /* Range from -10 V to 10 V. Requires Rfb4x connection */
- AD3552R_CH_OUTPUT_RANGE_NEG_10__10V,
-};
+#include "ad3552r.h"
static const s32 ad3552r_ch_ranges[][2] = {
[AD3552R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500},
@@ -167,21 +23,6 @@ static const s32 ad3552r_ch_ranges[][2] = {
[AD3552R_CH_OUTPUT_RANGE_NEG_10__10V] = {-10000, 10000}
};
-enum ad3542r_ch_output_range {
- /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
- AD3542R_CH_OUTPUT_RANGE_0__2P5V,
- /* Range from 0 V to 3 V. Requires Rfb1x connection */
- AD3542R_CH_OUTPUT_RANGE_0__3V,
- /* Range from 0 V to 5 V. Requires Rfb1x connection */
- AD3542R_CH_OUTPUT_RANGE_0__5V,
- /* Range from 0 V to 10 V. Requires Rfb2x connection */
- AD3542R_CH_OUTPUT_RANGE_0__10V,
- /* Range from -2.5 V to 7.5 V. Requires Rfb2x connection */
- AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V,
- /* Range from -5 V to 5 V. Requires Rfb2x connection */
- AD3542R_CH_OUTPUT_RANGE_NEG_5__5V,
-};
-
static const s32 ad3542r_ch_ranges[][2] = {
[AD3542R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500},
[AD3542R_CH_OUTPUT_RANGE_0__3V] = {0, 3000},
@@ -733,72 +574,32 @@ static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch)
dac->ch_data[ch].offset_dec = div_s64(tmp, span);
}
-static int ad3552r_find_range(const struct ad3552r_model_data *model_data,
- s32 *vals)
-{
- int i;
-
- for (i = 0; i < model_data->num_ranges; i++)
- if (vals[0] == model_data->ranges_table[i][0] * 1000 &&
- vals[1] == model_data->ranges_table[i][1] * 1000)
- return i;
-
- return -EINVAL;
-}
-
static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
struct fwnode_handle *child,
u32 ch)
{
struct device *dev = &dac->spi->dev;
- u32 val;
int err;
u8 addr;
- u16 reg = 0, offset;
-
- struct fwnode_handle *gain_child __free(fwnode_handle)
- = fwnode_get_named_child_node(child,
- "custom-output-range-config");
- if (!gain_child)
- return dev_err_probe(dev, -EINVAL,
- "mandatory custom-output-range-config property missing\n");
-
- dac->ch_data[ch].range_override = 1;
- reg |= FIELD_PREP(AD3552R_MASK_CH_RANGE_OVERRIDE, 1);
-
- err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val);
- if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,gain-scaling-p property missing\n");
- reg |= FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_P, val);
- dac->ch_data[ch].p = val;
+ u16 reg = 0;
- err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val);
+ err = ad3552r_get_custom_gain(dev, child,
+ &dac->ch_data[ch].p,
+ &dac->ch_data[ch].n,
+ &dac->ch_data[ch].rfb,
+ &dac->ch_data[ch].gain_offset);
if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,gain-scaling-n property missing\n");
- reg |= FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_N, val);
- dac->ch_data[ch].n = val;
-
- err = fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val);
- if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,rfb-ohms property missing\n");
- dac->ch_data[ch].rfb = val;
+ return err;
- err = fwnode_property_read_u32(gain_child, "adi,gain-offset", &val);
- if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,gain-offset property missing\n");
- dac->ch_data[ch].gain_offset = val;
+ dac->ch_data[ch].range_override = 1;
- offset = abs((s32)val);
- reg |= FIELD_PREP(AD3552R_MASK_CH_OFFSET_BIT_8, (offset >> 8));
+ ad3552r_calc_custom_gain(dac->ch_data[ch].p, dac->ch_data[ch].n,
+ dac->ch_data[ch].gain_offset, ®);
- reg |= FIELD_PREP(AD3552R_MASK_CH_OFFSET_POLARITY, (s32)val < 0);
addr = AD3552R_REG_ADDR_CH_GAIN(ch);
err = ad3552r_write_reg(dac, addr,
- offset & AD3552R_MASK_CH_OFFSET_BITS_0_7);
+ abs((s32)dac->ch_data[ch].gain_offset) &
+ AD3552R_MASK_CH_OFFSET_BITS_0_7);
if (err)
return dev_err_probe(dev, err, "Error writing register\n");
@@ -812,30 +613,17 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
static int ad3552r_configure_device(struct ad3552r_desc *dac)
{
struct device *dev = &dac->spi->dev;
- int err, cnt = 0, voltage, delta = 100000;
- u32 vals[2], val, ch;
+ int err, cnt = 0;
+ u32 val, ch;
dac->gpio_ldac = devm_gpiod_get_optional(dev, "ldac", GPIOD_OUT_HIGH);
if (IS_ERR(dac->gpio_ldac))
return dev_err_probe(dev, PTR_ERR(dac->gpio_ldac),
"Error getting gpio ldac");
- voltage = devm_regulator_get_enable_read_voltage(dev, "vref");
- if (voltage < 0 && voltage != -ENODEV)
- return dev_err_probe(dev, voltage, "Error getting vref voltage\n");
-
- if (voltage == -ENODEV) {
- if (device_property_read_bool(dev, "adi,vref-out-en"))
- val = AD3552R_INTERNAL_VREF_PIN_2P5V;
- else
- val = AD3552R_INTERNAL_VREF_PIN_FLOATING;
- } else {
- if (voltage > 2500000 + delta || voltage < 2500000 - delta) {
- dev_warn(dev, "vref-supply must be 2.5V");
- return -EINVAL;
- }
- val = AD3552R_EXTERNAL_VREF_PIN_INPUT;
- }
+ err = ad3552r_get_ref_voltage(dev, &val);
+ if (err)
+ return err;
err = ad3552r_update_reg_field(dac,
AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
@@ -844,13 +632,10 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
if (err)
return err;
- err = device_property_read_u32(dev, "adi,sdo-drive-strength", &val);
+ err = ad3552r_get_drive_strength(dev, &val);
+ if (err)
+ return err;
if (!err) {
- if (val > 3) {
- dev_err(dev, "adi,sdo-drive-strength must be less than 4\n");
- return -EINVAL;
- }
-
err = ad3552r_update_reg_field(dac,
AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
AD3552R_MASK_SDO_DRIVE_STRENGTH,
@@ -875,21 +660,12 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
"reg must be less than %d\n",
dac->model_data->num_hw_channels);
- if (fwnode_property_present(child, "adi,output-range-microvolt")) {
- err = fwnode_property_read_u32_array(child,
- "adi,output-range-microvolt",
- vals,
- 2);
- if (err)
- return dev_err_probe(dev, err,
- "adi,output-range-microvolt property could not be parsed\n");
-
- err = ad3552r_find_range(dac->model_data, vals);
- if (err < 0)
- return dev_err_probe(dev, err,
- "Invalid adi,output-range-microvolt value\n");
+ err = ad3552r_get_output_range(dev, dac->model_data->chip_id,
+ child, &val);
+ if (err && err != -ENOENT)
+ return err;
- val = err;
+ if (!err) {
if (ch == 0)
val = FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0), val);
else
diff --git a/drivers/iio/dac/ad3552r.h b/drivers/iio/dac/ad3552r.h
new file mode 100644
index 000000000000..cada1f12f000
--- /dev/null
+++ b/drivers/iio/dac/ad3552r.h
@@ -0,0 +1,199 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AD3552R Digital <-> Analog converters common header
+ *
+ * Copyright 2024 Analog Devices Inc.
+ * Author: Angelo Dureghello <adureghello@baylibre.com>
+ */
+
+#ifndef __DRIVERS_IIO_DAC_AD3552R_H__
+#define __DRIVERS_IIO_DAC_AD3552R_H__
+
+/* Register addresses */
+/* Primary address space */
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_A 0x00
+#define AD3552R_MASK_SOFTWARE_RESET (BIT(7) | BIT(0))
+#define AD3552R_MASK_ADDR_ASCENSION BIT(5)
+#define AD3552R_MASK_SDO_ACTIVE BIT(4)
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_B 0x01
+#define AD3552R_MASK_SINGLE_INST BIT(7)
+#define AD3552R_MASK_SHORT_INSTRUCTION BIT(3)
+#define AD3552R_REG_ADDR_DEVICE_CONFIG 0x02
+#define AD3552R_MASK_DEVICE_STATUS(n) BIT(4 + (n))
+#define AD3552R_MASK_CUSTOM_MODES GENMASK(3, 2)
+#define AD3552R_MASK_OPERATING_MODES GENMASK(1, 0)
+#define AD3552R_REG_ADDR_CHIP_TYPE 0x03
+#define AD3552R_MASK_CLASS GENMASK(7, 0)
+#define AD3552R_REG_ADDR_PRODUCT_ID_L 0x04
+#define AD3552R_REG_ADDR_PRODUCT_ID_H 0x05
+#define AD3552R_REG_ADDR_CHIP_GRADE 0x06
+#define AD3552R_MASK_GRADE GENMASK(7, 4)
+#define AD3552R_MASK_DEVICE_REVISION GENMASK(3, 0)
+#define AD3552R_REG_ADDR_SCRATCH_PAD 0x0A
+#define AD3552R_REG_ADDR_SPI_REVISION 0x0B
+#define AD3552R_REG_ADDR_VENDOR_L 0x0C
+#define AD3552R_REG_ADDR_VENDOR_H 0x0D
+#define AD3552R_REG_ADDR_STREAM_MODE 0x0E
+#define AD3552R_MASK_LENGTH GENMASK(7, 0)
+#define AD3552R_REG_ADDR_TRANSFER_REGISTER 0x0F
+#define AD3552R_MASK_MULTI_IO_MODE GENMASK(7, 6)
+#define AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE BIT(2)
+#define AD3552R_MASK_DUAL_SPI BIT(6)
+#define AD3552R_MASK_QUAD_SPI BIT(7)
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_C 0x10
+#define AD3552R_MASK_CRC_ENABLE (GENMASK(7, 6) |\
+ GENMASK(1, 0))
+#define AD3552R_MASK_STRICT_REGISTER_ACCESS BIT(5)
+#define AD3552R_REG_ADDR_INTERFACE_STATUS_A 0x11
+#define AD3552R_MASK_INTERFACE_NOT_READY BIT(7)
+#define AD3552R_MASK_CLOCK_COUNTING_ERROR BIT(5)
+#define AD3552R_MASK_INVALID_OR_NO_CRC BIT(3)
+#define AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER BIT(2)
+#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS BIT(1)
+#define AD3552R_MASK_REGISTER_ADDRESS_INVALID BIT(0)
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_D 0x14
+#define AD3552R_MASK_ALERT_ENABLE_PULLUP BIT(6)
+#define AD3552R_MASK_MEM_CRC_EN BIT(4)
+#define AD3552R_MASK_SDO_DRIVE_STRENGTH GENMASK(3, 2)
+#define AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN BIT(1)
+#define AD3552R_MASK_SPI_CONFIG_DDR BIT(0)
+#define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG 0x15
+#define AD3552R_MASK_IDUMP_FAST_MODE BIT(6)
+#define AD3552R_MASK_SAMPLE_HOLD_DIFF_USER_EN BIT(5)
+#define AD3552R_MASK_SAMPLE_HOLD_USER_TRIM GENMASK(4, 3)
+#define AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE BIT(2)
+#define AD3552R_MASK_REFERENCE_VOLTAGE_SEL GENMASK(1, 0)
+#define AD3552R_REG_ADDR_ERR_ALARM_MASK 0x16
+#define AD3552R_MASK_REF_RANGE_ALARM BIT(6)
+#define AD3552R_MASK_CLOCK_COUNT_ERR_ALARM BIT(5)
+#define AD3552R_MASK_MEM_CRC_ERR_ALARM BIT(4)
+#define AD3552R_MASK_SPI_CRC_ERR_ALARM BIT(3)
+#define AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM BIT(2)
+#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM BIT(1)
+#define AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM BIT(0)
+#define AD3552R_REG_ADDR_ERR_STATUS 0x17
+#define AD3552R_MASK_REF_RANGE_ERR_STATUS BIT(6)
+#define AD3552R_MASK_STREAM_EXCEEDS_DAC_ERR_STATUS BIT(5)
+#define AD3552R_MASK_MEM_CRC_ERR_STATUS BIT(4)
+#define AD3552R_MASK_RESET_STATUS BIT(0)
+#define AD3552R_REG_ADDR_POWERDOWN_CONFIG 0x18
+#define AD3552R_MASK_CH_DAC_POWERDOWN(ch) BIT(4 + (ch))
+#define AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch) BIT(ch)
+#define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE 0x19
+#define AD3552R_MASK_CH0_RANGE GENMASK(2, 0)
+#define AD3552R_MASK_CH1_RANGE GENMASK(6, 4)
+#define AD3552R_MASK_CH_OUTPUT_RANGE GENMASK(7, 0)
+#define AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch) ((ch) ? \
+ GENMASK(7, 4) : \
+ GENMASK(3, 0))
+#define AD3552R_REG_ADDR_CH_OFFSET(ch) (0x1B + (ch) * 2)
+#define AD3552R_MASK_CH_OFFSET_BITS_0_7 GENMASK(7, 0)
+#define AD3552R_REG_ADDR_CH_GAIN(ch) (0x1C + (ch) * 2)
+#define AD3552R_MASK_CH_RANGE_OVERRIDE BIT(7)
+#define AD3552R_MASK_CH_GAIN_SCALING_N GENMASK(6, 5)
+#define AD3552R_MASK_CH_GAIN_SCALING_P GENMASK(4, 3)
+#define AD3552R_MASK_CH_OFFSET_POLARITY BIT(2)
+#define AD3552R_MASK_CH_OFFSET_BIT_8 BIT(0)
+/*
+ * Secondary region
+ * For multibyte registers specify the highest address because the access is
+ * done in descending order
+ */
+#define AD3552R_SECONDARY_REGION_START 0x28
+#define AD3552R_REG_ADDR_HW_LDAC_16B 0x28
+#define AD3552R_REG_ADDR_CH_DAC_16B(ch) (0x2C - (1 - (ch)) * 2)
+#define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B 0x2E
+#define AD3552R_REG_ADDR_CH_SELECT_16B 0x2F
+#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B 0x31
+#define AD3552R_REG_ADDR_SW_LDAC_16B 0x32
+#define AD3552R_REG_ADDR_CH_INPUT_16B(ch) (0x36 - (1 - (ch)) * 2)
+/* 3 bytes registers */
+#define AD3552R_REG_START_24B 0x37
+#define AD3552R_REG_ADDR_HW_LDAC_24B 0x37
+#define AD3552R_REG_ADDR_CH_DAC_24B(ch) (0x3D - (1 - (ch)) * 3)
+#define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B 0x40
+#define AD3552R_REG_ADDR_CH_SELECT_24B 0x41
+#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B 0x44
+#define AD3552R_REG_ADDR_SW_LDAC_24B 0x45
+#define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - (ch)) * 3)
+
+/* Useful defines */
+#define AD3552R_MAX_CH 2
+#define AD3552R_MASK_CH(ch) BIT(ch)
+#define AD3552R_MASK_ALL_CH GENMASK(1, 0)
+#define AD3552R_MAX_REG_SIZE 3
+#define AD3552R_READ_BIT BIT(7)
+#define AD3552R_ADDR_MASK GENMASK(6, 0)
+#define AD3552R_MASK_DAC_12B GENMASK(15, 4)
+#define AD3552R_DEFAULT_CONFIG_B_VALUE 0x8
+#define AD3552R_SCRATCH_PAD_TEST_VAL1 0x34
+#define AD3552R_SCRATCH_PAD_TEST_VAL2 0xB2
+#define AD3552R_GAIN_SCALE 1000
+#define AD3552R_LDAC_PULSE_US 100
+
+#define AD3552R_AXI_REG_MAX 0x35
+#define AD3552R_REF_INIT 0x00
+#define AD3552R_STREAM_2BYTE_LOOP 0x02
+#define AD3552R_STREAM_4BYTE_LOOP 0x04
+
+#define AD3552R_CH0_ACTIVE BIT(0)
+#define AD3552R_CH1_ACTIVE BIT(1)
+#define AD3552R_CH0_CH1_ACTIVE (AD3552R_CH0_ACTIVE | \
+ AD3552R_CH1_ACTIVE)
+
+#define AD3552R_TRANSFER_INIT (AD3552R_MASK_QUAD_SPI | \
+ AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE)
+
+enum ad3552r_id {
+ AD3541R_ID = 0x400b,
+ AD3542R_ID = 0x4009,
+ AD3551R_ID = 0x400a,
+ AD3552R_ID = 0x4008,
+};
+
+enum ad3552r_ch_vref_select {
+ /* Internal source with Vref I/O floating */
+ AD3552R_INTERNAL_VREF_PIN_FLOATING,
+ /* Internal source with Vref I/O at 2.5V */
+ AD3552R_INTERNAL_VREF_PIN_2P5V,
+ /* External source with Vref I/O as input */
+ AD3552R_EXTERNAL_VREF_PIN_INPUT
+};
+
+enum ad3542r_ch_output_range {
+ /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__2P5V,
+ /* Range from 0 V to 3 V. Requires Rfb1x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__3V,
+ /* Range from 0 V to 5 V. Requires Rfb1x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__5V,
+ /* Range from 0 V to 10 V. Requires Rfb2x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__10V,
+ /* Range from -2.5 V to 7.5 V. Requires Rfb2x connection */
+ AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V,
+ /* Range from -5 V to 5 V. Requires Rfb2x connection */
+ AD3542R_CH_OUTPUT_RANGE_NEG_5__5V,
+};
+
+enum ad3552r_ch_output_range {
+ /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
+ AD3552R_CH_OUTPUT_RANGE_0__2P5V,
+ /* Range from 0 V to 5 V. Requires Rfb1x connection */
+ AD3552R_CH_OUTPUT_RANGE_0__5V,
+ /* Range from 0 V to 10 V. Requires Rfb2x connection */
+ AD3552R_CH_OUTPUT_RANGE_0__10V,
+ /* Range from -5 V to 5 V. Requires Rfb2x connection */
+ AD3552R_CH_OUTPUT_RANGE_NEG_5__5V,
+ /* Range from -10 V to 10 V. Requires Rfb4x connection */
+ AD3552R_CH_OUTPUT_RANGE_NEG_10__10V,
+};
+
+int ad3552r_get_output_range(struct device *dev, enum ad3552r_id id,
+ struct fwnode_handle *child, u32 *val);
+int ad3552r_get_custom_gain(struct device *dev, struct fwnode_handle *child,
+ u8 *gs_p, u8 *gs_n, u16 *rfb, s16 *goffs);
+void ad3552r_calc_custom_gain(u8 p, u8 n, s16 goffs, u16 *reg);
+int ad3552r_get_ref_voltage(struct device *dev, u32 *val);
+int ad3552r_get_drive_strength(struct device *dev, u32 *val);
+
+#endif /* __DRIVERS_IIO_DAC_AD3552R_H__ */
--
2.45.0.rc1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH RFC 7/8] iio: dac: ad3552r: add axi platform driver
2024-08-29 12:31 [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Angelo Dureghello
` (5 preceding siblings ...)
2024-08-29 12:32 ` [PATCH RFC 6/8] iio: dac: ad3552r: extract common code (no changes in behavior intended) Angelo Dureghello
@ 2024-08-29 12:32 ` Angelo Dureghello
2024-08-31 12:13 ` Jonathan Cameron
2024-08-29 12:32 ` [PATCH RFC 8/8] iio: ABI: add DAC sysfs synchronous_mode parameter Angelo Dureghello
2024-08-31 11:38 ` [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Jonathan Cameron
8 siblings, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-08-29 12:32 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan
Cc: linux-iio, devicetree, linux-kernel, dlechner, Angelo Dureghello
From: Angelo Dureghello <adureghello@baylibre.com>
Add support for ad3552r AXI DAC IP version.
Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
---
drivers/iio/dac/Kconfig | 11 +
drivers/iio/dac/Makefile | 1 +
drivers/iio/dac/ad3552r-axi.c | 572 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 584 insertions(+)
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 1cfd7e2a622f..030af7702a3c 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -16,6 +16,17 @@ config AD3552R
To compile this driver as a module, choose M here: the
module will be called ad3552r.
+config AD3552R_AXI
+ tristate "Analog Devices AD3552R DAC driver, AXI version"
+ select IIO_BACKEND
+ help
+ Say yes here to build support for Analog Devices AD3552R
+ Digital to Analog Converter, connected through the Xilinx
+ fpga AXI interface.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad3552r-axi.
+
config AD5064
tristate "Analog Devices AD5064 and similar multi-channel DAC driver"
depends on (SPI_MASTER && I2C!=m) || I2C
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 56a125f56284..cc2af3aa3f52 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -5,6 +5,7 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AD3552R) += ad3552r.o ad3552r-common.o
+obj-$(CONFIG_AD3552R_AXI) += ad3552r-axi.o ad3552r-common.o
obj-$(CONFIG_AD5360) += ad5360.o
obj-$(CONFIG_AD5380) += ad5380.o
obj-$(CONFIG_AD5421) += ad5421.o
diff --git a/drivers/iio/dac/ad3552r-axi.c b/drivers/iio/dac/ad3552r-axi.c
new file mode 100644
index 000000000000..98e5da08c973
--- /dev/null
+++ b/drivers/iio/dac/ad3552r-axi.c
@@ -0,0 +1,572 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Analog Devices AD3552R
+ * Digital to Analog converter driver, AXI DAC backend version
+ *
+ * Copyright 2024 Analog Devices Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/backend.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/units.h>
+
+#include "ad3552r.h"
+
+enum ad3552r_synchronous_mode_status {
+ AD3552R_NO_SYNC,
+ AD3552R_EXT_SYNC_ARM,
+};
+
+struct ad3552r_axi_state {
+ struct gpio_desc *reset_gpio;
+ struct device *dev;
+ struct iio_backend *back;
+ unsigned long active_scan_mask;
+ enum ad3552r_id chip_id;
+ bool single_channel;
+ bool synced_transfer;
+};
+
+static int axi3552r_qspi_update_reg_bits(struct iio_backend *back,
+ u32 reg, u32 mask, u32 val,
+ size_t xfer_size)
+{
+ u32 rval;
+ int err;
+
+ err = iio_backend_bus_reg_read(back, reg, &rval, xfer_size);
+ if (err)
+ return err;
+
+ rval &= ~mask;
+ rval |= val;
+
+ return iio_backend_bus_reg_write(back, reg, &rval, xfer_size);
+}
+
+static int ad3552r_axi_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct ad3552r_axi_state *st = iio_priv(indio_dev);
+ int err, ch = chan->channel;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ: {
+ int clk_rate;
+
+ err = iio_backend_read_raw(st->back, chan, &clk_rate, 0,
+ IIO_CHAN_INFO_FREQUENCY);
+ if (err != IIO_VAL_INT)
+ return err;
+
+ /*
+ * Data stream SDR/DDR (clk_in/8 or clk_in/4 update rate).
+ * Samplerate has sense in DDR only.
+ */
+ if (st->single_channel)
+ clk_rate = DIV_ROUND_CLOSEST(clk_rate, 4);
+ else
+ clk_rate = DIV_ROUND_CLOSEST(clk_rate, 8);
+
+ *val = clk_rate;
+
+ return IIO_VAL_INT;
+ }
+ case IIO_CHAN_INFO_RAW:
+ err = iio_backend_bus_reg_read(st->back,
+ AD3552R_REG_ADDR_CH_DAC_16B(ch),
+ val, 2);
+ if (err)
+ return err;
+
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad3552r_axi_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ struct ad3552r_axi_state *st = iio_priv(indio_dev);
+ int ch = chan->channel;
+
+ return iio_backend_bus_reg_write(st->back,
+ AD3552R_REG_ADDR_CH_DAC_16B(ch), &val, 2);
+ }
+ unreachable();
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad3552r_axi_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *active_scan_mask)
+{
+ struct ad3552r_axi_state *st = iio_priv(indio_dev);
+
+ st->active_scan_mask = *active_scan_mask;
+
+ return 0;
+}
+
+static int ad3552r_axi_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct ad3552r_axi_state *st = iio_priv(indio_dev);
+ struct iio_backend_data_fmt fmt = {
+ .type = IIO_BACKEND_DATA_UNSIGNED
+ };
+ int loop_len, val, err;
+
+ /* Inform DAC chip to switch into DDR mode */
+ err = axi3552r_qspi_update_reg_bits(st->back,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SPI_CONFIG_DDR,
+ AD3552R_MASK_SPI_CONFIG_DDR, 1);
+ if (err)
+ return err;
+
+ /* Inform DAC IP to go for DDR mode from now on */
+ err = iio_backend_ddr_enable(st->back);
+ if (err)
+ goto exit_err;
+
+ switch (st->active_scan_mask) {
+ case AD3552R_CH0_ACTIVE:
+ st->single_channel = true;
+ loop_len = AD3552R_STREAM_2BYTE_LOOP;
+ val = AD3552R_REG_ADDR_CH_DAC_16B(0);
+ break;
+ case AD3552R_CH1_ACTIVE:
+ st->single_channel = true;
+ loop_len = AD3552R_STREAM_2BYTE_LOOP;
+ val = AD3552R_REG_ADDR_CH_DAC_16B(1);
+ break;
+ case AD3552R_CH0_CH1_ACTIVE:
+ st->single_channel = false;
+ loop_len = AD3552R_STREAM_4BYTE_LOOP;
+ val = AD3552R_REG_ADDR_CH_DAC_16B(1);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = iio_backend_bus_reg_write(st->back, AD3552R_REG_ADDR_STREAM_MODE,
+ &loop_len, 1);
+ if (err)
+ goto exit_err;
+
+ iio_backend_data_transfer_addr(st->back, val);
+ if (err)
+ goto exit_err;
+ /*
+ * The EXT_SYNC is mandatory in the CN0585 project where 2 instances
+ * of the IP are in the design and they need to generate the signals
+ * synchronized.
+ *
+ * Note: in first IP implementations CONFIG EXT_SYNC (RO) can be 0,
+ * but EXT_SYMC is anabled anyway.
+ */
+
+ if (st->synced_transfer == AD3552R_EXT_SYNC_ARM)
+ err = iio_backend_ext_sync_enable(st->back);
+ else
+ err = iio_backend_ext_sync_disable(st->back);
+ if (err)
+ goto exit_err_sync;
+
+ err = iio_backend_data_format_set(st->back, 0, &fmt);
+ if (err)
+ goto exit_err;
+
+ err = iio_backend_buffer_enable(st->back);
+ if (!err)
+ return 0;
+
+exit_err_sync:
+ iio_backend_ext_sync_disable(st->back);
+
+exit_err:
+ axi3552r_qspi_update_reg_bits(st->back,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SPI_CONFIG_DDR,
+ 0, 1);
+
+ iio_backend_ddr_disable(st->back);
+
+ return err;
+}
+
+static int ad3552r_axi_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct ad3552r_axi_state *st = iio_priv(indio_dev);
+ int err;
+
+ err = iio_backend_buffer_disable(st->back);
+ if (err)
+ return err;
+
+ /* Inform DAC to set in DDR mode */
+ err = axi3552r_qspi_update_reg_bits(st->back,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SPI_CONFIG_DDR,
+ 0, 1);
+ if (err)
+ return err;
+
+ return iio_backend_ddr_disable(st->back);
+}
+
+static int ad3552r_axi_set_output_range(struct ad3552r_axi_state *st,
+ unsigned int mode)
+{
+ int range_ch_0 = FIELD_PREP(AD3552R_MASK_CH0_RANGE, mode);
+ int range_ch_1 = FIELD_PREP(AD3552R_MASK_CH1_RANGE, mode);
+
+ return axi3552r_qspi_update_reg_bits(st->back,
+ AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
+ AD3552R_MASK_CH_OUTPUT_RANGE,
+ range_ch_0 | range_ch_1, 1);
+}
+
+static int ad3552r_axi_reset(struct ad3552r_axi_state *st)
+{
+ int err;
+
+ /* AXI reset performed by backend enable() */
+
+ st->reset_gpio = devm_gpiod_get_optional(st->dev,
+ "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(st->reset_gpio))
+ return PTR_ERR(st->reset_gpio);
+
+ if (st->reset_gpio) {
+ gpiod_set_value_cansleep(st->reset_gpio, 1);
+ fsleep(10);
+ gpiod_set_value_cansleep(st->reset_gpio, 0);
+ } else {
+ err = axi3552r_qspi_update_reg_bits(st->back,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
+ AD3552R_MASK_SOFTWARE_RESET,
+ AD3552R_MASK_SOFTWARE_RESET, 1);
+ if (err)
+ return err;
+ }
+ msleep(100);
+
+ return 0;
+}
+
+static int ad3552r_axi_setup(struct ad3552r_axi_state *st)
+{
+ struct fwnode_handle *child __free(fwnode_handle) = NULL;
+ u8 gs_p, gs_n;
+ s16 goffs;
+ u16 id, rfb, reg = 0, offset = 0;
+ u32 val, range;
+ int err;
+
+ err = ad3552r_axi_reset(st);
+ if (err)
+ return err;
+
+ err = iio_backend_ddr_disable(st->back);
+ if (err)
+ return err;
+
+ val = AD3552R_SCRATCH_PAD_TEST_VAL1;
+ err = iio_backend_bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ &val, 1);
+ if (err)
+ return err;
+
+ err = iio_backend_bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ &val, 1);
+ if (err)
+ return err;
+
+ if (val != AD3552R_SCRATCH_PAD_TEST_VAL1) {
+ dev_err(st->dev,
+ "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n",
+ AD3552R_SCRATCH_PAD_TEST_VAL1, val);
+ return -EIO;
+ }
+
+ val = AD3552R_SCRATCH_PAD_TEST_VAL2;
+ err = iio_backend_bus_reg_write(st->back,
+ AD3552R_REG_ADDR_SCRATCH_PAD,
+ &val, 1);
+ if (err)
+ return err;
+
+ err = iio_backend_bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ &val, 1);
+ if (err)
+ return err;
+
+ if (val != AD3552R_SCRATCH_PAD_TEST_VAL2) {
+ dev_err(st->dev,
+ "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n",
+ AD3552R_SCRATCH_PAD_TEST_VAL2, val);
+ return -EIO;
+ }
+
+ err = iio_backend_bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_L,
+ &val, 1);
+ if (err)
+ return err;
+
+ id = val;
+ mdelay(100);
+
+ err = iio_backend_bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_H,
+ &val, 1);
+ if (err)
+ return err;
+
+ id |= val << 8;
+ if (id != AD3552R_ID) {
+ dev_err(st->dev, "Chip ID mismatch. Expected 0x%x, Read 0x%x\n",
+ AD3552R_ID, id);
+ return -ENODEV;
+ }
+
+ st->chip_id = id;
+
+ val = AD3552R_REF_INIT;
+ err = iio_backend_bus_reg_write(st->back,
+ AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
+ &val, 1);
+ if (err)
+ return err;
+
+ val = AD3552R_TRANSFER_INIT;
+ err = iio_backend_bus_reg_write(st->back,
+ AD3552R_REG_ADDR_TRANSFER_REGISTER,
+ &val, 1);
+ if (err)
+ return err;
+
+ err = iio_backend_data_source_set(st->back, 0, IIO_BACKEND_EXTERNAL);
+ if (err)
+ return err;
+
+ err = iio_backend_data_source_set(st->back, 1, IIO_BACKEND_EXTERNAL);
+ if (err)
+ return err;
+
+ err = ad3552r_get_ref_voltage(st->dev, &val);
+ if (err)
+ return err;
+
+ err = axi3552r_qspi_update_reg_bits(st->back,
+ AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
+ AD3552R_MASK_REFERENCE_VOLTAGE_SEL,
+ val, 1);
+ if (err)
+ return err;
+
+ err = ad3552r_get_drive_strength(st->dev, &val);
+ if (!err) {
+ err = axi3552r_qspi_update_reg_bits(st->back,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SDO_DRIVE_STRENGTH,
+ val, 1);
+ if (err)
+ return err;
+ }
+
+ child = device_get_named_child_node(st->dev, "channel");
+ if (!child)
+ return -EINVAL;
+
+ err = ad3552r_get_output_range(st->dev, st->chip_id, child, &range);
+ if (!err)
+ return ad3552r_axi_set_output_range(st, range);
+
+ if (err != -ENOENT)
+ return err;
+
+ /* Try to get custom range */
+ err = ad3552r_get_custom_gain(st->dev, child,
+ &gs_p, &gs_n, &rfb, &goffs);
+ if (err)
+ return err;
+
+ ad3552r_calc_custom_gain(gs_p, gs_n, goffs, ®);
+
+ offset = abs((s32)goffs);
+
+ err = iio_backend_bus_reg_write(st->back,
+ AD3552R_REG_ADDR_CH_OFFSET(0),
+ &offset, 1);
+ if (err)
+ return dev_err_probe(st->dev, err,
+ "Error writing register\n");
+
+ err = iio_backend_bus_reg_write(st->back,
+ AD3552R_REG_ADDR_CH_OFFSET(1),
+ &offset, 1);
+ if (err)
+ return dev_err_probe(st->dev, err,
+ "Error writing register\n");
+
+ err = iio_backend_bus_reg_write(st->back,
+ AD3552R_REG_ADDR_CH_GAIN(0),
+ ®, 1);
+ if (err)
+ return dev_err_probe(st->dev, err,
+ "Error writing register\n");
+
+ err = iio_backend_bus_reg_write(st->back,
+ AD3552R_REG_ADDR_CH_GAIN(1),
+ ®, 1);
+ if (err)
+ return dev_err_probe(st->dev, err,
+ "Error writing register\n");
+
+ return 0;
+}
+
+static const struct iio_buffer_setup_ops ad3552r_axi_buffer_setup_ops = {
+ .postenable = ad3552r_axi_buffer_postenable,
+ .predisable = ad3552r_axi_buffer_predisable,
+};
+
+static int ad3552r_set_synchronous_mode_status(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ unsigned int status)
+{
+ struct ad3552r_axi_state *st = iio_priv(indio_dev);
+
+ st->synced_transfer = status;
+
+ return 0;
+}
+
+static int ad3552r_get_synchronous_mode_status(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ struct ad3552r_axi_state *st = iio_priv(indio_dev);
+
+ return st->synced_transfer;
+}
+
+static const char *const synchronous_mode_status[] = {
+ [AD3552R_NO_SYNC] = "no_sync",
+ [AD3552R_EXT_SYNC_ARM] = "ext_sync_arm",
+};
+
+static const struct iio_enum ad3552r_synchronous_mode_enum = {
+ .items = synchronous_mode_status,
+ .num_items = ARRAY_SIZE(synchronous_mode_status),
+ .get = ad3552r_get_synchronous_mode_status,
+ .set = ad3552r_set_synchronous_mode_status,
+};
+
+static const struct iio_chan_spec_ext_info ad3552r_axi_ext_info[] = {
+ IIO_ENUM("synchronous_mode", IIO_SHARED_BY_TYPE,
+ &ad3552r_synchronous_mode_enum),
+ IIO_ENUM_AVAILABLE("synchronous_mode", IIO_SHARED_BY_TYPE,
+ &ad3552r_synchronous_mode_enum),
+ {},
+};
+
+#define AD3552R_CHANNEL(ch) { \
+ .type = IIO_VOLTAGE, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_all = (((ch) == 0) ? \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) : 0), \
+ .output = 1, \
+ .indexed = 1, \
+ .channel = (ch), \
+ .scan_index = (ch), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .shift = 0, \
+ .endianness = IIO_BE, \
+ }, \
+ .ext_info = ad3552r_axi_ext_info, \
+}
+
+static struct iio_chan_spec ad3552r_axi_channels[] = {
+ AD3552R_CHANNEL(0),
+ AD3552R_CHANNEL(1),
+};
+
+static const struct iio_info ad3552r_axi_info = {
+ .read_raw = &ad3552r_axi_read_raw,
+ .write_raw = &ad3552r_axi_write_raw,
+ .update_scan_mode = ad3552r_axi_update_scan_mode,
+};
+
+static int ad3552r_axi_probe(struct platform_device *pdev)
+{
+ struct ad3552r_axi_state *st;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+ st->dev = &pdev->dev;
+
+ st->back = devm_iio_backend_get(&pdev->dev, NULL);
+ if (IS_ERR(st->back))
+ return PTR_ERR(st->back);
+
+ ret = devm_iio_backend_enable(&pdev->dev, st->back);
+ if (ret)
+ return ret;
+
+ indio_dev->name = "ad3552r";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->setup_ops = &ad3552r_axi_buffer_setup_ops;
+ indio_dev->channels = ad3552r_axi_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad3552r_axi_channels);
+ indio_dev->info = &ad3552r_axi_info;
+
+ ret = devm_iio_backend_request_buffer(&pdev->dev, st->back, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad3552r_axi_setup(st);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(&pdev->dev, indio_dev);
+}
+
+static const struct of_device_id ad3552r_axi_of_id[] = {
+ { .compatible = "adi,ad3552r" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, ad3552r_axi_of_id);
+
+static struct platform_driver axi_ad3552r_driver = {
+ .driver = {
+ .name = "ad3552r-axi",
+ .of_match_table = ad3552r_axi_of_id,
+ },
+ .probe = ad3552r_axi_probe,
+};
+module_platform_driver(axi_ad3552r_driver);
+
+MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>");
+MODULE_AUTHOR("Angelo Dureghello <adueghello@baylibre.com>");
+MODULE_DESCRIPTION("AD3552R Driver - AXI IP version");
+MODULE_LICENSE("GPL");
--
2.45.0.rc1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH RFC 8/8] iio: ABI: add DAC sysfs synchronous_mode parameter
2024-08-29 12:31 [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Angelo Dureghello
` (6 preceding siblings ...)
2024-08-29 12:32 ` [PATCH RFC 7/8] iio: dac: ad3552r: add axi platform driver Angelo Dureghello
@ 2024-08-29 12:32 ` Angelo Dureghello
2024-08-31 12:15 ` Jonathan Cameron
2024-08-31 11:38 ` [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Jonathan Cameron
8 siblings, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-08-29 12:32 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan
Cc: linux-iio, devicetree, linux-kernel, dlechner, Angelo Dureghello
From: Angelo Dureghello <adureghello@baylibre.com>
Some DACs as ad3552r need a synchronous mode setting, adding
this parameter for ad3552r and for future use on other DACs,
if needed.
Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
---
Documentation/ABI/testing/sysfs-bus-iio-dac | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-dac b/Documentation/ABI/testing/sysfs-bus-iio-dac
index 810eaac5533c..a3012baf90b3 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio-dac
+++ b/Documentation/ABI/testing/sysfs-bus-iio-dac
@@ -59,3 +59,10 @@ Description:
multiple predefined symbols. Each symbol corresponds to a different
output, denoted as out_voltageY_rawN, where N is the integer value
of the symbol. Writing an integer value N will select out_voltageY_rawN.
+
+What: /sys/bus/iio/devices/iio:deviceX/out_voltage_synchronous_mode
+KernelVersion: 6.13
+Contact: linux-iio@vger.kernel.org
+Description:
+ This attribute allows a specific synchronization mode, mainly
+ intended for DACs where multiple synchronization methods are available.
--
2.45.0.rc1
^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-08-29 12:32 ` [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property Angelo Dureghello
@ 2024-08-29 13:39 ` Rob Herring (Arm)
2024-08-29 15:46 ` Conor Dooley
1 sibling, 0 replies; 54+ messages in thread
From: Rob Herring (Arm) @ 2024-08-29 13:39 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Olivier Moysan, Lars-Peter Clausen, devicetree, Conor Dooley,
linux-iio, Michael Hennerich, dlechner, Nuno Sá,
Krzysztof Kozlowski, Jonathan Cameron, linux-kernel
On Thu, 29 Aug 2024 14:32:02 +0200, Angelo Dureghello wrote:
> From: Angelo Dureghello <adureghello@baylibre.com>
>
> Add bus property.
>
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> ---
> Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml: properties:bus-type: 'enum' should not be valid under {'enum': ['const', 'enum', 'exclusiveMaximum', 'exclusiveMinimum', 'minimum', 'maximum', 'multipleOf', 'pattern']}
hint: Scalar and array keywords cannot be mixed
from schema $id: http://devicetree.org/meta-schemas/keywords.yaml#
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240829-wip-bl-ad3552r-axi-v0-v1-4-b6da6015327a@baylibre.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-08-29 12:32 ` [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property Angelo Dureghello
2024-08-29 13:39 ` Rob Herring (Arm)
@ 2024-08-29 15:46 ` Conor Dooley
2024-08-30 8:16 ` Krzysztof Kozlowski
2024-08-30 8:19 ` Angelo Dureghello
1 sibling, 2 replies; 54+ messages in thread
From: Conor Dooley @ 2024-08-29 15:46 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan, linux-iio, devicetree, linux-kernel, dlechner
[-- Attachment #1: Type: text/plain, Size: 1672 bytes --]
On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
> From: Angelo Dureghello <adureghello@baylibre.com>
>
> Add bus property.
RFC it may be, but you do need to explain what this bus-type actually
describes for commenting on the suitability of the method to be
meaningful.
>
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> ---
> Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> index a55e9bfc66d7..a7ce72e1cd81 100644
> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> @@ -38,6 +38,15 @@ properties:
> clocks:
> maxItems: 1
You mentioned about new compatible strings, does the one currently
listed in this binding support both bus types?
Making the bus type decision based on compatible only really makes sense
if they're different versions of the IP, but not if they're different
configuration options for a given version.
> + bus-type:
If, as you mentioned, there are multiple bus types, a non-flag property
does make sense. However, I am really not keen on these "forced" numerical
properties at all, I'd much rather see strings used here.
Thanks,
Conor.
> + maxItems: 1
> + description: |
> + Configure bus type:
> + - 0: none
> + - 1: qspi
> + enum: [0, 1]
> + default: 0
> +
> '#io-backend-cells':
> const: 0
>
>
> --
> 2.45.0.rc1
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-08-29 15:46 ` Conor Dooley
@ 2024-08-30 8:16 ` Krzysztof Kozlowski
2024-08-30 15:06 ` Conor Dooley
2024-08-30 8:19 ` Angelo Dureghello
1 sibling, 1 reply; 54+ messages in thread
From: Krzysztof Kozlowski @ 2024-08-30 8:16 UTC (permalink / raw)
To: Conor Dooley
Cc: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
Nuno Sá, Jonathan Cameron, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Olivier Moysan, linux-iio, devicetree, linux-kernel,
dlechner
On Thu, Aug 29, 2024 at 04:46:59PM +0100, Conor Dooley wrote:
> On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
> > From: Angelo Dureghello <adureghello@baylibre.com>
> >
> > Add bus property.
>
> RFC it may be, but you do need to explain what this bus-type actually
> describes for commenting on the suitability of the method to be
> meaningful.
>
> >
> > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > ---
> > Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9 +++++++++
> > 1 file changed, 9 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > index a55e9bfc66d7..a7ce72e1cd81 100644
> > --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > @@ -38,6 +38,15 @@ properties:
> > clocks:
> > maxItems: 1
>
> You mentioned about new compatible strings, does the one currently
> listed in this binding support both bus types?
>
> Making the bus type decision based on compatible only really makes sense
> if they're different versions of the IP, but not if they're different
> configuration options for a given version.
>
Yeah, in general the parent defines the bus type.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-08-29 15:46 ` Conor Dooley
2024-08-30 8:16 ` Krzysztof Kozlowski
@ 2024-08-30 8:19 ` Angelo Dureghello
2024-08-30 15:33 ` Conor Dooley
1 sibling, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-08-30 8:19 UTC (permalink / raw)
To: Conor Dooley
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan, linux-iio, devicetree, linux-kernel, dlechner
Hi Conor,
On 29/08/24 5:46 PM, Conor Dooley wrote:
> On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
>> From: Angelo Dureghello <adureghello@baylibre.com>
>>
>> Add bus property.
> RFC it may be, but you do need to explain what this bus-type actually
> describes for commenting on the suitability of the method to be
> meaningful.
thanks for the feedbacks,
a "bus" is intended as a generic interface connected to the target,
may be used from a custom IP (fpga) to communicate with the target
device (by read/write(reg and value)) using a special custom interface.
The bus could also be physically the same of some well-known existing
interfaces (as parallel, lvds or other uncommon interfaces), but using
an uncommon/custom protocol over it.
In concrete, actually bus-type is added to the backend since the
ad3552r DAC chip can be connected (for maximum speed) by a 5 lanes DDR
parallel bus (interface that i named QSPI, but it's not exactly a QSPI
as a protocol), so it's a device-specific interface.
With additions in this patchset, other frontends, of course not only
DACs, will be able to add specific busses and read/wrtie to the bus
as needed.
>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>> ---
>> Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9 +++++++++
>> 1 file changed, 9 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>> index a55e9bfc66d7..a7ce72e1cd81 100644
>> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>> @@ -38,6 +38,15 @@ properties:
>> clocks:
>> maxItems: 1
> You mentioned about new compatible strings, does the one currently
> listed in this binding support both bus types?
>
> Making the bus type decision based on compatible only really makes sense
> if they're different versions of the IP, but not if they're different
> configuration options for a given version.
>
>> + bus-type:
DAC IP on fpga actually respects same structure and register set, except
for a named "custom" register that may use specific bitfields depending
on the application of the IP.
> If, as you mentioned, there are multiple bus types, a non-flag property
> does make sense. However, I am really not keen on these "forced" numerical
> properties at all, I'd much rather see strings used here.
ack, thanks.
> Thanks,
> Conor.
thanks a lot,
regards,
Angelo
>> + maxItems: 1
>> + description: |
>> + Configure bus type:
>> + - 0: none
>> + - 1: qspi
>> + enum: [0, 1]
>> + default: 0
>> +
>> '#io-backend-cells':
>> const: 0
>>
>>
>> --
>> 2.45.0.rc1
>>
--
,,, Angelo Dureghello
:: :. BayLibre -runtime team- Developer
:`___:
`____:
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-08-30 8:16 ` Krzysztof Kozlowski
@ 2024-08-30 15:06 ` Conor Dooley
0 siblings, 0 replies; 54+ messages in thread
From: Conor Dooley @ 2024-08-30 15:06 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
Nuno Sá, Jonathan Cameron, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Olivier Moysan, linux-iio, devicetree, linux-kernel,
dlechner
[-- Attachment #1: Type: text/plain, Size: 1838 bytes --]
On Fri, Aug 30, 2024 at 10:16:36AM +0200, Krzysztof Kozlowski wrote:
> On Thu, Aug 29, 2024 at 04:46:59PM +0100, Conor Dooley wrote:
> > On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
> > > From: Angelo Dureghello <adureghello@baylibre.com>
> > >
> > > Add bus property.
> >
> > RFC it may be, but you do need to explain what this bus-type actually
> > describes for commenting on the suitability of the method to be
> > meaningful.
> >
> > >
> > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > ---
> > > Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9 +++++++++
> > > 1 file changed, 9 insertions(+)
> > >
> > > diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > index a55e9bfc66d7..a7ce72e1cd81 100644
> > > --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > @@ -38,6 +38,15 @@ properties:
> > > clocks:
> > > maxItems: 1
> >
> > You mentioned about new compatible strings, does the one currently
> > listed in this binding support both bus types?
> >
> > Making the bus type decision based on compatible only really makes sense
> > if they're different versions of the IP, but not if they're different
> > configuration options for a given version.
> >
>
> Yeah, in general the parent defines the bus type.
Right, if the bus that's being used isn't spi anymore, you should be
able to detect that without a property. However, the device that "left"
the spi bus is not this "adi,axi-dac" it is the adi,ad3552r. I think
this property is actually representing the bus that this adi,axi-dac is
/providing/, rather than the bus it is "consuming".
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-08-30 8:19 ` Angelo Dureghello
@ 2024-08-30 15:33 ` Conor Dooley
2024-09-02 9:32 ` Angelo Dureghello
2024-09-05 9:50 ` Nuno Sá
0 siblings, 2 replies; 54+ messages in thread
From: Conor Dooley @ 2024-08-30 15:33 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan, linux-iio, devicetree, linux-kernel, dlechner
[-- Attachment #1: Type: text/plain, Size: 4571 bytes --]
On Fri, Aug 30, 2024 at 10:19:49AM +0200, Angelo Dureghello wrote:
> Hi Conor,
>
> On 29/08/24 5:46 PM, Conor Dooley wrote:
> > On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
> > > From: Angelo Dureghello <adureghello@baylibre.com>
> > >
> > > Add bus property.
> > RFC it may be, but you do need to explain what this bus-type actually
> > describes for commenting on the suitability of the method to be
> > meaningful.
>
> thanks for the feedbacks,
>
> a "bus" is intended as a generic interface connected to the target,
> may be used from a custom IP (fpga) to communicate with the target
> device (by read/write(reg and value)) using a special custom interface.
>
> The bus could also be physically the same of some well-known existing
> interfaces (as parallel, lvds or other uncommon interfaces), but using
> an uncommon/custom protocol over it.
>
> In concrete, actually bus-type is added to the backend since the
> ad3552r DAC chip can be connected (for maximum speed) by a 5 lanes DDR
> parallel bus (interface that i named QSPI, but it's not exactly a QSPI
> as a protocol), so it's a device-specific interface.
>
> With additions in this patchset, other frontends, of course not only
> DACs, will be able to add specific busses and read/wrtie to the bus
> as needed.
>
> > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > ---
> > > Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9 +++++++++
> > > 1 file changed, 9 insertions(+)
> > >
> > > diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > index a55e9bfc66d7..a7ce72e1cd81 100644
> > > --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > @@ -38,6 +38,15 @@ properties:
> > > clocks:
> > > maxItems: 1
> > You mentioned about new compatible strings, does the one currently
> > listed in this binding support both bus types?
You didn't answer this, and there's insufficient explanation of the
"hardware" in this RFC, but I found this which is supposedly the
backend:
https://github.com/analogdevicesinc/hdl/tree/main/library/axi_ad3552r
adi,axi-dac.yaml has a single compatible, and that compatible has
nothing to do with "axi_ad3552r" as it is "adi,axi-dac-9.1.b". I would
expect either justification for reuse of the compatible, or a brand new
compatible for this backend, even if the driver can mostly be reused.
Could you please link to whatever ADI wiki has detailed information on
how this stuff works so that I can look at it to better understand the
axes of configuration here?
> >
> > Making the bus type decision based on compatible only really makes sense
> > if they're different versions of the IP, but not if they're different
> > configuration options for a given version.
> >
> > > + bus-type:
>
> DAC IP on fpga actually respects same structure and register set, except
> for a named "custom" register that may use specific bitfields depending
> on the application of the IP.
To paraphrase:
"The register map is the same, except for the bit that is different".
If ADI is shipping several different configurations of this IP for
different DACs, I'd be expecting different compatibles for each backend
to be honest.
If each DAC specific backend was to have a unique compatible, would the
type of bus used be determinable from it? Doesn't have to work for all
devices from now until the heath death of the universe, but at least for
the devices that you're currently aware of?
> > If, as you mentioned, there are multiple bus types, a non-flag property
> > does make sense. However, I am really not keen on these "forced" numerical
> > properties at all, I'd much rather see strings used here.
> > > + maxItems: 1
> > > + description: |
> > > + Configure bus type:
> > > + - 0: none
> > > + - 1: qspi
Also, re-reading the cover letter, it says "this platform driver uses a 4
lanes parallel bus, plus a clock line, similar to a qspi."
I don't think we should call this "qspi" if it is not actually qspi,
that's just confusing.
Cheers,
Conor.
> > > + enum: [0, 1]
> > > + default: 0
> > > +
> > > '#io-backend-cells':
> > > const: 0
> > >
> > > --
> > > 2.45.0.rc1
> > >
> --
> ,,, Angelo Dureghello
> :: :. BayLibre -runtime team- Developer
> :`___:
> `____:
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 2/8] iio: backend: extend features
2024-08-29 12:32 ` [PATCH RFC 2/8] iio: backend: extend features Angelo Dureghello
@ 2024-08-31 11:23 ` Jonathan Cameron
2024-09-02 14:03 ` Angelo Dureghello
0 siblings, 1 reply; 54+ messages in thread
From: Jonathan Cameron @ 2024-08-31 11:23 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Thu, 29 Aug 2024 14:32:00 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:
> From: Angelo Dureghello <adureghello@baylibre.com>
>
> Extend backend features with new calls needed later on this
> patchset from axi version of ad3552r.
>
> A bus type property has been added to the devicetree to
> inform the backend about the type of bus (interface) in use
> bu the IP.
>
> The follwoing calls are added:
>
> iio_backend_ext_sync_enable
> enable synchronize channels on external trigger
> iio_backend_ext_sync_disable
> disable synchronize channels on external trigger
> iio_backend_ddr_enable
> enable ddr bus transfer
> iio_backend_ddr_disable
> disable ddr bus transfer
> iio_backend_set_bus_mode
> select the type of bus, so that specific read / write
> operations are performed accordingly
> iio_backend_buffer_enable
> enable buffer
> iio_backend_buffer_disable
> disable buffer
> iio_backend_data_transfer_addr
> define the target register address where the DAC sample
> will be written.
> iio_backend_bus_reg_read
> generic bus read, bus-type dependent
> iio_backend_bus_read_write
> generic bus write, bus-type dependent
>
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> ---
> drivers/iio/industrialio-backend.c | 151 +++++++++++++++++++++++++++++++++++++
> include/linux/iio/backend.h | 24 ++++++
> 2 files changed, 175 insertions(+)
>
> diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
> index a52a6b61c8b5..1f60c8626be7 100644
> --- a/drivers/iio/industrialio-backend.c
> +++ b/drivers/iio/industrialio-backend.c
> @@ -718,6 +718,157 @@ static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back)
> return 0;
> }
> +
> +/**
> + * iio_backend_buffer_enable - Enable data buffering
Data buffering is a very vague term. Perhaps some more detail on what
this means?
> + * @back: Backend device
> + *
> + * RETURNS:
> + * 0 on success, negative error number on failure.
> + */
> +int iio_backend_buffer_enable(struct iio_backend *back)
> +{
> + return iio_backend_op_call(back, buffer_enable);
> +}
> +EXPORT_SYMBOL_NS_GPL(iio_backend_buffer_enable, IIO_BACKEND);
> +
> +/**
> + * iio_backend_set_buffer_disable - Disable data buffering
> + * @back: Backend device
> + *
> + * RETURNS:
> + * 0 on success, negative error number on failure.
> + */
> +int iio_backend_buffer_disable(struct iio_backend *back)
> +{
> + return iio_backend_op_call(back, buffer_disable);
> +}
> +EXPORT_SYMBOL_NS_GPL(iio_backend_buffer_disable, IIO_BACKEND);
> +
> +/**
> + * iio_backend_buffer_transfer_addr - Set data address.
> + * @back: Backend device
> + * @chan_address: Channel register address
Run scripts/kernel-doc on this and fix the errors (parameter name is
wrong). W=1 builds might also point the simpler ones out.
> + *
> + * Some devices may need to inform the backend about an address/location
> + * where to read or write the data.
I'd drop the 'location' part unless this gets used later because you
are referring register address above.
> + *
> + * RETURNS:
> + * 0 on success, negative error number on failure.
> + */
> +int iio_backend_data_transfer_addr(struct iio_backend *back, u32 address)
> +{
> + return iio_backend_op_call(back, data_transfer_addr, address);
> +}
> +EXPORT_SYMBOL_NS_GPL(iio_backend_data_transfer_addr, IIO_BACKEND);
> +
> +/**
> + * iio_backend_bus_reg_read - Read from the interface bus
> + * @back: Backend device
> + * @reg: Register valule
> + * @val: Pointer to register value
> + * @size: Size, in bytes
> + *
> + * A backend may operate on a specific interface with a related bus.
> + * Read from the interface bus.
So this is effectively routing control plane data through the offloaded
bus? That sounds a lot more like a conventional bus than IIO backend.
Perhaps it should be presented as that with the IIO device attached
to that bus? I don't fully understand what is wired up here.
> + *
> + * RETURNS:
> + * 0 on success, negative error number on failure.
> + */
> +int iio_backend_bus_reg_read(struct iio_backend *back,
> + u32 reg, void *val, size_t size)
> +{
> + if (!size)
> + return -EINVAL;
> +
> + return iio_backend_op_call(back, bus_reg_read, reg, val, size);
> +}
> +EXPORT_SYMBOL_NS_GPL(iio_backend_bus_reg_read, IIO_BACKEND);
> +
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 3/8] iio: backend adi-axi-dac: backend features
2024-08-29 12:32 ` [PATCH RFC 3/8] iio: backend adi-axi-dac: backend features Angelo Dureghello
@ 2024-08-31 11:34 ` Jonathan Cameron
2024-09-02 16:04 ` Angelo Dureghello
0 siblings, 1 reply; 54+ messages in thread
From: Jonathan Cameron @ 2024-08-31 11:34 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Thu, 29 Aug 2024 14:32:01 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:
> From: Angelo Dureghello <adureghello@baylibre.com>
>
> Extend DAC backend with new features required for the AXI driver
> version for the a3552r DAC.
>
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
Hi Angelo
Minor comments inline.
>
> static int axi_dac_enable(struct iio_backend *back)
> @@ -460,7 +493,13 @@ static int axi_dac_data_source_set(struct iio_backend *back, unsigned int chan,
> case IIO_BACKEND_EXTERNAL:
> return regmap_update_bits(st->regmap,
> AXI_DAC_REG_CHAN_CNTRL_7(chan),
> - AXI_DAC_DATA_SEL, AXI_DAC_DATA_DMA);
> + AXI_DAC_DATA_SEL,
> + AXI_DAC_DATA_DMA);
Unrelated change. If you want to change this, separate patch.
> + case IIO_BACKEND_INTERNAL_RAMP_16:
> + return regmap_update_bits(st->regmap,
> + AXI_DAC_REG_CHAN_CNTRL_7(chan),
> + AXI_DAC_DATA_SEL,
> + AXI_DAC_DATA_INTERNAL_RAMP_16);
> default:
> return -EINVAL;
> }
> @@ -518,9 +557,204 @@ static int axi_dac_reg_access(struct iio_backend *back, unsigned int reg,
> return regmap_write(st->regmap, reg, writeval);
> }
>
> +
> +static int axi_dac_bus_reg_write(struct iio_backend *back,
> + u32 reg, void *val, size_t size)
Maybe just pass an unsigned int for val?
So follow what regmap does? You will still need the size, but it
will just be configuration related rather than affecting the type
of val.
> +{
> + struct axi_dac_state *st = iio_backend_get_priv(back);
> +
> + if (!st->bus_type)
> + return -EOPNOTSUPP;
> +
> + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
As below, I'd use a switch and factor out this block as a separate
bus specific function.
> + int ret;
> + u32 ival;
> +
> + if (size != 1 && size != 2)
> + return -EINVAL;
> +
> + switch (size) {
> + case 1:
> + ival = FIELD_PREP(AXI_DAC_DATA_WR_8, *(u8 *)val);
> + break;
> + case 2:
> + ival = FIELD_PREP(AXI_DAC_DATA_WR_16, *(u16 *)val);
> + break;
> + default:
> + return -EINVAL;
Hopefully compiler won't need this and the above. I'd drop the size != 1..
check in favour of just doing it in this switch.
> + }
> +
> + ret = regmap_write(st->regmap, AXI_DAC_CNTRL_DATA_WR, ival);
> + if (ret)
> + return ret;
> +
> + /*
> + * Both REG_CNTRL_2 and AXI_DAC_CNTRL_DATA_WR need to know
> + * the data size. So keeping data size control here only,
> + * since data size is mandatory for to the current transfer.
> + * DDR state handled separately by specific backend calls,
> + * generally all raw register writes are SDR.
> + */
> + if (size == 1)
> + ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_2,
> + AXI_DAC_SYMB_8B);
> + else
> + ret = regmap_clear_bits(st->regmap, AXI_DAC_REG_CNTRL_2,
> + AXI_DAC_SYMB_8B);
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
> + AXI_DAC_ADDRESS,
> + FIELD_PREP(AXI_DAC_ADDRESS, reg));
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
> + AXI_DAC_TRANSFER_DATA,
> + AXI_DAC_TRANSFER_DATA);
> + if (ret)
> + return ret;
> +
> + ret = regmap_read_poll_timeout(st->regmap,
> + AXI_DAC_REG_CUSTOM_CTRL, ival,
> + ival & AXI_DAC_TRANSFER_DATA,
> + 10, 100 * KILO);
> + if (ret)
> + return ret;
> +
> + return regmap_clear_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
> + AXI_DAC_TRANSFER_DATA);
> + }
> +
> + return -EINVAL;
> +}
> +
> +static int axi_dac_bus_reg_read(struct iio_backend *back,
> + u32 reg, void *val, size_t size)
As for write, I'd just use an unsigned int * for val like
regmap does.
> +{
> + struct axi_dac_state *st = iio_backend_get_priv(back);
> +
> + if (!st->bus_type)
> + return -EOPNOTSUPP;
> +
> + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
It got mentioned in binding review but if this isn't QSPI, even
if similar don't call it that.
Maybe use a switch from the start give it will make sense
anyway the moment there is a second bus type.
I'd be tempted to factor the rest of this block out.
I guess expectation is we'll see more bus types so that factoring
out will be needed soon anyway.
> + int ret;
> + u32 bval;
u32 bval = 0;
> +
> + if (size != 1 && size != 2)
> + return -EINVAL;
> +
> + bval = 0;
> + ret = axi_dac_bus_reg_write(back,
> + AXI_DAC_RD_ADDR(reg), &bval, size);
Ugly wrap. Move more stuff on to first line.
> + if (ret)
> + return ret;
> +
> + ret = regmap_read_poll_timeout(st->regmap, AXI_DAC_UI_STATUS,
> + bval, bval != AXI_DAC_BUSY,
> + 10, 100);
> + if (ret)
> + return ret;
> +
> + return regmap_read(st->regmap, AXI_DAC_CNTRL_DATA_RD, val);
> + }
> +
> + return -EINVAL;
> +}
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi
2024-08-29 12:31 [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Angelo Dureghello
` (7 preceding siblings ...)
2024-08-29 12:32 ` [PATCH RFC 8/8] iio: ABI: add DAC sysfs synchronous_mode parameter Angelo Dureghello
@ 2024-08-31 11:38 ` Jonathan Cameron
2024-09-03 8:34 ` Angelo Dureghello
8 siblings, 1 reply; 54+ messages in thread
From: Jonathan Cameron @ 2024-08-31 11:38 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Thu, 29 Aug 2024 14:31:58 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:
> Hi, asking for comments for this patchset, that is mostly
> ready, at least feature-complete and functionally tested.
>
> I am introducing ad3552r-axi variant, controlled from a fpga-based
> AXI IP, as a platform driver, using the DAC backend. The patchset is
> actually based on linux-iio, since some needed DAC backend features
> was already there on that repo only, still to be merged in mainline.
>
> Comments i would like to ask are:
>
> - i added some devicetree bindings inside current ad3552r yaml,
> device is the same, so i wouldn't create a different yaml file.
Agreed. If same device, it's usually better to keep it in one file.
>
> - if it's ok adding the bus-type property in the DAC backend:
> actually, this platform driver uses a 4 lanes parallel bus, plus
> a clock line, similar to a qspi. This to read an write registers
> and as well to send samples at double data rate. Other DAC may
> need "parallel" or "lvds" in the future.
If it is for register read + write as well, sounds to me like you need
to treat this as a new bus type, possibly then combined with a
backend, or something similar to spi offload?
What bus does this currently sit on in your DT bindings?
(add an example)
>
> - adding the bus-type property vs. a boolean property vs. adding
> a new compatible string.
>
> - how external synchronization should be handled. Actually, i added
> 2 backend calls to enable or disable this external trigger.
That seems more or less fine. Is there any control over the external
trigger? This feels a bit like some of the complex stm32 hardware
triggers in that a 'hidden' trigger is being enabled.
If it is controllable or selectable (between say a PWM or an external
pin) then you may need to be careful how to expose that control.
>
> - is a read-only sampling-frequency useful ?
Yes. If it is easy to provide, it can be useful to userspace to
allow it to figure out how much data to expect.
Jonathan
>
> Thanks a lot for your feedbacks.
>
> To: Lars-Peter Clausen <lars@metafoo.de>
> To: Michael Hennerich <Michael.Hennerich@analog.com>
> To: Nuno Sá <nuno.sa@analog.com>
> To: Jonathan Cameron <jic23@kernel.org>
> To: Rob Herring <robh@kernel.org>
> To: Krzysztof Kozlowski <krzk+dt@kernel.org>
> To: Conor Dooley <conor+dt@kernel.org>
> To: Olivier Moysan <olivier.moysan@foss.st.com>
> Cc: linux-iio@vger.kernel.org
> Cc: devicetree@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: dlechner@baylibre.com
>
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> ---
> Angelo Dureghello (8):
> dt-bindings: iio: dac: ad3552r: add io-backend property
> iio: backend: extend features
> iio: backend adi-axi-dac: backend features
> dt-bindings: iio: dac: add adi axi-dac bus property
> iio: dac: ad3552r: changes to use FIELD_PREP
> iio: dac: ad3552r: extract common code (no changes in behavior intended)
> iio: dac: ad3552r: add axi platform driver
> iio: ABI: add DAC sysfs synchronous_mode parameter
>
> Documentation/ABI/testing/sysfs-bus-iio-dac | 7 +
> .../devicetree/bindings/iio/dac/adi,ad3552r.yaml | 39 +-
> .../devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9 +
> drivers/iio/dac/Kconfig | 11 +
> drivers/iio/dac/Makefile | 3 +-
> drivers/iio/dac/ad3552r-axi.c | 572 +++++++++++++++++++++
> drivers/iio/dac/ad3552r-common.c | 163 ++++++
> drivers/iio/dac/ad3552r.c | 394 +++-----------
> drivers/iio/dac/ad3552r.h | 199 +++++++
> drivers/iio/dac/adi-axi-dac.c | 250 ++++++++-
> drivers/iio/industrialio-backend.c | 151 ++++++
> include/linux/iio/backend.h | 24 +
> 12 files changed, 1494 insertions(+), 328 deletions(-)
> ---
> base-commit: 7ccb2c2db44572deadb795c4637273cdabbe8b66
> change-id: 20240829-wip-bl-ad3552r-axi-v0-b1e379c986d3
>
> Best regards,
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 5/8] iio: dac: ad3552r: changes to use FIELD_PREP
2024-08-29 12:32 ` [PATCH RFC 5/8] iio: dac: ad3552r: changes to use FIELD_PREP Angelo Dureghello
@ 2024-08-31 11:48 ` Jonathan Cameron
2024-09-02 16:15 ` Angelo Dureghello
0 siblings, 1 reply; 54+ messages in thread
From: Jonathan Cameron @ 2024-08-31 11:48 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Thu, 29 Aug 2024 14:32:03 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:
> From: Angelo Dureghello <adureghello@baylibre.com>
>
> Changes to use FIELD_PREP, so that driver-specific ad3552r_field_prep
> is removed. Variables (arrays) that was used to call ad3552r_field_prep
> are removerd too.
removed
LGTM
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 7/8] iio: dac: ad3552r: add axi platform driver
2024-08-29 12:32 ` [PATCH RFC 7/8] iio: dac: ad3552r: add axi platform driver Angelo Dureghello
@ 2024-08-31 12:13 ` Jonathan Cameron
2024-09-03 8:17 ` Angelo Dureghello
0 siblings, 1 reply; 54+ messages in thread
From: Jonathan Cameron @ 2024-08-31 12:13 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Thu, 29 Aug 2024 14:32:05 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:
> From: Angelo Dureghello <adureghello@baylibre.com>
>
> Add support for ad3552r AXI DAC IP version.
>
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
Hi Angelo
To me this feels like the interface is much closer to SPI + SPI offload
than to a conventional IIO backend on the basis it carries the configuration
path as well.
Can we see if it can be fitted into that model? You will need to define
a new bus type etc for it but should be fairly simple given constrained
setup (at least today!)
That will resolve a bunch of questions around the binding as well.
Jonathan
> diff --git a/drivers/iio/dac/ad3552r-axi.c b/drivers/iio/dac/ad3552r-axi.c
> new file mode 100644
> index 000000000000..98e5da08c973
> --- /dev/null
> +++ b/drivers/iio/dac/ad3552r-axi.c
> @@ -0,0 +1,572 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Analog Devices AD3552R
> + * Digital to Analog converter driver, AXI DAC backend version
> + *
> + * Copyright 2024 Analog Devices Inc.
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/delay.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/backend.h>
> +#include <linux/of.h>
Why? Probably want mod_devicetable.h
> +#include <linux/platform_device.h>
> +#include <linux/units.h>
> +static int ad3552r_axi_update_scan_mode(struct iio_dev *indio_dev,
> + const unsigned long *active_scan_mask)
> +{
> + struct ad3552r_axi_state *st = iio_priv(indio_dev);
> +
> + st->active_scan_mask = *active_scan_mask;
We probably want another accessor for this, but for now that variable
can still be read from iio_dev->active_scan_mask so no need
for the copy here (and hence no need for this callback).
> +
> + return 0;
> +}
> +
> +static int ad3552r_axi_buffer_postenable(struct iio_dev *indio_dev)
> +{
> + struct ad3552r_axi_state *st = iio_priv(indio_dev);
> + struct iio_backend_data_fmt fmt = {
> + .type = IIO_BACKEND_DATA_UNSIGNED
> + };
> + int loop_len, val, err;
> +
> + /* Inform DAC chip to switch into DDR mode */
> + err = axi3552r_qspi_update_reg_bits(st->back,
> + AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
> + AD3552R_MASK_SPI_CONFIG_DDR,
> + AD3552R_MASK_SPI_CONFIG_DDR, 1);
> + if (err)
> + return err;
> +
> + /* Inform DAC IP to go for DDR mode from now on */
> + err = iio_backend_ddr_enable(st->back);
> + if (err)
> + goto exit_err;
> +
> + switch (st->active_scan_mask) {
> + case AD3552R_CH0_ACTIVE:
> + st->single_channel = true;
> + loop_len = AD3552R_STREAM_2BYTE_LOOP;
> + val = AD3552R_REG_ADDR_CH_DAC_16B(0);
> + break;
> + case AD3552R_CH1_ACTIVE:
> + st->single_channel = true;
> + loop_len = AD3552R_STREAM_2BYTE_LOOP;
> + val = AD3552R_REG_ADDR_CH_DAC_16B(1);
> + break;
> + case AD3552R_CH0_CH1_ACTIVE:
> + st->single_channel = false;
> + loop_len = AD3552R_STREAM_4BYTE_LOOP;
> + val = AD3552R_REG_ADDR_CH_DAC_16B(1);
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + err = iio_backend_bus_reg_write(st->back, AD3552R_REG_ADDR_STREAM_MODE,
> + &loop_len, 1);
> + if (err)
> + goto exit_err;
> +
> + iio_backend_data_transfer_addr(st->back, val);
err = ?
> + if (err)
> + goto exit_err;
> + /*
> + * The EXT_SYNC is mandatory in the CN0585 project where 2 instances
> + * of the IP are in the design and they need to generate the signals
> + * synchronized.
> + *
> + * Note: in first IP implementations CONFIG EXT_SYNC (RO) can be 0,
> + * but EXT_SYMC is anabled anyway.
> + */
> +
> + if (st->synced_transfer == AD3552R_EXT_SYNC_ARM)
> + err = iio_backend_ext_sync_enable(st->back);
> + else
> + err = iio_backend_ext_sync_disable(st->back);
> + if (err)
> + goto exit_err_sync;
> +
> + err = iio_backend_data_format_set(st->back, 0, &fmt);
> + if (err)
> + goto exit_err;
> +
> + err = iio_backend_buffer_enable(st->back);
> + if (!err)
> + return 0;
Keep the good path inline as that's more idiomatic and what a reviewers
eyes expect to see.
if (err)
goto exit_err_sync;
return 0;
> +
> +exit_err_sync:
> + iio_backend_ext_sync_disable(st->back);
> +
> +exit_err:
> + axi3552r_qspi_update_reg_bits(st->back,
> + AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
> + AD3552R_MASK_SPI_CONFIG_DDR,
> + 0, 1);
> +
> + iio_backend_ddr_disable(st->back);
> +
> + return err;
> +}
> +
> +static int ad3552r_axi_buffer_predisable(struct iio_dev *indio_dev)
> +{
> + struct ad3552r_axi_state *st = iio_priv(indio_dev);
> + int err;
> +
> + err = iio_backend_buffer_disable(st->back);
> + if (err)
> + return err;
> +
> + /* Inform DAC to set in DDR mode */
You set the DAC to ddr mode whilst disabling it? That seems backwards.
> + err = axi3552r_qspi_update_reg_bits(st->back,
> + AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
> + AD3552R_MASK_SPI_CONFIG_DDR,
> + 0, 1);
> + if (err)
> + return err;
> +
> + return iio_backend_ddr_disable(st->back);
> +}
> +
> +
> +static int ad3552r_axi_reset(struct ad3552r_axi_state *st)
> +{
> + int err;
> +
> + /* AXI reset performed by backend enable() */
This comment is confusing given it's in a function called
axi_reset and you don't do the backend enable() here.
So how is this resetting the AXI bus (or is that name
referring to the fpga IP?)
> +
> + st->reset_gpio = devm_gpiod_get_optional(st->dev,
> + "reset", GPIOD_OUT_LOW);
> + if (IS_ERR(st->reset_gpio))
> + return PTR_ERR(st->reset_gpio);
> +
> + if (st->reset_gpio) {
> + gpiod_set_value_cansleep(st->reset_gpio, 1);
> + fsleep(10);
> + gpiod_set_value_cansleep(st->reset_gpio, 0);
> + } else {
> + err = axi3552r_qspi_update_reg_bits(st->back,
> + AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
> + AD3552R_MASK_SOFTWARE_RESET,
> + AD3552R_MASK_SOFTWARE_RESET, 1);
> + if (err)
> + return err;
> + }
> + msleep(100);
> +
> + return 0;
> +}
> +
> +static int ad3552r_axi_setup(struct ad3552r_axi_state *st)
> +{
> + struct fwnode_handle *child __free(fwnode_handle) = NULL;
> + u8 gs_p, gs_n;
> + s16 goffs;
> + u16 id, rfb, reg = 0, offset = 0;
Generally don't mix assignment and non assignment stuff on online.
Fine to have them all not assigned or all assigned, but a mix
tends to lead to people missing one in the middle that is
different.
u16 id, rfb,
u16 reg = 0, offset = 0;
> + u32 val, range;
> + int err;
> +
> + err = ad3552r_axi_reset(st);
> + if (err)
> + return err;
> +
> + err = iio_backend_ddr_disable(st->back);
> + if (err)
> + return err;
> +
> + val = AD3552R_SCRATCH_PAD_TEST_VAL1;
> + err = iio_backend_bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
> + &val, 1);
as per earlier review, I'd pass an unsigned int instead of a void *
Then you can avoid the dance with a local variable.
> + if (err)
> + return err;
> +
> + err = iio_backend_bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
> + &val, 1);
> + if (err)
> + return err;
> +
> + if (val != AD3552R_SCRATCH_PAD_TEST_VAL1) {
> + dev_err(st->dev,
> + "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n",
> + AD3552R_SCRATCH_PAD_TEST_VAL1, val);
> + return -EIO;
> + }
> +
> + val = AD3552R_SCRATCH_PAD_TEST_VAL2;
> + err = iio_backend_bus_reg_write(st->back,
> + AD3552R_REG_ADDR_SCRATCH_PAD,
> + &val, 1);
> + if (err)
> + return err;
> +
> + err = iio_backend_bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
> + &val, 1);
> + if (err)
> + return err;
> +
> + if (val != AD3552R_SCRATCH_PAD_TEST_VAL2) {
> + dev_err(st->dev,
> + "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n",
> + AD3552R_SCRATCH_PAD_TEST_VAL2, val);
> + return -EIO;
> + }
> +
> + err = iio_backend_bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_L,
> + &val, 1);
> + if (err)
> + return err;
> +
> + id = val;
> + mdelay(100);
Document this delay as it's odd to need a gap whilst reading ID registers.
> +
> + err = iio_backend_bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_H,
> + &val, 1);
> + if (err)
> + return err;
> +
> + id |= val << 8;
> + if (id != AD3552R_ID) {
> + dev_err(st->dev, "Chip ID mismatch. Expected 0x%x, Read 0x%x\n",
> + AD3552R_ID, id);
Print an message only on this. We want to enable fallback dt compatibles for
future devices on old kernels, so we can't require a match on a WHOAMI type register.
We can put a message in the log though to give us a hint if that fallback
compatible is wrong.
> + return -ENODEV;
> + }
> +
> + st->chip_id = id;
This is usually a bad sign. It is much more extensible for a driver to at
this point 'pick' between a set of per device type structures that encode
all the difference between device variants. So good to do that from
the start. Lots of old drivers do it this way, but we've learnt over the years
that it becomes steadily more messy over time as a driver supports more and
more devices.
I guess the existing driver is doing it this way though so maybe that's
a refactor for another day.
> +
> + val = AD3552R_REF_INIT;
> + err = iio_backend_bus_reg_write(st->back,
> + AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
> + &val, 1);
> + if (err)
> + return err;
> +
> + val = AD3552R_TRANSFER_INIT;
> + err = iio_backend_bus_reg_write(st->back,
> + AD3552R_REG_ADDR_TRANSFER_REGISTER,
> + &val, 1);
> + if (err)
> + return err;
> +
> + err = iio_backend_data_source_set(st->back, 0, IIO_BACKEND_EXTERNAL);
> + if (err)
> + return err;
> +
> + err = iio_backend_data_source_set(st->back, 1, IIO_BACKEND_EXTERNAL);
> + if (err)
> + return err;
> +
> + err = ad3552r_get_ref_voltage(st->dev, &val);
> + if (err)
> + return err;
> +
> + err = axi3552r_qspi_update_reg_bits(st->back,
> + AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
> + AD3552R_MASK_REFERENCE_VOLTAGE_SEL,
> + val, 1);
> + if (err)
> + return err;
> +
> + err = ad3552r_get_drive_strength(st->dev, &val);
> + if (!err) {
> + err = axi3552r_qspi_update_reg_bits(st->back,
> + AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
> + AD3552R_MASK_SDO_DRIVE_STRENGTH,
> + val, 1);
> + if (err)
> + return err;
> + }
> +
> + child = device_get_named_child_node(st->dev, "channel");
> + if (!child)
> + return -EINVAL;
> +
> + err = ad3552r_get_output_range(st->dev, st->chip_id, child, &range);
> + if (!err)
> + return ad3552r_axi_set_output_range(st, range);
> +
> + if (err != -ENOENT)
> + return err;
> +
> + /* Try to get custom range */
> + err = ad3552r_get_custom_gain(st->dev, child,
> + &gs_p, &gs_n, &rfb, &goffs);
> + if (err)
> + return err;
> +
> + ad3552r_calc_custom_gain(gs_p, gs_n, goffs, ®);
> +
> + offset = abs((s32)goffs);
> +
> + err = iio_backend_bus_reg_write(st->back,
> + AD3552R_REG_ADDR_CH_OFFSET(0),
> + &offset, 1);
> + if (err)
> + return dev_err_probe(st->dev, err,
> + "Error writing register\n");
> +
> + err = iio_backend_bus_reg_write(st->back,
> + AD3552R_REG_ADDR_CH_OFFSET(1),
> + &offset, 1);
> + if (err)
> + return dev_err_probe(st->dev, err,
> + "Error writing register\n");
> +
> + err = iio_backend_bus_reg_write(st->back,
> + AD3552R_REG_ADDR_CH_GAIN(0),
> + ®, 1);
> + if (err)
> + return dev_err_probe(st->dev, err,
> + "Error writing register\n");
> +
> + err = iio_backend_bus_reg_write(st->back,
> + AD3552R_REG_ADDR_CH_GAIN(1),
> + ®, 1);
> + if (err)
> + return dev_err_probe(st->dev, err,
> + "Error writing register\n");
> +
> + return 0;
> +}
> +
> +static const struct iio_buffer_setup_ops ad3552r_axi_buffer_setup_ops = {
> + .postenable = ad3552r_axi_buffer_postenable,
> + .predisable = ad3552r_axi_buffer_predisable,
> +};
> +
> +static const char *const synchronous_mode_status[] = {
> + [AD3552R_NO_SYNC] = "no_sync",
> + [AD3552R_EXT_SYNC_ARM] = "ext_sync_arm",
I'll comment on this in the ABI docs patch.
> +};
> +
> +static const struct iio_enum ad3552r_synchronous_mode_enum = {
> + .items = synchronous_mode_status,
> + .num_items = ARRAY_SIZE(synchronous_mode_status),
> + .get = ad3552r_get_synchronous_mode_status,
> + .set = ad3552r_set_synchronous_mode_status,
> +};
> +
> +static const struct iio_chan_spec_ext_info ad3552r_axi_ext_info[] = {
> + IIO_ENUM("synchronous_mode", IIO_SHARED_BY_TYPE,
> + &ad3552r_synchronous_mode_enum),
> + IIO_ENUM_AVAILABLE("synchronous_mode", IIO_SHARED_BY_TYPE,
> + &ad3552r_synchronous_mode_enum),
> + {},
{ }
I'm not blanket fixing this case yet (unlikely the ID ones) but
generally it's nice to not have a comma after a 'null' terminator
entry as adding anything after it would be a bug.
> +};
> +
> +#define AD3552R_CHANNEL(ch) { \
> + .type = IIO_VOLTAGE, \
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> + .info_mask_shared_by_all = (((ch) == 0) ? \
> + BIT(IIO_CHAN_INFO_SAMP_FREQ) : 0), \
If it's shared by all it should be set for all.
The core code will only create one attr as a result.
Technically it's not a 'bug' to not do this but the semantics
are wrong if you set something that is for all channels on only
one of them, so if there are other drivers doing this that I've
missed we should clean that up.
> + .output = 1, \
> + .indexed = 1, \
> + .channel = (ch), \
> + .scan_index = (ch), \
> + .scan_type = { \
> + .sign = 'u', \
> + .realbits = 16, \
> + .storagebits = 16, \
> + .shift = 0, \
Zero shift is the 'obvious' default, so need to specify it in this
case.
> + .endianness = IIO_BE, \
> + }, \
> + .ext_info = ad3552r_axi_ext_info, \
> +}
> +
> +static const struct of_device_id ad3552r_axi_of_id[] = {
> + { .compatible = "adi,ad3552r" },
> + {}
Trivial, but I'm trying to standardize formats of these in IIO on
{ }
> +};
> +MODULE_DEVICE_TABLE(of, ad3552r_axi_of_id);
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 8/8] iio: ABI: add DAC sysfs synchronous_mode parameter
2024-08-29 12:32 ` [PATCH RFC 8/8] iio: ABI: add DAC sysfs synchronous_mode parameter Angelo Dureghello
@ 2024-08-31 12:15 ` Jonathan Cameron
0 siblings, 0 replies; 54+ messages in thread
From: Jonathan Cameron @ 2024-08-31 12:15 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Thu, 29 Aug 2024 14:32:06 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:
> From: Angelo Dureghello <adureghello@baylibre.com>
>
> Some DACs as ad3552r need a synchronous mode setting, adding
> this parameter for ad3552r and for future use on other DACs,
> if needed.
>
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> ---
> Documentation/ABI/testing/sysfs-bus-iio-dac | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-dac b/Documentation/ABI/testing/sysfs-bus-iio-dac
> index 810eaac5533c..a3012baf90b3 100644
> --- a/Documentation/ABI/testing/sysfs-bus-iio-dac
> +++ b/Documentation/ABI/testing/sysfs-bus-iio-dac
> @@ -59,3 +59,10 @@ Description:
> multiple predefined symbols. Each symbol corresponds to a different
> output, denoted as out_voltageY_rawN, where N is the integer value
> of the symbol. Writing an integer value N will select out_voltageY_rawN.
> +
> +What: /sys/bus/iio/devices/iio:deviceX/out_voltage_synchronous_mode
> +KernelVersion: 6.13
> +Contact: linux-iio@vger.kernel.org
> +Description:
> + This attribute allows a specific synchronization mode, mainly
> + intended for DACs where multiple synchronization methods are available.
If we accept this it needs an _available as well + a list of the possible modes.
That list must be exhaustive across all devices so we constrain these appropriately.
However, right now this seems more like picking a trigger, or potentially the PWM
feeds into the spi offload code than anything else, so I'm not sure we want to
introduce new ABI for it.
Jonathan
>
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-08-30 15:33 ` Conor Dooley
@ 2024-09-02 9:32 ` Angelo Dureghello
2024-09-03 19:18 ` Jonathan Cameron
2024-09-06 9:04 ` Conor Dooley
2024-09-05 9:50 ` Nuno Sá
1 sibling, 2 replies; 54+ messages in thread
From: Angelo Dureghello @ 2024-09-02 9:32 UTC (permalink / raw)
To: Conor Dooley
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan, linux-iio, devicetree, linux-kernel, dlechner
Hi Conor,
On 30/08/24 5:33 PM, Conor Dooley wrote:
> On Fri, Aug 30, 2024 at 10:19:49AM +0200, Angelo Dureghello wrote:
>> Hi Conor,
>>
>> On 29/08/24 5:46 PM, Conor Dooley wrote:
>>> On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
>>>> From: Angelo Dureghello <adureghello@baylibre.com>
>>>>
>>>> Add bus property.
>>> RFC it may be, but you do need to explain what this bus-type actually
>>> describes for commenting on the suitability of the method to be
>>> meaningful.
>> thanks for the feedbacks,
>>
>> a "bus" is intended as a generic interface connected to the target,
>> may be used from a custom IP (fpga) to communicate with the target
>> device (by read/write(reg and value)) using a special custom interface.
>>
>> The bus could also be physically the same of some well-known existing
>> interfaces (as parallel, lvds or other uncommon interfaces), but using
>> an uncommon/custom protocol over it.
>>
>> In concrete, actually bus-type is added to the backend since the
>> ad3552r DAC chip can be connected (for maximum speed) by a 5 lanes DDR
>> parallel bus (interface that i named QSPI, but it's not exactly a QSPI
>> as a protocol), so it's a device-specific interface.
>>
>> With additions in this patchset, other frontends, of course not only
>> DACs, will be able to add specific busses and read/wrtie to the bus
>> as needed.
>>
>>>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>>>> ---
>>>> Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9 +++++++++
>>>> 1 file changed, 9 insertions(+)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>> index a55e9bfc66d7..a7ce72e1cd81 100644
>>>> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>> @@ -38,6 +38,15 @@ properties:
>>>> clocks:
>>>> maxItems: 1
>>> You mentioned about new compatible strings, does the one currently
>>> listed in this binding support both bus types?
> You didn't answer this, and there's insufficient explanation of the
> "hardware" in this RFC, but I found this which is supposedly the
> backend:
> https://github.com/analogdevicesinc/hdl/tree/main/library/axi_ad3552r
> adi,axi-dac.yaml has a single compatible, and that compatible has
> nothing to do with "axi_ad3552r" as it is "adi,axi-dac-9.1.b". I would
> expect either justification for reuse of the compatible, or a brand new
> compatible for this backend, even if the driver can mostly be reused.
>
> Could you please link to whatever ADI wiki has detailed information on
> how this stuff works so that I can look at it to better understand the
> axes of configuration here?
https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
that has same structure and register set of the generic ADI AXI-DAC IP:
https://wiki.analog.com/resources/fpga/docs/axi_dac_ip
>>> Making the bus type decision based on compatible only really makes sense
>>> if they're different versions of the IP, but not if they're different
>>> configuration options for a given version.
>>>
>>>> + bus-type:
>> DAC IP on fpga actually respects same structure and register set, except
>> for a named "custom" register that may use specific bitfields depending
>> on the application of the IP.
> To paraphrase:
> "The register map is the same, except for the bit that is different".
> If ADI is shipping several different configurations of this IP for
> different DACs, I'd be expecting different compatibles for each backend
> to be honest
i am still quite new to this fpga-based implementations, at least for how
such IPs are actually interfacing to the linux subsystem, so i may miss
some point.
About the "adi,axi-dac-9.1.b" compatible, the generic DAC IP register set
is mostly the same structure of this ad3552r IP (links above), except for
bitfields in the DAC_CUSTOM_CTRL register.
My choice for now was to add a bus-type property.
Not an HDL expert, but i think a different bus means, from an hardware
point of
view, a different IP in terms of internal fpga circuitry, even if not as a
register-set.
> .
> If each DAC specific backend was to have a unique compatible, would the
> type of bus used be determinable from it? Doesn't have to work for all
> devices from now until the heath death of the universe, but at least for
> the devices that you're currently aware of?
>
>>> If, as you mentioned, there are multiple bus types, a non-flag property
>>> does make sense. However, I am really not keen on these "forced" numerical
>>> properties at all, I'd much rather see strings used here.
>>>> + maxItems: 1
>>>> + description: |
>>>> + Configure bus type:
>>>> + - 0: none
>>>> + - 1: qspi
> Also, re-reading the cover letter, it says "this platform driver uses a 4
> lanes parallel bus, plus a clock line, similar to a qspi."
> I don't think we should call this "qspi" if it is not actually qspi,
> that's just confusing.
Agree, name should be something different.
> Cheers,
> Conor.
Thanks,
regards,
Angelo
>>>> + enum: [0, 1]
>>>> + default: 0
>>>> +
>>>> '#io-backend-cells':
>>>> const: 0
>>>>
>>>> --
>>>> 2.45.0.rc1
>>>>
>> --
>> ,,, Angelo Dureghello
>> :: :. BayLibre -runtime team- Developer
>> :`___:
>> `____:
>>
--
,,, Angelo Dureghello
:: :. BayLibre -runtime team- Developer
:`___:
`____:
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 2/8] iio: backend: extend features
2024-08-31 11:23 ` Jonathan Cameron
@ 2024-09-02 14:03 ` Angelo Dureghello
2024-09-03 19:11 ` Jonathan Cameron
0 siblings, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-09-02 14:03 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
Hi Jonathan,
thanks for the feedbacks,
On 31/08/24 1:23 PM, Jonathan Cameron wrote:
> On Thu, 29 Aug 2024 14:32:00 +0200
> Angelo Dureghello <adureghello@baylibre.com> wrote:
>
>> From: Angelo Dureghello <adureghello@baylibre.com>
>>
>> Extend backend features with new calls needed later on this
>> patchset from axi version of ad3552r.
>>
>> A bus type property has been added to the devicetree to
>> inform the backend about the type of bus (interface) in use
>> bu the IP.
>>
>> The follwoing calls are added:
>>
>> iio_backend_ext_sync_enable
>> enable synchronize channels on external trigger
>> iio_backend_ext_sync_disable
>> disable synchronize channels on external trigger
>> iio_backend_ddr_enable
>> enable ddr bus transfer
>> iio_backend_ddr_disable
>> disable ddr bus transfer
>> iio_backend_set_bus_mode
>> select the type of bus, so that specific read / write
>> operations are performed accordingly
>> iio_backend_buffer_enable
>> enable buffer
>> iio_backend_buffer_disable
>> disable buffer
>> iio_backend_data_transfer_addr
>> define the target register address where the DAC sample
>> will be written.
>> iio_backend_bus_reg_read
>> generic bus read, bus-type dependent
>> iio_backend_bus_read_write
>> generic bus write, bus-type dependent
>>
>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>> ---
>> drivers/iio/industrialio-backend.c | 151 +++++++++++++++++++++++++++++++++++++
>> include/linux/iio/backend.h | 24 ++++++
>> 2 files changed, 175 insertions(+)
>>
>> diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
>> index a52a6b61c8b5..1f60c8626be7 100644
>> --- a/drivers/iio/industrialio-backend.c
>> +++ b/drivers/iio/industrialio-backend.c
>> @@ -718,6 +718,157 @@ static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back)
>> return 0;
>> }
>
>> +
>> +/**
>> + * iio_backend_buffer_enable - Enable data buffering
> Data buffering is a very vague term. Perhaps some more detail on what
> this means?
for this DAC IP, it is the dma buffer where i write the samples,
for other non-dac frontends may be something different, so i kept it
generic. Not sure what a proper name may be, maybe
"Enable optional data buffer" ?
>> + * @back: Backend device
>> + *
>> + * RETURNS:
>> + * 0 on success, negative error number on failure.
>> + */
>> +int iio_backend_buffer_enable(struct iio_backend *back)
>> +{
>> + return iio_backend_op_call(back, buffer_enable);
>> +}
>> +EXPORT_SYMBOL_NS_GPL(iio_backend_buffer_enable, IIO_BACKEND);
>> +
>> +/**
>> + * iio_backend_set_buffer_disable - Disable data buffering
>> + * @back: Backend device
>> + *
>> + * RETURNS:
>> + * 0 on success, negative error number on failure.
>> + */
>> +int iio_backend_buffer_disable(struct iio_backend *back)
>> +{
>> + return iio_backend_op_call(back, buffer_disable);
>> +}
>> +EXPORT_SYMBOL_NS_GPL(iio_backend_buffer_disable, IIO_BACKEND);
>> +
>> +/**
>> + * iio_backend_buffer_transfer_addr - Set data address.
>> + * @back: Backend device
>> + * @chan_address: Channel register address
> Run scripts/kernel-doc on this and fix the errors (parameter name is
> wrong). W=1 builds might also point the simpler ones out.
ack, done
>> + *
>> + * Some devices may need to inform the backend about an address/location
>> + * where to read or write the data.
> I'd drop the 'location' part unless this gets used later because you
> are referring register address above.
ack, done
>> + *
>> + * RETURNS:
>> + * 0 on success, negative error number on failure.
>> + */
>> +int iio_backend_data_transfer_addr(struct iio_backend *back, u32 address)
>> +{
>> + return iio_backend_op_call(back, data_transfer_addr, address);
>> +}
>> +EXPORT_SYMBOL_NS_GPL(iio_backend_data_transfer_addr, IIO_BACKEND);
>> +
>> +/**
>> + * iio_backend_bus_reg_read - Read from the interface bus
>> + * @back: Backend device
>> + * @reg: Register valule
>> + * @val: Pointer to register value
>> + * @size: Size, in bytes
>> + *
>> + * A backend may operate on a specific interface with a related bus.
>> + * Read from the interface bus.
> So this is effectively routing control plane data through the offloaded
> bus? That sounds a lot more like a conventional bus than IIO backend.
> Perhaps it should be presented as that with the IIO device attached
> to that bus? I don't fully understand what is wired up here.
>
Mainly, an IP may include a bus as 16bit parallel, or LVDS, or similar
to QSPI as in my case (ad3552r).
In particular, the bus is physically as a QSPI bus, but the data format
over it is a bit different.
So ad3552r needs this 5 lanes bus + double data rate to reach 33MUPS.
https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
>> + *
>> + * RETURNS:
>> + * 0 on success, negative error number on failure.
>> + */
>> +int iio_backend_bus_reg_read(struct iio_backend *back,
>> + u32 reg, void *val, size_t size)
>> +{
>> + if (!size)
>> + return -EINVAL;
>> +
>> + return iio_backend_op_call(back, bus_reg_read, reg, val, size);
>> +}
>> +EXPORT_SYMBOL_NS_GPL(iio_backend_bus_reg_read, IIO_BACKEND);
>> +
Thanks a lot,
regards,
Angelo
--
,,, Angelo Dureghello
:: :. BayLibre -runtime team- Developer
:`___:
`____:
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 3/8] iio: backend adi-axi-dac: backend features
2024-08-31 11:34 ` Jonathan Cameron
@ 2024-09-02 16:04 ` Angelo Dureghello
2024-09-03 19:16 ` Jonathan Cameron
0 siblings, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-09-02 16:04 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On 31/08/24 1:34 PM, Jonathan Cameron wrote:
> On Thu, 29 Aug 2024 14:32:01 +0200
> Angelo Dureghello <adureghello@baylibre.com> wrote:
>
>> From: Angelo Dureghello <adureghello@baylibre.com>
>>
>> Extend DAC backend with new features required for the AXI driver
>> version for the a3552r DAC.
>>
>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> Hi Angelo
> Minor comments inline.
>>
>> static int axi_dac_enable(struct iio_backend *back)
>> @@ -460,7 +493,13 @@ static int axi_dac_data_source_set(struct iio_backend *back, unsigned int chan,
>> case IIO_BACKEND_EXTERNAL:
>> return regmap_update_bits(st->regmap,
>> AXI_DAC_REG_CHAN_CNTRL_7(chan),
>> - AXI_DAC_DATA_SEL, AXI_DAC_DATA_DMA);
>> + AXI_DAC_DATA_SEL,
>> + AXI_DAC_DATA_DMA);
> Unrelated change. If you want to change this, separate patch.
Thanks, fixed.
>
>> + case IIO_BACKEND_INTERNAL_RAMP_16:
>> + return regmap_update_bits(st->regmap,
>> + AXI_DAC_REG_CHAN_CNTRL_7(chan),
>> + AXI_DAC_DATA_SEL,
>> + AXI_DAC_DATA_INTERNAL_RAMP_16);
>> default:
>> return -EINVAL;
>> }
>> @@ -518,9 +557,204 @@ static int axi_dac_reg_access(struct iio_backend *back, unsigned int reg,
>> return regmap_write(st->regmap, reg, writeval);
>> }
>>
>> +
>> +static int axi_dac_bus_reg_write(struct iio_backend *back,
>> + u32 reg, void *val, size_t size)
> Maybe just pass an unsigned int for val?
> So follow what regmap does? You will still need the size, but it
> will just be configuration related rather than affecting the type
> of val.
>
void * was used since data size in the future may vary depending
on the bus physical interface.
Actually, a reg bus write involves several AXI regmap operations.
>
>> +{
>> + struct axi_dac_state *st = iio_backend_get_priv(back);
>> +
>> + if (!st->bus_type)
>> + return -EOPNOTSUPP;
>> +
>> + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
> As below, I'd use a switch and factor out this block as a separate
> bus specific function.
Ok, changed.
>
>> + int ret;
>> + u32 ival;
>> +
>> + if (size != 1 && size != 2)
>> + return -EINVAL;
>> +
>> + switch (size) {
>> + case 1:
>> + ival = FIELD_PREP(AXI_DAC_DATA_WR_8, *(u8 *)val);
>> + break;
>> + case 2:
>> + ival = FIELD_PREP(AXI_DAC_DATA_WR_16, *(u16 *)val);
>> + break;
>> + default:
>> + return -EINVAL;
> Hopefully compiler won't need this and the above. I'd drop the size != 1..
> check in favour of just doing it in this switch.
>
sure, done.
>> + }
>> +
>> + ret = regmap_write(st->regmap, AXI_DAC_CNTRL_DATA_WR, ival);
>> + if (ret)
>> + return ret;
>> +
>> + /*
>> + * Both REG_CNTRL_2 and AXI_DAC_CNTRL_DATA_WR need to know
>> + * the data size. So keeping data size control here only,
>> + * since data size is mandatory for to the current transfer.
>> + * DDR state handled separately by specific backend calls,
>> + * generally all raw register writes are SDR.
>> + */
>> + if (size == 1)
>> + ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_2,
>> + AXI_DAC_SYMB_8B);
>> + else
>> + ret = regmap_clear_bits(st->regmap, AXI_DAC_REG_CNTRL_2,
>> + AXI_DAC_SYMB_8B);
>> + if (ret)
>> + return ret;
>> +
>> + ret = regmap_update_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
>> + AXI_DAC_ADDRESS,
>> + FIELD_PREP(AXI_DAC_ADDRESS, reg));
>> + if (ret)
>> + return ret;
>> +
>> + ret = regmap_update_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
>> + AXI_DAC_TRANSFER_DATA,
>> + AXI_DAC_TRANSFER_DATA);
>> + if (ret)
>> + return ret;
>> +
>> + ret = regmap_read_poll_timeout(st->regmap,
>> + AXI_DAC_REG_CUSTOM_CTRL, ival,
>> + ival & AXI_DAC_TRANSFER_DATA,
>> + 10, 100 * KILO);
>> + if (ret)
>> + return ret;
>> +
>> + return regmap_clear_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
>> + AXI_DAC_TRANSFER_DATA);
>> + }
>> +
>> + return -EINVAL;
>> +}
>> +
>> +static int axi_dac_bus_reg_read(struct iio_backend *back,
>> + u32 reg, void *val, size_t size)
> As for write, I'd just use an unsigned int * for val like
> regmap does.
Ok, so initial choice was unsigned int, further thinking of
possible future busses drive the choice to void *.
Let me know, i can switch to unsigned int in case.
>
>
>> +{
>> + struct axi_dac_state *st = iio_backend_get_priv(back);
>> +
>> + if (!st->bus_type)
>> + return -EOPNOTSUPP;
>> +
>> + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
> It got mentioned in binding review but if this isn't QSPI, even
> if similar don't call it that.
It's a bit difficult to find a different name, physically,
it is a QSPI, 4 lanes + clock + cs, and datasheet is naming it Quad SPI.
But looking the data protocol, it's a bit different.
QSPI has instruction, address and data.
Here we have just ADDR and DATA.
What about ADI_QSPI ?
> Maybe use a switch from the start give it will make sense
> anyway the moment there is a second bus type.
ok, used a switch in the write too.
> I'd be tempted to factor the rest of this block out.
> I guess expectation is we'll see more bus types so that factoring
> out will be needed soon anyway.
>
>
>> + int ret;
>> + u32 bval;
> u32 bval = 0;
>> +
>> + if (size != 1 && size != 2)
>> + return -EINVAL;
>> +
>> + bval = 0;
>> + ret = axi_dac_bus_reg_write(back,
>> + AXI_DAC_RD_ADDR(reg), &bval, size);
> Ugly wrap. Move more stuff on to first line.
ok done.
>
>> + if (ret)
>> + return ret;
>> +
>> + ret = regmap_read_poll_timeout(st->regmap, AXI_DAC_UI_STATUS,
>> + bval, bval != AXI_DAC_BUSY,
>> + 10, 100);
>> + if (ret)
>> + return ret;
>> +
>> + return regmap_read(st->regmap, AXI_DAC_CNTRL_DATA_RD, val);
>> + }
>> +
>> + return -EINVAL;
>> +}
Thanks,
regards,
Angelo
--
,,, Angelo Dureghello
:: :. BayLibre -runtime team- Developer
:`___:
`____:
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 5/8] iio: dac: ad3552r: changes to use FIELD_PREP
2024-08-31 11:48 ` Jonathan Cameron
@ 2024-09-02 16:15 ` Angelo Dureghello
2024-09-03 19:19 ` Jonathan Cameron
0 siblings, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-09-02 16:15 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On 31/08/24 1:48 PM, Jonathan Cameron wrote:
> On Thu, 29 Aug 2024 14:32:03 +0200
> Angelo Dureghello <adureghello@baylibre.com> wrote:
>
>> From: Angelo Dureghello <adureghello@baylibre.com>
>>
>> Changes to use FIELD_PREP, so that driver-specific ad3552r_field_prep
>> is removed. Variables (arrays) that was used to call ad3552r_field_prep
>> are removerd too.
> removed
fixed thanks.
>
> LGTM
Regards,
Angelo
--
,,, Angelo Dureghello
:: :. BayLibre -runtime team- Developer
:`___:
`____:
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 7/8] iio: dac: ad3552r: add axi platform driver
2024-08-31 12:13 ` Jonathan Cameron
@ 2024-09-03 8:17 ` Angelo Dureghello
2024-09-03 19:28 ` Jonathan Cameron
0 siblings, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-09-03 8:17 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
Hi Jonathan,
On 31/08/24 2:13 PM, Jonathan Cameron wrote:
> On Thu, 29 Aug 2024 14:32:05 +0200
> Angelo Dureghello <adureghello@baylibre.com> wrote:
>
>> From: Angelo Dureghello <adureghello@baylibre.com>
>>
>> Add support for ad3552r AXI DAC IP version.
>>
>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> Hi Angelo
>
> To me this feels like the interface is much closer to SPI + SPI offload
> than to a conventional IIO backend on the basis it carries the configuration
> path as well.
>
> Can we see if it can be fitted into that model? You will need to define
> a new bus type etc for it but should be fairly simple given constrained
> setup (at least today!)
>
> That will resolve a bunch of questions around the binding as well.
thanks for all the feedbacks.
I see, spi offload may have more sense but as of now looks like moving to
AXI SPI engine instead of AXI DAC would require quite a lot of work from the
ADI HDL guys and also then, for me some work reworking all this stuff.
From an initial discussion with Nuno and David, we was oriented to use the
iio backend for the current HDL, so at least for this chip at this stage
would
be good, if possible, to stay this way.
> Jonathan
>
>> diff --git a/drivers/iio/dac/ad3552r-axi.c b/drivers/iio/dac/ad3552r-axi.c
>> new file mode 100644
>> index 000000000000..98e5da08c973
>> --- /dev/null
>> +++ b/drivers/iio/dac/ad3552r-axi.c
>> @@ -0,0 +1,572 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Analog Devices AD3552R
>> + * Digital to Analog converter driver, AXI DAC backend version
>> + *
>> + * Copyright 2024 Analog Devices Inc.
>> + */
>> +
>> +#include <linux/bitfield.h>
>> +#include <linux/delay.h>
>> +#include <linux/gpio/consumer.h>
>> +#include <linux/iio/buffer.h>
>> +#include <linux/iio/backend.h>
>> +#include <linux/of.h>
> Why? Probably want mod_devicetable.h
with mod_devicetable.h in place of of.h i get
drivers/iio/dac/ad3552r-axi.c:272:9: error: cleanup argument not a function
struct fwnode_handle *child __free(fwnode_handle) = NULL;
^~~~~~~~~~~~~
>> +#include <linux/platform_device.h>
>> +#include <linux/units.h>
>
>> +static int ad3552r_axi_update_scan_mode(struct iio_dev *indio_dev,
>> + const unsigned long *active_scan_mask)
>> +{
>> + struct ad3552r_axi_state *st = iio_priv(indio_dev);
>> +
>> + st->active_scan_mask = *active_scan_mask;
> We probably want another accessor for this, but for now that variable
> can still be read from iio_dev->active_scan_mask so no need
> for the copy here (and hence no need for this callback).
thanks a lot, removed the accessor, not needed
>> +
>> + return 0;
>> +}
>> +
>> +static int ad3552r_axi_buffer_postenable(struct iio_dev *indio_dev)
>> +{
>> + struct ad3552r_axi_state *st = iio_priv(indio_dev);
>> + struct iio_backend_data_fmt fmt = {
>> + .type = IIO_BACKEND_DATA_UNSIGNED
>> + };
>> + int loop_len, val, err;
>> +
>> + /* Inform DAC chip to switch into DDR mode */
>> + err = axi3552r_qspi_update_reg_bits(st->back,
>> + AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
>> + AD3552R_MASK_SPI_CONFIG_DDR,
>> + AD3552R_MASK_SPI_CONFIG_DDR, 1);
>> + if (err)
>> + return err;
>> +
>> + /* Inform DAC IP to go for DDR mode from now on */
>> + err = iio_backend_ddr_enable(st->back);
>> + if (err)
>> + goto exit_err;
>> +
>> + switch (st->active_scan_mask) {
>> + case AD3552R_CH0_ACTIVE:
>> + st->single_channel = true;
>> + loop_len = AD3552R_STREAM_2BYTE_LOOP;
>> + val = AD3552R_REG_ADDR_CH_DAC_16B(0);
>> + break;
>> + case AD3552R_CH1_ACTIVE:
>> + st->single_channel = true;
>> + loop_len = AD3552R_STREAM_2BYTE_LOOP;
>> + val = AD3552R_REG_ADDR_CH_DAC_16B(1);
>> + break;
>> + case AD3552R_CH0_CH1_ACTIVE:
>> + st->single_channel = false;
>> + loop_len = AD3552R_STREAM_4BYTE_LOOP;
>> + val = AD3552R_REG_ADDR_CH_DAC_16B(1);
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + err = iio_backend_bus_reg_write(st->back, AD3552R_REG_ADDR_STREAM_MODE,
>> + &loop_len, 1);
>> + if (err)
>> + goto exit_err;
>> +
>> + iio_backend_data_transfer_addr(st->back, val);
> err = ?
thanks, fixed.
>> + if (err)
>> + goto exit_err;
>> + /*
>> + * The EXT_SYNC is mandatory in the CN0585 project where 2 instances
>> + * of the IP are in the design and they need to generate the signals
>> + * synchronized.
>> + *
>> + * Note: in first IP implementations CONFIG EXT_SYNC (RO) can be 0,
>> + * but EXT_SYMC is anabled anyway.
>> + */
>> +
>> + if (st->synced_transfer == AD3552R_EXT_SYNC_ARM)
>> + err = iio_backend_ext_sync_enable(st->back);
>> + else
>> + err = iio_backend_ext_sync_disable(st->back);
>> + if (err)
>> + goto exit_err_sync;
>> +
>> + err = iio_backend_data_format_set(st->back, 0, &fmt);
>> + if (err)
>> + goto exit_err;
>> +
>> + err = iio_backend_buffer_enable(st->back);
>> + if (!err)
>> + return 0;
> Keep the good path inline as that's more idiomatic and what a reviewers
> eyes expect to see.
>
> if (err)
> goto exit_err_sync;
>
> return 0;
ok, fixed
>> +
>> +exit_err_sync:
>> + iio_backend_ext_sync_disable(st->back);
>> +
>> +exit_err:
>> + axi3552r_qspi_update_reg_bits(st->back,
>> + AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
>> + AD3552R_MASK_SPI_CONFIG_DDR,
>> + 0, 1);
>> +
>> + iio_backend_ddr_disable(st->back);
>> +
>> + return err;
>> +}
>> +
>> +static int ad3552r_axi_buffer_predisable(struct iio_dev *indio_dev)
>> +{
>> + struct ad3552r_axi_state *st = iio_priv(indio_dev);
>> + int err;
>> +
>> + err = iio_backend_buffer_disable(st->back);
>> + if (err)
>> + return err;
>> +
>> + /* Inform DAC to set in DDR mode */
> You set the DAC to ddr mode whilst disabling it? That seems backwards.
Thanks, wrong comment, i am setting back to SDR here, comment fixed.
>> + err = axi3552r_qspi_update_reg_bits(st->back,
>> + AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
>> + AD3552R_MASK_SPI_CONFIG_DDR,
>> + 0, 1);
>> + if (err)
>> + return err;
>> +
>> + return iio_backend_ddr_disable(st->back);
>> +}
>> +
>> +
>> +static int ad3552r_axi_reset(struct ad3552r_axi_state *st)
>> +{
>> + int err;
>> +
>> + /* AXI reset performed by backend enable() */
> This comment is confusing given it's in a function called
> axi_reset and you don't do the backend enable() here.
> So how is this resetting the AXI bus (or is that name
> referring to the fpga IP?)
Ok, i removed the comment.
Actually, the IP reset is performed by the backend "enable"
while this function resets the target chip.
>
>> +
>> + st->reset_gpio = devm_gpiod_get_optional(st->dev,
>> + "reset", GPIOD_OUT_LOW);
>> + if (IS_ERR(st->reset_gpio))
>> + return PTR_ERR(st->reset_gpio);
>> +
>> + if (st->reset_gpio) {
>> + gpiod_set_value_cansleep(st->reset_gpio, 1);
>> + fsleep(10);
>> + gpiod_set_value_cansleep(st->reset_gpio, 0);
>> + } else {
>> + err = axi3552r_qspi_update_reg_bits(st->back,
>> + AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
>> + AD3552R_MASK_SOFTWARE_RESET,
>> + AD3552R_MASK_SOFTWARE_RESET, 1);
>> + if (err)
>> + return err;
>> + }
>> + msleep(100);
>> +
>> + return 0;
>> +}
>> +
>> +static int ad3552r_axi_setup(struct ad3552r_axi_state *st)
>> +{
>> + struct fwnode_handle *child __free(fwnode_handle) = NULL;
>> + u8 gs_p, gs_n;
>> + s16 goffs;
>> + u16 id, rfb, reg = 0, offset = 0;
> Generally don't mix assignment and non assignment stuff on online.
> Fine to have them all not assigned or all assigned, but a mix
> tends to lead to people missing one in the middle that is
> different.
>
> u16 id, rfb,
> u16 reg = 0, offset = 0;
Ok, done.
>
>> + u32 val, range;
>> + int err;
>> +
>> + err = ad3552r_axi_reset(st);
>> + if (err)
>> + return err;
>> +
>> + err = iio_backend_ddr_disable(st->back);
>> + if (err)
>> + return err;
>> +
>> + val = AD3552R_SCRATCH_PAD_TEST_VAL1;
>> + err = iio_backend_bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
>> + &val, 1);
> as per earlier review, I'd pass an unsigned int instead of a void *
> Then you can avoid the dance with a local variable.
void * was chosen thinking to future busses, please let me know if
it can stay this way.
>> + if (err)
>> + return err;
>> +
>> + err = iio_backend_bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
>> + &val, 1);
>> + if (err)
>> + return err;
>> +
>> + if (val != AD3552R_SCRATCH_PAD_TEST_VAL1) {
>> + dev_err(st->dev,
>> + "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n",
>> + AD3552R_SCRATCH_PAD_TEST_VAL1, val);
>> + return -EIO;
>> + }
>> +
>> + val = AD3552R_SCRATCH_PAD_TEST_VAL2;
>> + err = iio_backend_bus_reg_write(st->back,
>> + AD3552R_REG_ADDR_SCRATCH_PAD,
>> + &val, 1);
>> + if (err)
>> + return err;
>> +
>> + err = iio_backend_bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
>> + &val, 1);
>> + if (err)
>> + return err;
>> +
>> + if (val != AD3552R_SCRATCH_PAD_TEST_VAL2) {
>> + dev_err(st->dev,
>> + "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n",
>> + AD3552R_SCRATCH_PAD_TEST_VAL2, val);
>> + return -EIO;
>> + }
>> +
>> + err = iio_backend_bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_L,
>> + &val, 1);
>> + if (err)
>> + return err;
>> +
>> + id = val;
>> + mdelay(100);
> Document this delay as it's odd to need a gap whilst reading ID registers.
I ported that delay from a previous testing driver, but i verified
it is not needed, so i removed it.
>> +
>> + err = iio_backend_bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_H,
>> + &val, 1);
>> + if (err)
>> + return err;
>> +
>> + id |= val << 8;
>> + if (id != AD3552R_ID) {
>> + dev_err(st->dev, "Chip ID mismatch. Expected 0x%x, Read 0x%x\n",
>> + AD3552R_ID, id);
> Print an message only on this. We want to enable fallback dt compatibles for
> future devices on old kernels, so we can't require a match on a WHOAMI type register.
> We can put a message in the log though to give us a hint if that fallback
> compatible is wrong.
>
ok, done.
>> + return -ENODEV;
>> + }
>> +
>> + st->chip_id = id;
> This is usually a bad sign. It is much more extensible for a driver to at
> this point 'pick' between a set of per device type structures that encode
> all the difference between device variants. So good to do that from
> the start. Lots of old drivers do it this way, but we've learnt over the years
> that it becomes steadily more messy over time as a driver supports more and
> more devices.
>
> I guess the existing driver is doing it this way though so maybe that's
> a refactor for another day.
Thanks, ok, i reworked the same way as ad3552r.c (spi) since i'll have
to add
other variants soon.
>
>> +
>> + val = AD3552R_REF_INIT;
>> + err = iio_backend_bus_reg_write(st->back,
>> + AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
>> + &val, 1);
>> + if (err)
>> + return err;
>> +
>> + val = AD3552R_TRANSFER_INIT;
>> + err = iio_backend_bus_reg_write(st->back,
>> + AD3552R_REG_ADDR_TRANSFER_REGISTER,
>> + &val, 1);
>> + if (err)
>> + return err;
>> +
>> + err = iio_backend_data_source_set(st->back, 0, IIO_BACKEND_EXTERNAL);
>> + if (err)
>> + return err;
>> +
>> + err = iio_backend_data_source_set(st->back, 1, IIO_BACKEND_EXTERNAL);
>> + if (err)
>> + return err;
>> +
>> + err = ad3552r_get_ref_voltage(st->dev, &val);
>> + if (err)
>> + return err;
>> +
>> + err = axi3552r_qspi_update_reg_bits(st->back,
>> + AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
>> + AD3552R_MASK_REFERENCE_VOLTAGE_SEL,
>> + val, 1);
>> + if (err)
>> + return err;
>> +
>> + err = ad3552r_get_drive_strength(st->dev, &val);
>> + if (!err) {
>> + err = axi3552r_qspi_update_reg_bits(st->back,
>> + AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
>> + AD3552R_MASK_SDO_DRIVE_STRENGTH,
>> + val, 1);
>> + if (err)
>> + return err;
>> + }
>> +
>> + child = device_get_named_child_node(st->dev, "channel");
>> + if (!child)
>> + return -EINVAL;
>> +
>> + err = ad3552r_get_output_range(st->dev, st->chip_id, child, &range);
>> + if (!err)
>> + return ad3552r_axi_set_output_range(st, range);
>> +
>> + if (err != -ENOENT)
>> + return err;
>> +
>> + /* Try to get custom range */
>> + err = ad3552r_get_custom_gain(st->dev, child,
>> + &gs_p, &gs_n, &rfb, &goffs);
>> + if (err)
>> + return err;
>> +
>> + ad3552r_calc_custom_gain(gs_p, gs_n, goffs, ®);
>> +
>> + offset = abs((s32)goffs);
>> +
>> + err = iio_backend_bus_reg_write(st->back,
>> + AD3552R_REG_ADDR_CH_OFFSET(0),
>> + &offset, 1);
>> + if (err)
>> + return dev_err_probe(st->dev, err,
>> + "Error writing register\n");
>> +
>> + err = iio_backend_bus_reg_write(st->back,
>> + AD3552R_REG_ADDR_CH_OFFSET(1),
>> + &offset, 1);
>> + if (err)
>> + return dev_err_probe(st->dev, err,
>> + "Error writing register\n");
>> +
>> + err = iio_backend_bus_reg_write(st->back,
>> + AD3552R_REG_ADDR_CH_GAIN(0),
>> + ®, 1);
>> + if (err)
>> + return dev_err_probe(st->dev, err,
>> + "Error writing register\n");
>> +
>> + err = iio_backend_bus_reg_write(st->back,
>> + AD3552R_REG_ADDR_CH_GAIN(1),
>> + ®, 1);
>> + if (err)
>> + return dev_err_probe(st->dev, err,
>> + "Error writing register\n");
>> +
>> + return 0;
>> +}
>> +
>> +static const struct iio_buffer_setup_ops ad3552r_axi_buffer_setup_ops = {
>> + .postenable = ad3552r_axi_buffer_postenable,
>> + .predisable = ad3552r_axi_buffer_predisable,
>> +};
>> +
>> +static const char *const synchronous_mode_status[] = {
>> + [AD3552R_NO_SYNC] = "no_sync",
>> + [AD3552R_EXT_SYNC_ARM] = "ext_sync_arm",
> I'll comment on this in the ABI docs patch.
>
>> +};
>> +
>> +static const struct iio_enum ad3552r_synchronous_mode_enum = {
>> + .items = synchronous_mode_status,
>> + .num_items = ARRAY_SIZE(synchronous_mode_status),
>> + .get = ad3552r_get_synchronous_mode_status,
>> + .set = ad3552r_set_synchronous_mode_status,
>> +};
>> +
>> +static const struct iio_chan_spec_ext_info ad3552r_axi_ext_info[] = {
>> + IIO_ENUM("synchronous_mode", IIO_SHARED_BY_TYPE,
>> + &ad3552r_synchronous_mode_enum),
>> + IIO_ENUM_AVAILABLE("synchronous_mode", IIO_SHARED_BY_TYPE,
>> + &ad3552r_synchronous_mode_enum),
>> + {},
> { }
>
> I'm not blanket fixing this case yet (unlikely the ID ones) but
> generally it's nice to not have a comma after a 'null' terminator
> entry as adding anything after it would be a bug.
ok, done
>
>
>> +};
>> +
>> +#define AD3552R_CHANNEL(ch) { \
>> + .type = IIO_VOLTAGE, \
>> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
>> + .info_mask_shared_by_all = (((ch) == 0) ? \
>> + BIT(IIO_CHAN_INFO_SAMP_FREQ) : 0), \
> If it's shared by all it should be set for all.
> The core code will only create one attr as a result.
>
> Technically it's not a 'bug' to not do this but the semantics
> are wrong if you set something that is for all channels on only
> one of them, so if there are other drivers doing this that I've
> missed we should clean that up.
Ok, i set it for all so.
>
>
>> + .output = 1, \
>> + .indexed = 1, \
>> + .channel = (ch), \
>> + .scan_index = (ch), \
>> + .scan_type = { \
>> + .sign = 'u', \
>> + .realbits = 16, \
>> + .storagebits = 16, \
>> + .shift = 0, \
> Zero shift is the 'obvious' default, so need to specify it in this
> case.
ok, fixed
>
>> + .endianness = IIO_BE, \
>> + }, \
>> + .ext_info = ad3552r_axi_ext_info, \
>> +}
>> +
>> +static const struct of_device_id ad3552r_axi_of_id[] = {
>> + { .compatible = "adi,ad3552r" },
>> + {}
> Trivial, but I'm trying to standardize formats of these in IIO on
> { }
ok, done
>> +};
Thanks a lot,
regards,
Angelo
--
,,, Angelo Dureghello
:: :. BayLibre -runtime team- Developer
:`___:
`____:
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi
2024-08-31 11:38 ` [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Jonathan Cameron
@ 2024-09-03 8:34 ` Angelo Dureghello
2024-09-03 16:17 ` David Lechner
0 siblings, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-09-03 8:34 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
Hi Jonathan and all,
On 31/08/24 1:38 PM, Jonathan Cameron wrote:
> On Thu, 29 Aug 2024 14:31:58 +0200
> Angelo Dureghello <adureghello@baylibre.com> wrote:
>
>> Hi, asking for comments for this patchset, that is mostly
>> ready, at least feature-complete and functionally tested.
>>
>> I am introducing ad3552r-axi variant, controlled from a fpga-based
>> AXI IP, as a platform driver, using the DAC backend. The patchset is
>> actually based on linux-iio, since some needed DAC backend features
>> was already there on that repo only, still to be merged in mainline.
>>
>> Comments i would like to ask are:
>>
>> - i added some devicetree bindings inside current ad3552r yaml,
>> device is the same, so i wouldn't create a different yaml file.
> Agreed. If same device, it's usually better to keep it in one file.
>
>> - if it's ok adding the bus-type property in the DAC backend:
>> actually, this platform driver uses a 4 lanes parallel bus, plus
>> a clock line, similar to a qspi. This to read an write registers
>> and as well to send samples at double data rate. Other DAC may
>> need "parallel" or "lvds" in the future.
> If it is for register read + write as well, sounds to me like you need
> to treat this as a new bus type, possibly then combined with a
> backend, or something similar to spi offload?
>
> What bus does this currently sit on in your DT bindings?
> (add an example)
&amba {
ref_clk: clk@44B00000 {
compatible = "adi,axi-clkgen-2.00.a";
reg = <0x44B00000 0x10000>;
#clock-cells = <0>;
clocks = <&clkc 15>, <&clkc 15>;
clock-names = "s_axi_aclk", "clkin1";
clock-output-names = "ref_clk";
};
dac_tx_dma: dma-controller@0x44a30000 {
compatible = "adi,axi-dmac-1.00.a";
reg = <0x44a30000 0x10000>;
#dma-cells = <1>;
interrupt-parent = <&intc>;
interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clkc 15>;
adi,channels {
#size-cells = <0>;
#address-cells = <1>;
dma-channel@0 {
reg = <0>;
adi,source-bus-width = <32>;
adi,source-bus-type = <0>;
adi,destination-bus-width = <32>;
adi,destination-bus-type = <1>;
};
};
};
backend: controller@44a70000 {
compatible = "adi,axi-dac-9.1.b";
reg = <0x44a70000 0x1000>;
dmas = <&dac_tx_dma 0>;
dma-names = "tx";
#io-backend-cells = <0>;
clocks = <&ref_clk>;
bus-type = <1>; /* IIO QSPI */
};
axi-ad3552r {
compatible = "adi,ad3552r";
reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
io-backends = <&backend>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
adi,output-range-microvolt = <(-10000000) (10000000)>;
};
};
};
>
>> - adding the bus-type property vs. a boolean property vs. adding
>> a new compatible string.
>>
>> - how external synchronization should be handled. Actually, i added
>> 2 backend calls to enable or disable this external trigger.
> That seems more or less fine. Is there any control over the external
> trigger? This feels a bit like some of the complex stm32 hardware
> triggers in that a 'hidden' trigger is being enabled.
> If it is controllable or selectable (between say a PWM or an external
> pin) then you may need to be careful how to expose that control.
>
Actually this synchronization is needed since ADI is going to use this
IP also in a a dual layout, so the 2 IPs needs to have an external
synchronization by a signal. But as default synch is not enabled.
Yes, it looks like a trigger. I can check if i can do this in a different
way.
>> - is a read-only sampling-frequency useful ?
> Yes. If it is easy to provide, it can be useful to userspace to
> allow it to figure out how much data to expect.
>
> Jonathan
So this is the last RFC mail i am handling,
trying to wrap up the open points:
- about DAC backend or spi offload, if possible i would not change approach
at this stage, i worked on the provided HDL.
- about reg_read/write, let me know if the void * can stay
- about external synch, i am trying to see if i can do this by a trigger.
Just as a note, Nuno and David was involved helping me on this,
so will add them as co-developers.
Thanks a lot,
Regards,
Angelo
>> Thanks a lot for your feedbacks.
>>
>> To: Lars-Peter Clausen <lars@metafoo.de>
>> To: Michael Hennerich <Michael.Hennerich@analog.com>
>> To: Nuno Sá <nuno.sa@analog.com>
>> To: Jonathan Cameron <jic23@kernel.org>
>> To: Rob Herring <robh@kernel.org>
>> To: Krzysztof Kozlowski <krzk+dt@kernel.org>
>> To: Conor Dooley <conor+dt@kernel.org>
>> To: Olivier Moysan <olivier.moysan@foss.st.com>
>> Cc: linux-iio@vger.kernel.org
>> Cc: devicetree@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Cc: dlechner@baylibre.com
>>
>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>> ---
>> Angelo Dureghello (8):
>> dt-bindings: iio: dac: ad3552r: add io-backend property
>> iio: backend: extend features
>> iio: backend adi-axi-dac: backend features
>> dt-bindings: iio: dac: add adi axi-dac bus property
>> iio: dac: ad3552r: changes to use FIELD_PREP
>> iio: dac: ad3552r: extract common code (no changes in behavior intended)
>> iio: dac: ad3552r: add axi platform driver
>> iio: ABI: add DAC sysfs synchronous_mode parameter
>>
>> Documentation/ABI/testing/sysfs-bus-iio-dac | 7 +
>> .../devicetree/bindings/iio/dac/adi,ad3552r.yaml | 39 +-
>> .../devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9 +
>> drivers/iio/dac/Kconfig | 11 +
>> drivers/iio/dac/Makefile | 3 +-
>> drivers/iio/dac/ad3552r-axi.c | 572 +++++++++++++++++++++
>> drivers/iio/dac/ad3552r-common.c | 163 ++++++
>> drivers/iio/dac/ad3552r.c | 394 +++-----------
>> drivers/iio/dac/ad3552r.h | 199 +++++++
>> drivers/iio/dac/adi-axi-dac.c | 250 ++++++++-
>> drivers/iio/industrialio-backend.c | 151 ++++++
>> include/linux/iio/backend.h | 24 +
>> 12 files changed, 1494 insertions(+), 328 deletions(-)
>> ---
>> base-commit: 7ccb2c2db44572deadb795c4637273cdabbe8b66
>> change-id: 20240829-wip-bl-ad3552r-axi-v0-b1e379c986d3
>>
>> Best regards,
--
,,, Angelo Dureghello
:: :. BayLibre -runtime team- Developer
:`___:
`____:
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi
2024-09-03 8:34 ` Angelo Dureghello
@ 2024-09-03 16:17 ` David Lechner
2024-09-03 19:39 ` Jonathan Cameron
0 siblings, 1 reply; 54+ messages in thread
From: David Lechner @ 2024-09-03 16:17 UTC (permalink / raw)
To: Angelo Dureghello, Jonathan Cameron
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel
On 9/3/24 3:34 AM, Angelo Dureghello wrote:
> Hi Jonathan and all,
>
>
> On 31/08/24 1:38 PM, Jonathan Cameron wrote:
>> On Thu, 29 Aug 2024 14:31:58 +0200
>> Angelo Dureghello <adureghello@baylibre.com> wrote:
>>
>>> Hi, asking for comments for this patchset, that is mostly
>>> ready, at least feature-complete and functionally tested.
>>>
>>> I am introducing ad3552r-axi variant, controlled from a fpga-based
>>> AXI IP, as a platform driver, using the DAC backend. The patchset is
>>> actually based on linux-iio, since some needed DAC backend features
>>> was already there on that repo only, still to be merged in mainline.
>>>
>>> Comments i would like to ask are:
>>>
>>> - i added some devicetree bindings inside current ad3552r yaml,
>>> device is the same, so i wouldn't create a different yaml file.
>> Agreed. If same device, it's usually better to keep it in one file.
>>
>>> - if it's ok adding the bus-type property in the DAC backend:
>>> actually, this platform driver uses a 4 lanes parallel bus, plus
>>> a clock line, similar to a qspi. This to read an write registers
>>> and as well to send samples at double data rate. Other DAC may
>>> need "parallel" or "lvds" in the future.
>> If it is for register read + write as well, sounds to me like you need
>> to treat this as a new bus type, possibly then combined with a
>> backend, or something similar to spi offload?
>>
>> What bus does this currently sit on in your DT bindings?
>> (add an example)
>
>
> &amba {
>
> ref_clk: clk@44B00000 {
> compatible = "adi,axi-clkgen-2.00.a";
> reg = <0x44B00000 0x10000>;
> #clock-cells = <0>;
> clocks = <&clkc 15>, <&clkc 15>;
> clock-names = "s_axi_aclk", "clkin1";
> clock-output-names = "ref_clk";
> };
>
> dac_tx_dma: dma-controller@0x44a30000 {
> compatible = "adi,axi-dmac-1.00.a";
> reg = <0x44a30000 0x10000>;
> #dma-cells = <1>;
> interrupt-parent = <&intc>;
> interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
> clocks = <&clkc 15>;
>
> adi,channels {
> #size-cells = <0>;
> #address-cells = <1>;
>
> dma-channel@0 {
> reg = <0>;
> adi,source-bus-width = <32>;
> adi,source-bus-type = <0>;
> adi,destination-bus-width = <32>;
> adi,destination-bus-type = <1>;
> };
> };
> };
>
> backend: controller@44a70000 {
> compatible = "adi,axi-dac-9.1.b";
> reg = <0x44a70000 0x1000>;
> dmas = <&dac_tx_dma 0>;
> dma-names = "tx";
> #io-backend-cells = <0>;
> clocks = <&ref_clk>;
> bus-type = <1>; /* IIO QSPI */
> };
>
> axi-ad3552r {
> compatible = "adi,ad3552r";
> reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
> io-backends = <&backend>;
> #address-cells = <1>;
> #size-cells = <0>;
> channel@0 {
> reg = <0>;
> adi,output-range-microvolt = <(-10000000) (10000000)>;
> };
> };
Shouldn't the axi-ad3552r node be one level higher since it isn't
a memory-mapped device, but rather an external chip?
But based on the other feedback we got in this series and some
#devicetree IRC chat here is an alternate binding suggestion we
could consider.
First, even though the FPGA IP block for use with AD3225R uses
the same register map as the AXI DAC IP block, some of the
registers behave differently, so it makes sense to have a
different compatible string rather than using the bus-type
property to tell the difference between the two IP blocks.
There are likely more differences than just the bus type.
Second, technically, the AXI DAC IP block can't be used as
a generic SPI controller, so it wouldn't make sense to put
it in drivers/spi. But, from wiring point of view, it could
still make sense to use SPI DT bindings since we have SPI
wiring. At the same time, the AXI DAC IP block is also
providing extra functionality in addition to the SPI bus
so it makes sense to keep the io-backend bindings for those
extra bits.
backend: spi@44a70000 {
compatible = "adi,axi-dac-ad3225r";
reg = <0x44a70000 0x1000>;
dmas = <&dac_tx_dma 0>;
dma-names = "tx";
#io-backend-cells = <0>;
clocks = <&ref_clk>;
#address-cells = <1>;
#size-cells = <0>;
dac@0 {
compatible = "adi,ad3552r";
reg = <0>;
/*
* Not sure how right this is - attempting to say that
* the QSPI select pin is hardwired high, so the 4 SPI I/O
* pins on the DAC are always functioning as SDIO0/1/2/3
* as opposed to the usual 2 SDI/SDO pins and 2 unused.
*/
spi-3-wire;
spi-tx-bus-width = <4>;
spi-rx-bus-width = <4>;
reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
io-backends = <&backend>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
adi,output-range-microvolt = <(-10000000) (10000000)>;
};
};
};
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 2/8] iio: backend: extend features
2024-09-02 14:03 ` Angelo Dureghello
@ 2024-09-03 19:11 ` Jonathan Cameron
2024-09-04 12:01 ` Angelo Dureghello
0 siblings, 1 reply; 54+ messages in thread
From: Jonathan Cameron @ 2024-09-03 19:11 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Mon, 2 Sep 2024 16:03:22 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:
> Hi Jonathan,
>
> thanks for the feedbacks,
>
> On 31/08/24 1:23 PM, Jonathan Cameron wrote:
> > On Thu, 29 Aug 2024 14:32:00 +0200
> > Angelo Dureghello <adureghello@baylibre.com> wrote:
> >
> >> From: Angelo Dureghello <adureghello@baylibre.com>
> >>
> >> Extend backend features with new calls needed later on this
> >> patchset from axi version of ad3552r.
> >>
> >> A bus type property has been added to the devicetree to
> >> inform the backend about the type of bus (interface) in use
> >> bu the IP.
> >>
> >> The follwoing calls are added:
> >>
> >> iio_backend_ext_sync_enable
> >> enable synchronize channels on external trigger
> >> iio_backend_ext_sync_disable
> >> disable synchronize channels on external trigger
> >> iio_backend_ddr_enable
> >> enable ddr bus transfer
> >> iio_backend_ddr_disable
> >> disable ddr bus transfer
> >> iio_backend_set_bus_mode
> >> select the type of bus, so that specific read / write
> >> operations are performed accordingly
> >> iio_backend_buffer_enable
> >> enable buffer
> >> iio_backend_buffer_disable
> >> disable buffer
> >> iio_backend_data_transfer_addr
> >> define the target register address where the DAC sample
> >> will be written.
> >> iio_backend_bus_reg_read
> >> generic bus read, bus-type dependent
> >> iio_backend_bus_read_write
> >> generic bus write, bus-type dependent
> >>
> >> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> >> ---
> >> drivers/iio/industrialio-backend.c | 151 +++++++++++++++++++++++++++++++++++++
> >> include/linux/iio/backend.h | 24 ++++++
> >> 2 files changed, 175 insertions(+)
> >>
> >> diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
> >> index a52a6b61c8b5..1f60c8626be7 100644
> >> --- a/drivers/iio/industrialio-backend.c
> >> +++ b/drivers/iio/industrialio-backend.c
> >> @@ -718,6 +718,157 @@ static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back)
> >> return 0;
> >> }
> >
> >> +
> >> +/**
> >> + * iio_backend_buffer_enable - Enable data buffering
> > Data buffering is a very vague term. Perhaps some more detail on what
> > this means?
>
> for this DAC IP, it is the dma buffer where i write the samples,
> for other non-dac frontends may be something different, so i kept it
> generic. Not sure what a proper name may be, maybe
>
> "Enable optional data buffer" ?
How do you 'enable' a buffer? Enable writing into it maybe?
>
>
> >> + * @back: Backend device
> >> + *
> >> + * RETURNS:
> >> + * 0 on success, negative error number on failure.
> >> + */
> >> +int iio_backend_buffer_enable(struct iio_backend *back)
> >> +{
> >> + return iio_backend_op_call(back, buffer_enable);
> >> +}
> >> +EXPORT_SYMBOL_NS_GPL(iio_backend_buffer_enable, IIO_BACKEND);
> >> +
> >> +/**
>
> >> +/**
> >> + * iio_backend_bus_reg_read - Read from the interface bus
> >> + * @back: Backend device
> >> + * @reg: Register valule
> >> + * @val: Pointer to register value
> >> + * @size: Size, in bytes
> >> + *
> >> + * A backend may operate on a specific interface with a related bus.
> >> + * Read from the interface bus.
> > So this is effectively routing control plane data through the offloaded
> > bus? That sounds a lot more like a conventional bus than IIO backend.
> > Perhaps it should be presented as that with the IIO device attached
> > to that bus? I don't fully understand what is wired up here.
> >
> Mainly, an IP may include a bus as 16bit parallel, or LVDS, or similar
> to QSPI as in my case (ad3552r).
ok.
If this is a bus used for both control and dataplane, then we should really
be presenting it as a bus (+ offload) similar to do for spi + offload.
>
> In particular, the bus is physically as a QSPI bus, but the data format
> over it is a bit different.
>
> So ad3552r needs this 5 lanes bus + double data rate to reach 33MUPS.
>
> https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
>
Jonathan
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 3/8] iio: backend adi-axi-dac: backend features
2024-09-02 16:04 ` Angelo Dureghello
@ 2024-09-03 19:16 ` Jonathan Cameron
2024-09-05 10:49 ` Nuno Sá
0 siblings, 1 reply; 54+ messages in thread
From: Jonathan Cameron @ 2024-09-03 19:16 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Mon, 2 Sep 2024 18:04:51 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:
> On 31/08/24 1:34 PM, Jonathan Cameron wrote:
> > On Thu, 29 Aug 2024 14:32:01 +0200
> > Angelo Dureghello <adureghello@baylibre.com> wrote:
> >
> >> From: Angelo Dureghello <adureghello@baylibre.com>
> >>
> >> Extend DAC backend with new features required for the AXI driver
> >> version for the a3552r DAC.
> >>
> >> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > Hi Angelo
> > Minor comments inline.
> >>
> >> static int axi_dac_enable(struct iio_backend *back)
> >> @@ -460,7 +493,13 @@ static int axi_dac_data_source_set(struct iio_backend *back, unsigned int chan,
> >> case IIO_BACKEND_EXTERNAL:
> >> return regmap_update_bits(st->regmap,
> >> AXI_DAC_REG_CHAN_CNTRL_7(chan),
> >> - AXI_DAC_DATA_SEL, AXI_DAC_DATA_DMA);
> >> + AXI_DAC_DATA_SEL,
> >> + AXI_DAC_DATA_DMA);
> > Unrelated change. If you want to change this, separate patch.
> Thanks, fixed.
> >
> >> + case IIO_BACKEND_INTERNAL_RAMP_16:
> >> + return regmap_update_bits(st->regmap,
> >> + AXI_DAC_REG_CHAN_CNTRL_7(chan),
> >> + AXI_DAC_DATA_SEL,
> >> + AXI_DAC_DATA_INTERNAL_RAMP_16);
> >> default:
> >> return -EINVAL;
> >> }
> >> @@ -518,9 +557,204 @@ static int axi_dac_reg_access(struct iio_backend *back, unsigned int reg,
> >> return regmap_write(st->regmap, reg, writeval);
> >> }
> >>
> >> +
> >> +static int axi_dac_bus_reg_write(struct iio_backend *back,
> >> + u32 reg, void *val, size_t size)
> > Maybe just pass an unsigned int for val?
> > So follow what regmap does? You will still need the size, but it
> > will just be configuration related rather than affecting the type
> > of val.
> >
> void * was used since data size in the future may vary depending
> on the bus physical interface.
>
I doubt it will get bigger than u64. Passing void * is always
nasty if we can do something else and this is a register writing
operation. I'm yet to meet an ADC or similar with > 64 bit registers
(or even one with 64 bit ones!)
> Actually, a reg bus write involves several AXI regmap operations.
> >
> >> +{
> >> + struct axi_dac_state *st = iio_backend_get_priv(back);
> >> +
> >> + if (!st->bus_type)
> >> + return -EOPNOTSUPP;
> >> +
> >> + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
> > As below, I'd use a switch and factor out this block as a separate
> > bus specific function.
> Ok, changed.
> >
> >> + int ret;
> >> + u32 ival;
> >> +
> >> + if (size != 1 && size != 2)
> >> + return -EINVAL;
> >> +
> >> + switch (size) {
> >> + case 1:
> >> + ival = FIELD_PREP(AXI_DAC_DATA_WR_8, *(u8 *)val);
> >> + break;
> >> + case 2:
> >> + ival = FIELD_PREP(AXI_DAC_DATA_WR_16, *(u16 *)val);
> >> + break;
> >> + default:
> >> + return -EINVAL;
> > Hopefully compiler won't need this and the above. I'd drop the size != 1..
> > check in favour of just doing it in this switch.
> >
> sure, done.
>
>
> >> + }
> >> +
> >> + ret = regmap_write(st->regmap, AXI_DAC_CNTRL_DATA_WR, ival);
> >> + if (ret)
> >> + return ret;
> >> +
> >> + /*
> >> + * Both REG_CNTRL_2 and AXI_DAC_CNTRL_DATA_WR need to know
> >> + * the data size. So keeping data size control here only,
> >> + * since data size is mandatory for to the current transfer.
> >> + * DDR state handled separately by specific backend calls,
> >> + * generally all raw register writes are SDR.
> >> + */
> >> + if (size == 1)
> >> + ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_2,
> >> + AXI_DAC_SYMB_8B);
> >> + else
> >> + ret = regmap_clear_bits(st->regmap, AXI_DAC_REG_CNTRL_2,
> >> + AXI_DAC_SYMB_8B);
> >> + if (ret)
> >> + return ret;
> >> +
> >> + ret = regmap_update_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
> >> + AXI_DAC_ADDRESS,
> >> + FIELD_PREP(AXI_DAC_ADDRESS, reg));
> >> + if (ret)
> >> + return ret;
> >> +
> >> + ret = regmap_update_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
> >> + AXI_DAC_TRANSFER_DATA,
> >> + AXI_DAC_TRANSFER_DATA);
> >> + if (ret)
> >> + return ret;
> >> +
> >> + ret = regmap_read_poll_timeout(st->regmap,
> >> + AXI_DAC_REG_CUSTOM_CTRL, ival,
> >> + ival & AXI_DAC_TRANSFER_DATA,
> >> + 10, 100 * KILO);
> >> + if (ret)
> >> + return ret;
> >> +
> >> + return regmap_clear_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
> >> + AXI_DAC_TRANSFER_DATA);
> >> + }
> >> +
> >> + return -EINVAL;
> >> +}
> >> +
> >> +static int axi_dac_bus_reg_read(struct iio_backend *back,
> >> + u32 reg, void *val, size_t size)
> > As for write, I'd just use an unsigned int * for val like
> > regmap does.
>
> Ok, so initial choice was unsigned int, further thinking of
> possible future busses drive the choice to void *.
>
> Let me know, i can switch to unsigned int in case.
I would just go with unsigned int or at a push u64 *
>
>
> >
> >
> >> +{
> >> + struct axi_dac_state *st = iio_backend_get_priv(back);
> >> +
> >> + if (!st->bus_type)
> >> + return -EOPNOTSUPP;
> >> +
> >> + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
> > It got mentioned in binding review but if this isn't QSPI, even
> > if similar don't call it that.
>
> It's a bit difficult to find a different name, physically,
> it is a QSPI, 4 lanes + clock + cs, and datasheet is naming it Quad SPI.
> But looking the data protocol, it's a bit different.
is QSPI actually defined anywhere? I assumed it would be like
SPI for which everything is so flexible you can build whatever you like.
>
> QSPI has instruction, address and data.
> Here we have just ADDR and DATA.
>
> What about ADI_QSPI ?
Sure, that is fine if we worry about differences from qspi
(which depends on there being a reference spec!)
Jonathan
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-09-02 9:32 ` Angelo Dureghello
@ 2024-09-03 19:18 ` Jonathan Cameron
2024-09-06 9:04 ` Conor Dooley
1 sibling, 0 replies; 54+ messages in thread
From: Jonathan Cameron @ 2024-09-03 19:18 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Conor Dooley, Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Olivier Moysan,
linux-iio, devicetree, linux-kernel, dlechner
On Mon, 2 Sep 2024 11:32:37 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:
> Hi Conor,
>
>
> On 30/08/24 5:33 PM, Conor Dooley wrote:
> > On Fri, Aug 30, 2024 at 10:19:49AM +0200, Angelo Dureghello wrote:
> >> Hi Conor,
> >>
> >> On 29/08/24 5:46 PM, Conor Dooley wrote:
> >>> On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
> >>>> From: Angelo Dureghello <adureghello@baylibre.com>
> >>>>
> >>>> Add bus property.
> >>> RFC it may be, but you do need to explain what this bus-type actually
> >>> describes for commenting on the suitability of the method to be
> >>> meaningful.
> >> thanks for the feedbacks,
> >>
> >> a "bus" is intended as a generic interface connected to the target,
> >> may be used from a custom IP (fpga) to communicate with the target
> >> device (by read/write(reg and value)) using a special custom interface.
> >>
> >> The bus could also be physically the same of some well-known existing
> >> interfaces (as parallel, lvds or other uncommon interfaces), but using
> >> an uncommon/custom protocol over it.
> >>
> >> In concrete, actually bus-type is added to the backend since the
> >> ad3552r DAC chip can be connected (for maximum speed) by a 5 lanes DDR
> >> parallel bus (interface that i named QSPI, but it's not exactly a QSPI
> >> as a protocol), so it's a device-specific interface.
> >>
> >> With additions in this patchset, other frontends, of course not only
> >> DACs, will be able to add specific busses and read/wrtie to the bus
> >> as needed.
> >>
> >>>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> >>>> ---
> >>>> Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9 +++++++++
> >>>> 1 file changed, 9 insertions(+)
> >>>>
> >>>> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> >>>> index a55e9bfc66d7..a7ce72e1cd81 100644
> >>>> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> >>>> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> >>>> @@ -38,6 +38,15 @@ properties:
> >>>> clocks:
> >>>> maxItems: 1
> >>> You mentioned about new compatible strings, does the one currently
> >>> listed in this binding support both bus types?
> > You didn't answer this, and there's insufficient explanation of the
> > "hardware" in this RFC, but I found this which is supposedly the
> > backend:
> > https://github.com/analogdevicesinc/hdl/tree/main/library/axi_ad3552r
> > adi,axi-dac.yaml has a single compatible, and that compatible has
> > nothing to do with "axi_ad3552r" as it is "adi,axi-dac-9.1.b". I would
> > expect either justification for reuse of the compatible, or a brand new
> > compatible for this backend, even if the driver can mostly be reused.
> >
> > Could you please link to whatever ADI wiki has detailed information on
> > how this stuff works so that I can look at it to better understand the
> > axes of configuration here?
>
> https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
>
> that has same structure and register set of the generic ADI AXI-DAC IP:
> https://wiki.analog.com/resources/fpga/docs/axi_dac_ip
>
>
> >>> Making the bus type decision based on compatible only really makes sense
> >>> if they're different versions of the IP, but not if they're different
> >>> configuration options for a given version.
> >>>
> >>>> + bus-type:
> >> DAC IP on fpga actually respects same structure and register set, except
> >> for a named "custom" register that may use specific bitfields depending
> >> on the application of the IP.
> > To paraphrase:
> > "The register map is the same, except for the bit that is different".
> > If ADI is shipping several different configurations of this IP for
> > different DACs, I'd be expecting different compatibles for each backend
> > to be honest
>
> i am still quite new to this fpga-based implementations, at least for how
> such IPs are actually interfacing to the linux subsystem, so i may miss
> some point.
>
> About the "adi,axi-dac-9.1.b" compatible, the generic DAC IP register set
> is mostly the same structure of this ad3552r IP (links above), except for
> bitfields in the DAC_CUSTOM_CTRL register.
>
> My choice for now was to add a bus-type property.
>
> Not an HDL expert, but i think a different bus means, from an hardware
> point of
> view, a different IP in terms of internal fpga circuitry, even if not as a
> register-set.
Whilst I'm not sure we should be hiding the bus element away (rather than
doing something closer to an spi bus + offloads) if we do end up like this
maybe encode the bus type in the compatible. It's definitely the
adi,axi-dac-qspi* specific variant if there isn't an explicit register to
program to tell it not use a parallel bus or similar.
Jonathan
>
>
> > .
> > If each DAC specific backend was to have a unique compatible, would the
> > type of bus used be determinable from it? Doesn't have to work for all
> > devices from now until the heath death of the universe, but at least for
> > the devices that you're currently aware of?
> >
> >>> If, as you mentioned, there are multiple bus types, a non-flag property
> >>> does make sense. However, I am really not keen on these "forced" numerical
> >>> properties at all, I'd much rather see strings used here.
> >>>> + maxItems: 1
> >>>> + description: |
> >>>> + Configure bus type:
> >>>> + - 0: none
> >>>> + - 1: qspi
> > Also, re-reading the cover letter, it says "this platform driver uses a 4
> > lanes parallel bus, plus a clock line, similar to a qspi."
> > I don't think we should call this "qspi" if it is not actually qspi,
> > that's just confusing.
>
> Agree, name should be something different.
>
>
> > Cheers,
> > Conor.
>
> Thanks,
> regards,
>
> Angelo
>
>
> >>>> + enum: [0, 1]
> >>>> + default: 0
> >>>> +
> >>>> '#io-backend-cells':
> >>>> const: 0
> >>>>
> >>>> --
> >>>> 2.45.0.rc1
> >>>>
> >> --
> >> ,,, Angelo Dureghello
> >> :: :. BayLibre -runtime team- Developer
> >> :`___:
> >> `____:
> >>
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 5/8] iio: dac: ad3552r: changes to use FIELD_PREP
2024-09-02 16:15 ` Angelo Dureghello
@ 2024-09-03 19:19 ` Jonathan Cameron
0 siblings, 0 replies; 54+ messages in thread
From: Jonathan Cameron @ 2024-09-03 19:19 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Mon, 2 Sep 2024 18:15:43 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:
> On 31/08/24 1:48 PM, Jonathan Cameron wrote:
> > On Thu, 29 Aug 2024 14:32:03 +0200
> > Angelo Dureghello <adureghello@baylibre.com> wrote:
> >
> >> From: Angelo Dureghello <adureghello@baylibre.com>
> >>
> >> Changes to use FIELD_PREP, so that driver-specific ad3552r_field_prep
> >> is removed. Variables (arrays) that was used to call ad3552r_field_prep
> >> are removerd too.
> > removed
> fixed thanks.
For future reference, don't bother reply if you accept everything.
Just adds noise on the list.
My assumption is that you accept anything you 'don't' reply to ;)
Jonathan
> >
> > LGTM
>
> Regards,
> Angelo
>
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 7/8] iio: dac: ad3552r: add axi platform driver
2024-09-03 8:17 ` Angelo Dureghello
@ 2024-09-03 19:28 ` Jonathan Cameron
0 siblings, 0 replies; 54+ messages in thread
From: Jonathan Cameron @ 2024-09-03 19:28 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Tue, 3 Sep 2024 10:17:35 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:
> Hi Jonathan,
>
> On 31/08/24 2:13 PM, Jonathan Cameron wrote:
> > On Thu, 29 Aug 2024 14:32:05 +0200
> > Angelo Dureghello <adureghello@baylibre.com> wrote:
> >
> >> From: Angelo Dureghello <adureghello@baylibre.com>
> >>
> >> Add support for ad3552r AXI DAC IP version.
> >>
> >> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > Hi Angelo
> >
> > To me this feels like the interface is much closer to SPI + SPI offload
> > than to a conventional IIO backend on the basis it carries the configuration
> > path as well.
> >
> > Can we see if it can be fitted into that model? You will need to define
> > a new bus type etc for it but should be fairly simple given constrained
> > setup (at least today!)
> >
> > That will resolve a bunch of questions around the binding as well.
>
> thanks for all the feedbacks.
>
> I see, spi offload may have more sense but as of now looks like moving to
> AXI SPI engine instead of AXI DAC would require quite a lot of work from the
> ADI HDL guys and also then, for me some work reworking all this stuff.
> From an initial discussion with Nuno and David, we was oriented to use the
> iio backend for the current HDL, so at least for this chip at this stage
> would
> be good, if possible, to stay this way.
Superficially, even with the existing IP it feels to me like it's just
a qspi controller + an offload that happens not to need much programming.
You'd pass that offload the spi message structure etc and it would 'notice'
that it corresponds to what it has in hardware and then use that.
For register reads it looks like a simple (Q)SPI bus controller anyway.
So I'm not sure any real changes are needed in the IP to map it
in a more standard way as as a device on a bus.
Note though that key here may be how we do the dt-binding, rather than
what the code does (we can change the internals of the driver later
if we like).
If you built a binding that looked like an spi bus + offload and
could we bind a backend etc as you do currently?
Might require a bit of juggling to make it work.
>
>
> > Jonathan
> >
> >> diff --git a/drivers/iio/dac/ad3552r-axi.c b/drivers/iio/dac/ad3552r-axi.c
> >> new file mode 100644
> >> index 000000000000..98e5da08c973
> >> --- /dev/null
> >> +++ b/drivers/iio/dac/ad3552r-axi.c
> >> @@ -0,0 +1,572 @@
> >> +// SPDX-License-Identifier: GPL-2.0-only
> >> +/*
> >> + * Analog Devices AD3552R
> >> + * Digital to Analog converter driver, AXI DAC backend version
> >> + *
> >> + * Copyright 2024 Analog Devices Inc.
> >> + */
> >> +
> >> +#include <linux/bitfield.h>
> >> +#include <linux/delay.h>
> >> +#include <linux/gpio/consumer.h>
> >> +#include <linux/iio/buffer.h>
> >> +#include <linux/iio/backend.h>
> >> +#include <linux/of.h>
> > Why? Probably want mod_devicetable.h
>
>
> with mod_devicetable.h in place of of.h i get
>
> drivers/iio/dac/ad3552r-axi.c:272:9: error: cleanup argument not a function
> struct fwnode_handle *child __free(fwnode_handle) = NULL;
> ^~~~~~~~~~~~~
That's not in of.h either
add linux/property.h as well.
>
...
> >> +static int ad3552r_axi_setup(struct ad3552r_axi_state *st)
> >> +{
> >
> >> + u32 val, range;
> >> + int err;
> >> +
> >> + err = ad3552r_axi_reset(st);
> >> + if (err)
> >> + return err;
> >> +
> >> + err = iio_backend_ddr_disable(st->back);
> >> + if (err)
> >> + return err;
> >> +
> >> + val = AD3552R_SCRATCH_PAD_TEST_VAL1;
> >> + err = iio_backend_bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
> >> + &val, 1);
> > as per earlier review, I'd pass an unsigned int instead of a void *
> > Then you can avoid the dance with a local variable.
> void * was chosen thinking to future busses, please let me know if
> it can stay this way.
I'd not bother future proofing that much. If you think > 32 bit is
likely use a u64.
> >> + if (err)
> >> + return err;
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi
2024-09-03 16:17 ` David Lechner
@ 2024-09-03 19:39 ` Jonathan Cameron
2024-09-05 9:16 ` Nuno Sá
0 siblings, 1 reply; 54+ messages in thread
From: Jonathan Cameron @ 2024-09-03 19:39 UTC (permalink / raw)
To: David Lechner
Cc: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
Nuno Sá, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan, linux-iio, devicetree, linux-kernel, Mark Brown
On Tue, 3 Sep 2024 11:17:24 -0500
David Lechner <dlechner@baylibre.com> wrote:
> On 9/3/24 3:34 AM, Angelo Dureghello wrote:
> > Hi Jonathan and all,
> >
> >
> > On 31/08/24 1:38 PM, Jonathan Cameron wrote:
> >> On Thu, 29 Aug 2024 14:31:58 +0200
> >> Angelo Dureghello <adureghello@baylibre.com> wrote:
> >>
> >>> Hi, asking for comments for this patchset, that is mostly
> >>> ready, at least feature-complete and functionally tested.
> >>>
> >>> I am introducing ad3552r-axi variant, controlled from a fpga-based
> >>> AXI IP, as a platform driver, using the DAC backend. The patchset is
> >>> actually based on linux-iio, since some needed DAC backend features
> >>> was already there on that repo only, still to be merged in mainline.
> >>>
> >>> Comments i would like to ask are:
> >>>
> >>> - i added some devicetree bindings inside current ad3552r yaml,
> >>> device is the same, so i wouldn't create a different yaml file.
> >> Agreed. If same device, it's usually better to keep it in one file.
> >>
> >>> - if it's ok adding the bus-type property in the DAC backend:
> >>> actually, this platform driver uses a 4 lanes parallel bus, plus
> >>> a clock line, similar to a qspi. This to read an write registers
> >>> and as well to send samples at double data rate. Other DAC may
> >>> need "parallel" or "lvds" in the future.
> >> If it is for register read + write as well, sounds to me like you need
> >> to treat this as a new bus type, possibly then combined with a
> >> backend, or something similar to spi offload?
> >>
> >> What bus does this currently sit on in your DT bindings?
> >> (add an example)
> >
> >
> > &amba {
> >
> > ref_clk: clk@44B00000 {
> > compatible = "adi,axi-clkgen-2.00.a";
> > reg = <0x44B00000 0x10000>;
> > #clock-cells = <0>;
> > clocks = <&clkc 15>, <&clkc 15>;
> > clock-names = "s_axi_aclk", "clkin1";
> > clock-output-names = "ref_clk";
> > };
> >
> > dac_tx_dma: dma-controller@0x44a30000 {
> > compatible = "adi,axi-dmac-1.00.a";
> > reg = <0x44a30000 0x10000>;
> > #dma-cells = <1>;
> > interrupt-parent = <&intc>;
> > interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
> > clocks = <&clkc 15>;
> >
> > adi,channels {
> > #size-cells = <0>;
> > #address-cells = <1>;
> >
> > dma-channel@0 {
> > reg = <0>;
> > adi,source-bus-width = <32>;
> > adi,source-bus-type = <0>;
> > adi,destination-bus-width = <32>;
> > adi,destination-bus-type = <1>;
> > };
> > };
> > };
> >
> > backend: controller@44a70000 {
> > compatible = "adi,axi-dac-9.1.b";
> > reg = <0x44a70000 0x1000>;
> > dmas = <&dac_tx_dma 0>;
> > dma-names = "tx";
> > #io-backend-cells = <0>;
> > clocks = <&ref_clk>;
> > bus-type = <1>; /* IIO QSPI */
> > };
> >
> > axi-ad3552r {
> > compatible = "adi,ad3552r";
> > reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
> > io-backends = <&backend>;
> > #address-cells = <1>;
> > #size-cells = <0>;
> > channel@0 {
> > reg = <0>;
> > adi,output-range-microvolt = <(-10000000) (10000000)>;
> > };
> > };
>
> Shouldn't the axi-ad3552r node be one level higher since it isn't
> a memory-mapped device, but rather an external chip?
Definitely not where it currently is..
>
> But based on the other feedback we got in this series and some
> #devicetree IRC chat here is an alternate binding suggestion we
> could consider.
>
> First, even though the FPGA IP block for use with AD3225R uses
> the same register map as the AXI DAC IP block, some of the
> registers behave differently, so it makes sense to have a
> different compatible string rather than using the bus-type
> property to tell the difference between the two IP blocks.
> There are likely more differences than just the bus type.
I'd be amazed if they managed to keep things that similar
given totally different buses.
>
> Second, technically, the AXI DAC IP block can't be used as
> a generic SPI controller, so it wouldn't make sense to put
> it in drivers/spi.
I wonder if there is any precedence of restricted controllers
for SPI? (For i2c we have the smbus ones as a vaguely similar
example). +CC Mark.
> But, from wiring point of view, it could
> still make sense to use SPI DT bindings since we have SPI
> wiring. At the same time, the AXI DAC IP block is also
> providing extra functionality in addition to the SPI bus
> so it makes sense to keep the io-backend bindings for those
> extra bits.
>
> backend: spi@44a70000 {
> compatible = "adi,axi-dac-ad3225r";
> reg = <0x44a70000 0x1000>;
> dmas = <&dac_tx_dma 0>;
> dma-names = "tx";
> #io-backend-cells = <0>;
> clocks = <&ref_clk>;
>
> #address-cells = <1>;
> #size-cells = <0>;
>
> dac@0 {
> compatible = "adi,ad3552r";
> reg = <0>;
>
> /*
> * Not sure how right this is - attempting to say that
> * the QSPI select pin is hardwired high, so the 4 SPI I/O
> * pins on the DAC are always functioning as SDIO0/1/2/3
> * as opposed to the usual 2 SDI/SDO pins and 2 unused.
> */
> spi-3-wire;
> spi-tx-bus-width = <4>;
> spi-rx-bus-width = <4>;
>
> reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
> io-backends = <&backend>;
>
> #address-cells = <1>;
> #size-cells = <0>;
>
> channel@0 {
> reg = <0>;
> adi,output-range-microvolt = <(-10000000) (10000000)>;
> };
> };
> };
That's definitely an improvement. It's a little strange to have
a reference back to the parent but I'm fine with that.
Jonathan
>
>
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 2/8] iio: backend: extend features
2024-09-03 19:11 ` Jonathan Cameron
@ 2024-09-04 12:01 ` Angelo Dureghello
2024-09-05 10:28 ` Nuno Sá
0 siblings, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-09-04 12:01 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
Hi Jonathan,
On 03/09/24 9:11 PM, Jonathan Cameron wrote:
> On Mon, 2 Sep 2024 16:03:22 +0200
> Angelo Dureghello <adureghello@baylibre.com> wrote:
>
>> Hi Jonathan,
>>
>> thanks for the feedbacks,
>>
>> On 31/08/24 1:23 PM, Jonathan Cameron wrote:
>>> On Thu, 29 Aug 2024 14:32:00 +0200
>>> Angelo Dureghello <adureghello@baylibre.com> wrote:
>>>
>>>> From: Angelo Dureghello <adureghello@baylibre.com>
>>>>
>>>> Extend backend features with new calls needed later on this
>>>> patchset from axi version of ad3552r.
>>>>
>>>> A bus type property has been added to the devicetree to
>>>> inform the backend about the type of bus (interface) in use
>>>> bu the IP.
>>>>
>>>> The follwoing calls are added:
>>>>
>>>> iio_backend_ext_sync_enable
>>>> enable synchronize channels on external trigger
>>>> iio_backend_ext_sync_disable
>>>> disable synchronize channels on external trigger
>>>> iio_backend_ddr_enable
>>>> enable ddr bus transfer
>>>> iio_backend_ddr_disable
>>>> disable ddr bus transfer
>>>> iio_backend_set_bus_mode
>>>> select the type of bus, so that specific read / write
>>>> operations are performed accordingly
>>>> iio_backend_buffer_enable
>>>> enable buffer
>>>> iio_backend_buffer_disable
>>>> disable buffer
>>>> iio_backend_data_transfer_addr
>>>> define the target register address where the DAC sample
>>>> will be written.
>>>> iio_backend_bus_reg_read
>>>> generic bus read, bus-type dependent
>>>> iio_backend_bus_read_write
>>>> generic bus write, bus-type dependent
>>>>
>>>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>>>> ---
>>>> drivers/iio/industrialio-backend.c | 151 +++++++++++++++++++++++++++++++++++++
>>>> include/linux/iio/backend.h | 24 ++++++
>>>> 2 files changed, 175 insertions(+)
>>>>
>>>> diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
>>>> index a52a6b61c8b5..1f60c8626be7 100644
>>>> --- a/drivers/iio/industrialio-backend.c
>>>> +++ b/drivers/iio/industrialio-backend.c
>>>> @@ -718,6 +718,157 @@ static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back)
>>>> return 0;
>>>> }
>>>
>>>> +
>>>> +/**
>>>> + * iio_backend_buffer_enable - Enable data buffering
>>> Data buffering is a very vague term. Perhaps some more detail on what
>>> this means?
>> for this DAC IP, it is the dma buffer where i write the samples,
>> for other non-dac frontends may be something different, so i kept it
>> generic. Not sure what a proper name may be, maybe
>>
>> "Enable optional data buffer" ?
> How do you 'enable' a buffer? Enable writing into it maybe?
for the current case, this is done using the custom register
of the AXI IP, enabling a "stream".
return regmap_set_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
AXI_DAC_STREAM_ENABLE);
Functionally, looks like dma data is processed (sent over qspi)
when the stream is enabled.
Maybe a name as "stream_enable" would me more appropriate ?
"Stream" seems less generic btw.
>>
>>>> + * @back: Backend device
>>>> + *
>>>> + * RETURNS:
>>>> + * 0 on success, negative error number on failure.
>>>> + */
>>>> +int iio_backend_buffer_enable(struct iio_backend *back)
>>>> +{
>>>> + return iio_backend_op_call(back, buffer_enable);
>>>> +}
>>>> +EXPORT_SYMBOL_NS_GPL(iio_backend_buffer_enable, IIO_BACKEND);
>>>> +
>>>> +/**
>>>> +/**
>>>> + * iio_backend_bus_reg_read - Read from the interface bus
>>>> + * @back: Backend device
>>>> + * @reg: Register valule
>>>> + * @val: Pointer to register value
>>>> + * @size: Size, in bytes
>>>> + *
>>>> + * A backend may operate on a specific interface with a related bus.
>>>> + * Read from the interface bus.
>>> So this is effectively routing control plane data through the offloaded
>>> bus? That sounds a lot more like a conventional bus than IIO backend.
>>> Perhaps it should be presented as that with the IIO device attached
>>> to that bus? I don't fully understand what is wired up here.
>>>
>> Mainly, an IP may include a bus as 16bit parallel, or LVDS, or similar
>> to QSPI as in my case (ad3552r).
> ok.
>
> If this is a bus used for both control and dataplane, then we should really
> be presenting it as a bus (+ offload) similar to do for spi + offload.
>
>> In particular, the bus is physically as a QSPI bus, but the data format
>> over it is a bit different.
>>
>> So ad3552r needs this 5 lanes bus + double data rate to reach 33MUPS.
>>
>> https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
>>
> Jonathan
>
--
,,, Angelo Dureghello
:: :. BayLibre -runtime team- Developer
:`___:
`____:
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi
2024-09-03 19:39 ` Jonathan Cameron
@ 2024-09-05 9:16 ` Nuno Sá
2024-09-07 14:12 ` Jonathan Cameron
0 siblings, 1 reply; 54+ messages in thread
From: Nuno Sá @ 2024-09-05 9:16 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner
Cc: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
Nuno Sá, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan, linux-iio, devicetree, linux-kernel, Mark Brown
On Tue, 2024-09-03 at 20:39 +0100, Jonathan Cameron wrote:
> On Tue, 3 Sep 2024 11:17:24 -0500
> David Lechner <dlechner@baylibre.com> wrote:
>
> > On 9/3/24 3:34 AM, Angelo Dureghello wrote:
> > > Hi Jonathan and all,
> > >
> > >
> > > On 31/08/24 1:38 PM, Jonathan Cameron wrote:
> > > > On Thu, 29 Aug 2024 14:31:58 +0200
> > > > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > > >
> > > > > Hi, asking for comments for this patchset, that is mostly
> > > > > ready, at least feature-complete and functionally tested.
> > > > >
> > > > > I am introducing ad3552r-axi variant, controlled from a fpga-based
> > > > > AXI IP, as a platform driver, using the DAC backend. The patchset is
> > > > > actually based on linux-iio, since some needed DAC backend features
> > > > > was already there on that repo only, still to be merged in mainline.
> > > > >
> > > > > Comments i would like to ask are:
> > > > >
> > > > > - i added some devicetree bindings inside current ad3552r yaml,
> > > > > device is the same, so i wouldn't create a different yaml file.
> > > > Agreed. If same device, it's usually better to keep it in one file.
> > > >
> > > > > - if it's ok adding the bus-type property in the DAC backend:
> > > > > actually, this platform driver uses a 4 lanes parallel bus, plus
> > > > > a clock line, similar to a qspi. This to read an write registers
> > > > > and as well to send samples at double data rate. Other DAC may
> > > > > need "parallel" or "lvds" in the future.
> > > > If it is for register read + write as well, sounds to me like you need
> > > > to treat this as a new bus type, possibly then combined with a
> > > > backend, or something similar to spi offload?
> > > >
> > > > What bus does this currently sit on in your DT bindings?
> > > > (add an example)
> > >
> > >
> > > &amba {
> > >
> > > ref_clk: clk@44B00000 {
> > > compatible = "adi,axi-clkgen-2.00.a";
> > > reg = <0x44B00000 0x10000>;
> > > #clock-cells = <0>;
> > > clocks = <&clkc 15>, <&clkc 15>;
> > > clock-names = "s_axi_aclk", "clkin1";
> > > clock-output-names = "ref_clk";
> > > };
> > >
> > > dac_tx_dma: dma-controller@0x44a30000 {
> > > compatible = "adi,axi-dmac-1.00.a";
> > > reg = <0x44a30000 0x10000>;
> > > #dma-cells = <1>;
> > > interrupt-parent = <&intc>;
> > > interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
> > > clocks = <&clkc 15>;
> > >
> > > adi,channels {
> > > #size-cells = <0>;
> > > #address-cells = <1>;
> > >
> > > dma-channel@0 {
> > > reg = <0>;
> > > adi,source-bus-width = <32>;
> > > adi,source-bus-type = <0>;
> > > adi,destination-bus-width = <32>;
> > > adi,destination-bus-type = <1>;
> > > };
> > > };
> > > };
> > >
> > > backend: controller@44a70000 {
> > > compatible = "adi,axi-dac-9.1.b";
> > > reg = <0x44a70000 0x1000>;
> > > dmas = <&dac_tx_dma 0>;
> > > dma-names = "tx";
> > > #io-backend-cells = <0>;
> > > clocks = <&ref_clk>;
> > > bus-type = <1>; /* IIO QSPI */
> > > };
> > >
> > > axi-ad3552r {
> > > compatible = "adi,ad3552r";
> > > reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
> > > io-backends = <&backend>;
> > > #address-cells = <1>;
> > > #size-cells = <0>;
> > > channel@0 {
> > > reg = <0>;
> > > adi,output-range-microvolt = <(-10000000) (10000000)>;
> > > };
> > > };
> >
> > Shouldn't the axi-ad3552r node be one level higher since it isn't
> > a memory-mapped device, but rather an external chip?
> Definitely not where it currently is..
> >
> > But based on the other feedback we got in this series and some
> > #devicetree IRC chat here is an alternate binding suggestion we
> > could consider.
> >
> > First, even though the FPGA IP block for use with AD3225R uses
> > the same register map as the AXI DAC IP block, some of the
> > registers behave differently, so it makes sense to have a
> > different compatible string rather than using the bus-type
> > property to tell the difference between the two IP blocks.
> > There are likely more differences than just the bus type.
>
> I'd be amazed if they managed to keep things that similar
> given totally different buses.
>
Yeah, I was trying to avoid new compatibles as much as I can because things can
get pretty confusing (with lots of new compatibles and quirks) pretty quickly.
Typically yes, most designs have slight differences between them (with new
features and so on) but so far I was trying (thinking) to have those as a
generic new backend op (plus a matching binding property if needed). For this
particular case, I'm fairly sure we could get away with the bus controller
property and having different implementations depending on the bus being
implemented. For the other bits that might differ between designs (eg: DDR
support) is up to frontends to call it or not (depending on they having that
feature or not). Naturally we need that the IPs having DDR support to not have
the same thing supported in different registers but we do control that since
these are FPGA cores.
All the above said, I'm fine with new compatibles but we need to draw a line
when we add new ones. If the reasoning is the IP has some new bits or new
registers, then things can get very confusing (even more if we think about
fallback compatibles) as most of the new designs have some quirks (even if
minimal). So I would say to add new compatibles when things get different enough
that a sane/generic API is not doable.
> >
> > Second, technically, the AXI DAC IP block can't be used as
> > a generic SPI controller, so it wouldn't make sense to put
> > it in drivers/spi.
>
> I wonder if there is any precedence of restricted controllers
> for SPI? (For i2c we have the smbus ones as a vaguely similar
> example). +CC Mark.
>
> > But, from wiring point of view, it could
> > still make sense to use SPI DT bindings since we have SPI
> > wiring. At the same time, the AXI DAC IP block is also
> > providing extra functionality in addition to the SPI bus
> > so it makes sense to keep the io-backend bindings for those
> > extra bits.
> >
> > backend: spi@44a70000 {
> > compatible = "adi,axi-dac-ad3225r";
> > reg = <0x44a70000 0x1000>;
> > dmas = <&dac_tx_dma 0>;
> > dma-names = "tx";
> > #io-backend-cells = <0>;
> > clocks = <&ref_clk>;
> >
> > #address-cells = <1>;
> > #size-cells = <0>;
> >
> > dac@0 {
> > compatible = "adi,ad3552r";
> > reg = <0>;
> >
> > /*
> > * Not sure how right this is - attempting to say that
> > * the QSPI select pin is hardwired high, so the 4 SPI I/O
> > * pins on the DAC are always functioning as SDIO0/1/2/3
> > * as opposed to the usual 2 SDI/SDO pins and 2 unused.
> > */
> > spi-3-wire;
> > spi-tx-bus-width = <4>;
> > spi-rx-bus-width = <4>;
> >
> > reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
> > io-backends = <&backend>;
> >
> > #address-cells = <1>;
> > #size-cells = <0>;
> >
> > channel@0 {
> > reg = <0>;
> > adi,output-range-microvolt = <(-10000000) (10000000)>;
> > };
> > };
> > };
>
> That's definitely an improvement. It's a little strange to have
> a reference back to the parent but I'm fine with that.
>
Agreed...
- Nuno Sá
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-08-30 15:33 ` Conor Dooley
2024-09-02 9:32 ` Angelo Dureghello
@ 2024-09-05 9:50 ` Nuno Sá
2024-09-06 8:50 ` Conor Dooley
1 sibling, 1 reply; 54+ messages in thread
From: Nuno Sá @ 2024-09-05 9:50 UTC (permalink / raw)
To: Conor Dooley, Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan, linux-iio, devicetree, linux-kernel, dlechner
On Fri, 2024-08-30 at 16:33 +0100, Conor Dooley wrote:
> On Fri, Aug 30, 2024 at 10:19:49AM +0200, Angelo Dureghello wrote:
> > Hi Conor,
> >
> > On 29/08/24 5:46 PM, Conor Dooley wrote:
> > > On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
> > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > >
> > > > Add bus property.
> > > RFC it may be, but you do need to explain what this bus-type actually
> > > describes for commenting on the suitability of the method to be
> > > meaningful.
> >
> > thanks for the feedbacks,
> >
> > a "bus" is intended as a generic interface connected to the target,
> > may be used from a custom IP (fpga) to communicate with the target
> > device (by read/write(reg and value)) using a special custom interface.
> >
> > The bus could also be physically the same of some well-known existing
> > interfaces (as parallel, lvds or other uncommon interfaces), but using
> > an uncommon/custom protocol over it.
> >
> > In concrete, actually bus-type is added to the backend since the
> > ad3552r DAC chip can be connected (for maximum speed) by a 5 lanes DDR
> > parallel bus (interface that i named QSPI, but it's not exactly a QSPI
> > as a protocol), so it's a device-specific interface.
> >
> > With additions in this patchset, other frontends, of course not only
> > DACs, will be able to add specific busses and read/wrtie to the bus
> > as needed.
> >
> > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > > ---
> > > > Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9
> > > > +++++++++
> > > > 1 file changed, 9 insertions(+)
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > index a55e9bfc66d7..a7ce72e1cd81 100644
> > > > --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > @@ -38,6 +38,15 @@ properties:
> > > > clocks:
> > > > maxItems: 1
> > > You mentioned about new compatible strings, does the one currently
> > > listed in this binding support both bus types?
>
> You didn't answer this, and there's insufficient explanation of the
> "hardware" in this RFC, but I found this which is supposedly the
> backend:
> https://github.com/analogdevicesinc/hdl/tree/main/library/axi_ad3552r
> adi,axi-dac.yaml has a single compatible, and that compatible has
> nothing to do with "axi_ad3552r" as it is "adi,axi-dac-9.1.b". I would
> expect either justification for reuse of the compatible, or a brand new
> compatible for this backend, even if the driver can mostly be reused.
>
Hi Conor,
So most of these designs have some changes (even if minimal) in the register map
and the idea (mine actually) with this backend stuff was to keep the backend
driver (axi-dac/adc) with the generic compatible since all the (different)
functionality is basically defined by the frontend they connect too and that
functionality is modeled by IIO backend ops. For some more
significant/fundamental differences in the IP like this bus controller kind of
thing, we would add have proper FW properties. The main idea was kind of using
the frontend + generic backend combo so no need for new compatibles for every
new design.
It's still early days (at least upstream) for these IP cores and the backend
code so if you say that we should have new compatibles for every new design that
has some differences in the register map (even if minimal), I'm of course fine
with it. I've done it like this because I was (am) kind of afraid for things to
get complicated fairly quickly both in the bindings and driver (well maybe not
in the driver). OTOH, it can simplify things a lot as it's way easier to
identify different implementations of the IP directly in the driver so we have
way more flexibility.
> Could you please link to whatever ADI wiki has detailed information on
> how this stuff works so that I can look at it to better understand the
> axes of configuration here?
>
> > >
> > > Making the bus type decision based on compatible only really makes sense
> > > if they're different versions of the IP, but not if they're different
> > > configuration options for a given version.
> > >
> > > > + bus-type:
> >
> > DAC IP on fpga actually respects same structure and register set, except
> > for a named "custom" register that may use specific bitfields depending
> > on the application of the IP.
>
> To paraphrase:
> "The register map is the same, except for the bit that is different".
> If ADI is shipping several different configurations of this IP for
> different DACs, I'd be expecting different compatibles for each backend
> to be honest.
Yes, pretty much we have a generic core with most of the designs being based on
it but with some slight differences. At least for the new ones, almost all of
them have slight deviations from the generic/base core.
> If each DAC specific backend was to have a unique compatible, would the
> type of bus used be determinable from it? Doesn't have to work for all
> devices from now until the heath death of the universe, but at least for
> the devices that you're currently aware of?
>
My original idea was to have a bus controller boolean for this core at least for
now that we only have one bus type (so we could assume qspi in the driver). If
the time comes we need to add support for something else, then we would need
another property to identify the type.
> > > If, as you mentioned, there are multiple bus types, a non-flag property
> > > does make sense. However, I am really not keen on these "forced" numerical
> > > properties at all, I'd much rather see strings used here.
>
> > > > + maxItems: 1
> > > > + description: |
> > > > + Configure bus type:
> > > > + - 0: none
> > > > + - 1: qspi
>
> Also, re-reading the cover letter, it says "this platform driver uses a 4
> lanes parallel bus, plus a clock line, similar to a qspi."
> I don't think we should call this "qspi" if it is not actually qspi,
> that's just confusing.
>
Just by looking at the datasheet it feels like typical qspi to be honest. And,
fwiw, even if not really qspi, this is how the datasheet names the interface.
- Nuno Sá
> >
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 2/8] iio: backend: extend features
2024-09-04 12:01 ` Angelo Dureghello
@ 2024-09-05 10:28 ` Nuno Sá
2024-09-07 14:02 ` Jonathan Cameron
0 siblings, 1 reply; 54+ messages in thread
From: Nuno Sá @ 2024-09-05 10:28 UTC (permalink / raw)
To: Angelo Dureghello, Jonathan Cameron
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Wed, 2024-09-04 at 14:01 +0200, Angelo Dureghello wrote:
> Hi Jonathan,
>
> On 03/09/24 9:11 PM, Jonathan Cameron wrote:
> > On Mon, 2 Sep 2024 16:03:22 +0200
> > Angelo Dureghello <adureghello@baylibre.com> wrote:
> >
> > > Hi Jonathan,
> > >
> > > thanks for the feedbacks,
> > >
> > > On 31/08/24 1:23 PM, Jonathan Cameron wrote:
> > > > On Thu, 29 Aug 2024 14:32:00 +0200
> > > > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > > >
> > > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > > >
> > > > > Extend backend features with new calls needed later on this
> > > > > patchset from axi version of ad3552r.
> > > > >
> > > > > A bus type property has been added to the devicetree to
> > > > > inform the backend about the type of bus (interface) in use
> > > > > bu the IP.
> > > > >
> > > > > The follwoing calls are added:
> > > > >
> > > > > iio_backend_ext_sync_enable
> > > > > enable synchronize channels on external trigger
> > > > > iio_backend_ext_sync_disable
> > > > > disable synchronize channels on external trigger
> > > > > iio_backend_ddr_enable
> > > > > enable ddr bus transfer
> > > > > iio_backend_ddr_disable
> > > > > disable ddr bus transfer
> > > > > iio_backend_set_bus_mode
> > > > > select the type of bus, so that specific read / write
> > > > > operations are performed accordingly
> > > > > iio_backend_buffer_enable
> > > > > enable buffer
> > > > > iio_backend_buffer_disable
> > > > > disable buffer
> > > > > iio_backend_data_transfer_addr
> > > > > define the target register address where the DAC sample
> > > > > will be written.
> > > > > iio_backend_bus_reg_read
> > > > > generic bus read, bus-type dependent
> > > > > iio_backend_bus_read_write
> > > > > generic bus write, bus-type dependent
> > > > >
> > > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > > > ---
> > > > > drivers/iio/industrialio-backend.c | 151
> > > > > +++++++++++++++++++++++++++++++++++++
> > > > > include/linux/iio/backend.h | 24 ++++++
> > > > > 2 files changed, 175 insertions(+)
> > > > >
> > > > > diff --git a/drivers/iio/industrialio-backend.c
> > > > > b/drivers/iio/industrialio-backend.c
> > > > > index a52a6b61c8b5..1f60c8626be7 100644
> > > > > --- a/drivers/iio/industrialio-backend.c
> > > > > +++ b/drivers/iio/industrialio-backend.c
> > > > > @@ -718,6 +718,157 @@ static int __devm_iio_backend_get(struct device
> > > > > *dev, struct iio_backend *back)
> > > > > return 0;
> > > > > }
> > > >
> > > > > +
> > > > > +/**
> > > > > + * iio_backend_buffer_enable - Enable data buffering
> > > > Data buffering is a very vague term. Perhaps some more detail on what
> > > > this means?
> > > for this DAC IP, it is the dma buffer where i write the samples,
> > > for other non-dac frontends may be something different, so i kept it
> > > generic. Not sure what a proper name may be, maybe
> > >
> > > "Enable optional data buffer" ?
> > How do you 'enable' a buffer? Enable writing into it maybe?
>
> for the current case, this is done using the custom register
> of the AXI IP, enabling a "stream".
>
> return regmap_set_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
> AXI_DAC_STREAM_ENABLE);
>
> Functionally, looks like dma data is processed (sent over qspi)
> when the stream is enabled.
>
> Maybe a name as "stream_enable" would me more appropriate ?
> "Stream" seems less generic btw.
>
Yes, stream enable is very specific for this usecase. This is basically
connected to typical IIO buffering. So maybe we could either:
1) Embed struct iio_buffer_setup_ops in the backend ops struct;
2) Or just define directly the ones we need now in backend ops.
> > >
> > > > > + * @back: Backend device
> > > > > + *
> > > > > + * RETURNS:
> > > > > + * 0 on success, negative error number on failure.
> > > > > + */
> > > > > +int iio_backend_buffer_enable(struct iio_backend *back)
> > > > > +{
> > > > > + return iio_backend_op_call(back, buffer_enable);
> > > > > +}
> > > > > +EXPORT_SYMBOL_NS_GPL(iio_backend_buffer_enable, IIO_BACKEND);
> > > > > +
> > > > > +/**
> > > > > +/**
> > > > > + * iio_backend_bus_reg_read - Read from the interface bus
> > > > > + * @back: Backend device
> > > > > + * @reg: Register valule
> > > > > + * @val: Pointer to register value
> > > > > + * @size: Size, in bytes
> > > > > + *
> > > > > + * A backend may operate on a specific interface with a related bus.
> > > > > + * Read from the interface bus.
> > > > So this is effectively routing control plane data through the offloaded
> > > > bus? That sounds a lot more like a conventional bus than IIO backend.
> > > > Perhaps it should be presented as that with the IIO device attached
> > > > to that bus? I don't fully understand what is wired up here.
> > > >
> > > Mainly, an IP may include a bus as 16bit parallel, or LVDS, or similar
> > > to QSPI as in my case (ad3552r).
> > ok.
> >
> > If this is a bus used for both control and dataplane, then we should really
> > be presenting it as a bus (+ offload) similar to do for spi + offload.
> >
Yes, indeed. In this case we also use the axi-dac core for controlling the
frontend device (accessing it's register) which is fairly weird. But not sure
how we can do it differently. For the spi_engine that is really a spi controller
with the extra offloading capability. For this one, it's now "acting" as a spi
controller but in the future it may also "act" as a parallel controller (the
axi-adc already is in works for that with the ad7606 series).
I was also very skeptical when I first saw these new functions but I'm not
really sure how to do it differently. I mean, it also does not make much sense
to have an additional bus driver as the register maps are the same. Not sure if
turning it in a MFD device, helps...
FWIW, I still don't fully understand why can't we have this supported by the
spi_engine core. My guess is that we need features from the axi-dac (for the
dataplane) so we are incorporating the controlplane on it instead of going
spi_engine + axi-dac.
Also want to leave a quick note about LVDS (that was mentioned). That interface
is typically only used for data so I'm not seeing any special handling like this
for that interface.
- Nuno Sá
> >
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 3/8] iio: backend adi-axi-dac: backend features
2024-09-03 19:16 ` Jonathan Cameron
@ 2024-09-05 10:49 ` Nuno Sá
2024-09-05 11:58 ` Angelo Dureghello
2024-09-05 12:11 ` Angelo Dureghello
0 siblings, 2 replies; 54+ messages in thread
From: Nuno Sá @ 2024-09-05 10:49 UTC (permalink / raw)
To: Jonathan Cameron, Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Tue, 2024-09-03 at 20:16 +0100, Jonathan Cameron wrote:
> On Mon, 2 Sep 2024 18:04:51 +0200
> Angelo Dureghello <adureghello@baylibre.com> wrote:
>
> > On 31/08/24 1:34 PM, Jonathan Cameron wrote:
> > > On Thu, 29 Aug 2024 14:32:01 +0200
> > > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > >
> > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > >
> > > > Extend DAC backend with new features required for the AXI driver
> > > > version for the a3552r DAC.
> > > >
> > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > Hi Angelo
> > > Minor comments inline.
> > > >
> > > > static int axi_dac_enable(struct iio_backend *back)
> > > > @@ -460,7 +493,13 @@ static int axi_dac_data_source_set(struct
> > > > iio_backend *back, unsigned int chan,
> > > > case IIO_BACKEND_EXTERNAL:
> > > > return regmap_update_bits(st->regmap,
> > > >
> > > > AXI_DAC_REG_CHAN_CNTRL_7(chan),
> > > > - AXI_DAC_DATA_SEL,
> > > > AXI_DAC_DATA_DMA);
> > > > + AXI_DAC_DATA_SEL,
> > > > + AXI_DAC_DATA_DMA);
> > > Unrelated change. If you want to change this, separate patch.
> > Thanks, fixed.
> > >
> > > > + case IIO_BACKEND_INTERNAL_RAMP_16:
> > > > + return regmap_update_bits(st->regmap,
> > > > +
> > > > AXI_DAC_REG_CHAN_CNTRL_7(chan),
> > > > + AXI_DAC_DATA_SEL,
> > > > +
> > > > AXI_DAC_DATA_INTERNAL_RAMP_16);
> > > > default:
> > > > return -EINVAL;
> > > > }
> > > > @@ -518,9 +557,204 @@ static int axi_dac_reg_access(struct iio_backend
> > > > *back, unsigned int reg,
> > > > return regmap_write(st->regmap, reg, writeval);
> > > > }
> > > >
> > > > +
> > > > +static int axi_dac_bus_reg_write(struct iio_backend *back,
> > > > + u32 reg, void *val, size_t size)
> > > Maybe just pass an unsigned int for val?
> > > So follow what regmap does? You will still need the size, but it
> > > will just be configuration related rather than affecting the type
> > > of val.
> > >
> > void * was used since data size in the future may vary depending
> > on the bus physical interface.
> >
> I doubt it will get bigger than u64. Passing void * is always
> nasty if we can do something else and this is a register writing
> operation. I'm yet to meet an ADC or similar with > 64 bit registers
> (or even one with 64 bit ones!)
I think the original thinking was to support thinks like appending crc to the
register read/write. But even in that case, u32 for val might be enough. Not
sure. Anyways, as you often say with the backend stuff, this is all in the
kernel so I guess we can change it to unsigned int and change it in the future
if we need to.
Since you mentioned regmap, I also want to bring something that was discussed
before the RFC. Basically we talked about having the backend registering it's
own regmap_bus. Then we would either:
1) Have a specific get_regmap_bus() callback for the frontend to initialize a
regmap on;
2) Pass this bus into the core and have a new frontend API like
devm_iio_backend_regmap_init().
Then, on top of the API already provided by regmap (like _update_bit()), the
frontend could just use regmap independent of having a backend or not.
The current API is likely more generic but tbh (and David and Angelo are aware
of it) my preferred approach it to use the regmap_bus stuff. I just don't feel
that strong about it :)
>
> > Actually, a reg bus write involves several AXI regmap operations.
> > >
> > > > +{
> > > > + struct axi_dac_state *st = iio_backend_get_priv(back);
> > > > +
> > > > + if (!st->bus_type)
> > > > + return -EOPNOTSUPP;
> > > > +
> > > > + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
> > > As below, I'd use a switch and factor out this block as a separate
> > > bus specific function.
> > Ok, changed.
> > >
> > > > + int ret;
> > > > + u32 ival;
> > > > +
> > > > + if (size != 1 && size != 2)
> > > > + return -EINVAL;
> > > > +
> > > > + switch (size) {
> > > > + case 1:
> > > > + ival = FIELD_PREP(AXI_DAC_DATA_WR_8, *(u8
> > > > *)val);
> > > > + break;
> > > > + case 2:
> > > > + ival = FIELD_PREP(AXI_DAC_DATA_WR_16, *(u16
> > > > *)val);
> > > > + break;
> > > > + default:
> > > > + return -EINVAL;
> > > Hopefully compiler won't need this and the above. I'd drop the size != 1..
> > > check in favour of just doing it in this switch.
> > >
> > sure, done.
> >
> >
> > > > + }
> > > > +
> > > > + ret = regmap_write(st->regmap, AXI_DAC_CNTRL_DATA_WR,
> > > > ival);
> > > > + if (ret)
> > > > + return ret;
> > > > +
> > > > + /*
> > > > + * Both REG_CNTRL_2 and AXI_DAC_CNTRL_DATA_WR need to
> > > > know
> > > > + * the data size. So keeping data size control here
> > > > only,
> > > > + * since data size is mandatory for to the current
> > > > transfer.
> > > > + * DDR state handled separately by specific backend
> > > > calls,
> > > > + * generally all raw register writes are SDR.
> > > > + */
> > > > + if (size == 1)
> > > > + ret = regmap_set_bits(st->regmap,
> > > > AXI_DAC_REG_CNTRL_2,
> > > > + AXI_DAC_SYMB_8B);
> > > > + else
> > > > + ret = regmap_clear_bits(st->regmap,
> > > > AXI_DAC_REG_CNTRL_2,
> > > > + AXI_DAC_SYMB_8B);
> > > > + if (ret)
> > > > + return ret;
> > > > +
> > > > + ret = regmap_update_bits(st->regmap,
> > > > AXI_DAC_REG_CUSTOM_CTRL,
> > > > + AXI_DAC_ADDRESS,
> > > > + FIELD_PREP(AXI_DAC_ADDRESS,
> > > > reg));
> > > > + if (ret)
> > > > + return ret;
> > > > +
> > > > + ret = regmap_update_bits(st->regmap,
> > > > AXI_DAC_REG_CUSTOM_CTRL,
> > > > + AXI_DAC_TRANSFER_DATA,
> > > > + AXI_DAC_TRANSFER_DATA);
> > > > + if (ret)
> > > > + return ret;
> > > > +
> > > > + ret = regmap_read_poll_timeout(st->regmap,
> > > > + AXI_DAC_REG_CUSTOM_CTRL,
> > > > ival,
> > > > + ival &
> > > > AXI_DAC_TRANSFER_DATA,
> > > > + 10, 100 * KILO);
> > > > + if (ret)
> > > > + return ret;
> > > > +
> > > > + return regmap_clear_bits(st->regmap,
> > > > AXI_DAC_REG_CUSTOM_CTRL,
> > > > + AXI_DAC_TRANSFER_DATA);
> > > > + }
> > > > +
> > > > + return -EINVAL;
> > > > +}
> > > > +
> > > > +static int axi_dac_bus_reg_read(struct iio_backend *back,
> > > > + u32 reg, void *val, size_t size)
> > > As for write, I'd just use an unsigned int * for val like
> > > regmap does.
> >
> > Ok, so initial choice was unsigned int, further thinking of
> > possible future busses drive the choice to void *.
> >
> > Let me know, i can switch to unsigned int in case.
> I would just go with unsigned int or at a push u64 *
>
> >
> >
> > >
> > >
> > > > +{
> > > > + struct axi_dac_state *st = iio_backend_get_priv(back);
> > > > +
> > > > + if (!st->bus_type)
> > > > + return -EOPNOTSUPP;
> > > > +
> > > > + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
> > > It got mentioned in binding review but if this isn't QSPI, even
> > > if similar don't call it that.
> >
> > It's a bit difficult to find a different name, physically,
> > it is a QSPI, 4 lanes + clock + cs, and datasheet is naming it Quad SPI.
> > But looking the data protocol, it's a bit different.
>
> is QSPI actually defined anywhere? I assumed it would be like
> SPI for which everything is so flexible you can build whatever you like.
>
> >
> > QSPI has instruction, address and data.
> > Here we have just ADDR and DATA.
> >
I'm not sure the instruction is really relevant for this. From a quick look, it
feels like something used for accessing external flash memory like spi-nors. So,
I would not be surprised if things are just like Jonathan said and this is just
flexible as spi (being that extra instruction field a protocol defined for flash
memory - where one typically sees this interface)
- Nuno Sá
>
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 3/8] iio: backend adi-axi-dac: backend features
2024-09-05 10:49 ` Nuno Sá
@ 2024-09-05 11:58 ` Angelo Dureghello
2024-09-06 5:54 ` Nuno Sá
2024-09-05 12:11 ` Angelo Dureghello
1 sibling, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-09-05 11:58 UTC (permalink / raw)
To: Nuno Sá, Jonathan Cameron
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
Hi,
On 05/09/24 12:49 PM, Nuno Sá wrote:
> On Tue, 2024-09-03 at 20:16 +0100, Jonathan Cameron wrote:
>> On Mon, 2 Sep 2024 18:04:51 +0200
>> Angelo Dureghello <adureghello@baylibre.com> wrote:
>>
>>> On 31/08/24 1:34 PM, Jonathan Cameron wrote:
>>>> On Thu, 29 Aug 2024 14:32:01 +0200
>>>> Angelo Dureghello <adureghello@baylibre.com> wrote:
>>>>
>>>>> From: Angelo Dureghello <adureghello@baylibre.com>
>>>>>
>>>>> Extend DAC backend with new features required for the AXI driver
>>>>> version for the a3552r DAC.
>>>>>
>>>>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>>>> Hi Angelo
>>>> Minor comments inline.
>>>>>
>>>>> static int axi_dac_enable(struct iio_backend *back)
>>>>> @@ -460,7 +493,13 @@ static int axi_dac_data_source_set(struct
>>>>> iio_backend *back, unsigned int chan,
>>>>> case IIO_BACKEND_EXTERNAL:
>>>>> return regmap_update_bits(st->regmap,
>>>>>
>>>>> AXI_DAC_REG_CHAN_CNTRL_7(chan),
>>>>> - AXI_DAC_DATA_SEL,
>>>>> AXI_DAC_DATA_DMA);
>>>>> + AXI_DAC_DATA_SEL,
>>>>> + AXI_DAC_DATA_DMA);
>>>> Unrelated change. If you want to change this, separate patch.
>>> Thanks, fixed.
>>>>
>>>>> + case IIO_BACKEND_INTERNAL_RAMP_16:
>>>>> + return regmap_update_bits(st->regmap,
>>>>> +
>>>>> AXI_DAC_REG_CHAN_CNTRL_7(chan),
>>>>> + AXI_DAC_DATA_SEL,
>>>>> +
>>>>> AXI_DAC_DATA_INTERNAL_RAMP_16);
>>>>> default:
>>>>> return -EINVAL;
>>>>> }
>>>>> @@ -518,9 +557,204 @@ static int axi_dac_reg_access(struct iio_backend
>>>>> *back, unsigned int reg,
>>>>> return regmap_write(st->regmap, reg, writeval);
>>>>> }
>>>>>
>>>>> +
>>>>> +static int axi_dac_bus_reg_write(struct iio_backend *back,
>>>>> + u32 reg, void *val, size_t size)
>>>> Maybe just pass an unsigned int for val?
>>>> So follow what regmap does? You will still need the size, but it
>>>> will just be configuration related rather than affecting the type
>>>> of val.
>>>>
>>> void * was used since data size in the future may vary depending
>>> on the bus physical interface.
>>>
>> I doubt it will get bigger than u64. Passing void * is always
>> nasty if we can do something else and this is a register writing
>> operation. I'm yet to meet an ADC or similar with > 64 bit registers
>> (or even one with 64 bit ones!)
> I think the original thinking was to support thinks like appending crc to the
> register read/write. But even in that case, u32 for val might be enough. Not
> sure. Anyways, as you often say with the backend stuff, this is all in the
> kernel so I guess we can change it to unsigned int and change it in the future
> if we need to.
>
> Since you mentioned regmap, I also want to bring something that was discussed
> before the RFC. Basically we talked about having the backend registering it's
> own regmap_bus. Then we would either:
>
> 1) Have a specific get_regmap_bus() callback for the frontend to initialize a
> regmap on;
> 2) Pass this bus into the core and have a new frontend API like
> devm_iio_backend_regmap_init().
>
> Then, on top of the API already provided by regmap (like _update_bit()), the
> frontend could just use regmap independent of having a backend or not.
>
> The current API is likely more generic but tbh (and David and Angelo are aware
> of it) my preferred approach it to use the regmap_bus stuff. I just don't feel
> that strong about it :)
>
>>> Actually, a reg bus write involves several AXI regmap operations.
>>>>
>>>>> +{
>>>>> + struct axi_dac_state *st = iio_backend_get_priv(back);
>>>>> +
>>>>> + if (!st->bus_type)
>>>>> + return -EOPNOTSUPP;
>>>>> +
>>>>> + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
>>>> As below, I'd use a switch and factor out this block as a separate
>>>> bus specific function.
>>> Ok, changed.
>>>>
>>>>> + int ret;
>>>>> + u32 ival;
>>>>> +
>>>>> + if (size != 1 && size != 2)
>>>>> + return -EINVAL;
>>>>> +
>>>>> + switch (size) {
>>>>> + case 1:
>>>>> + ival = FIELD_PREP(AXI_DAC_DATA_WR_8, *(u8
>>>>> *)val);
>>>>> + break;
>>>>> + case 2:
>>>>> + ival = FIELD_PREP(AXI_DAC_DATA_WR_16, *(u16
>>>>> *)val);
>>>>> + break;
>>>>> + default:
>>>>> + return -EINVAL;
>>>> Hopefully compiler won't need this and the above. I'd drop the size != 1..
>>>> check in favour of just doing it in this switch.
>>>>
>>> sure, done.
>>>
>>>
>>>>> + }
>>>>> +
>>>>> + ret = regmap_write(st->regmap, AXI_DAC_CNTRL_DATA_WR,
>>>>> ival);
>>>>> + if (ret)
>>>>> + return ret;
>>>>> +
>>>>> + /*
>>>>> + * Both REG_CNTRL_2 and AXI_DAC_CNTRL_DATA_WR need to
>>>>> know
>>>>> + * the data size. So keeping data size control here
>>>>> only,
>>>>> + * since data size is mandatory for to the current
>>>>> transfer.
>>>>> + * DDR state handled separately by specific backend
>>>>> calls,
>>>>> + * generally all raw register writes are SDR.
>>>>> + */
>>>>> + if (size == 1)
>>>>> + ret = regmap_set_bits(st->regmap,
>>>>> AXI_DAC_REG_CNTRL_2,
>>>>> + AXI_DAC_SYMB_8B);
>>>>> + else
>>>>> + ret = regmap_clear_bits(st->regmap,
>>>>> AXI_DAC_REG_CNTRL_2,
>>>>> + AXI_DAC_SYMB_8B);
>>>>> + if (ret)
>>>>> + return ret;
>>>>> +
>>>>> + ret = regmap_update_bits(st->regmap,
>>>>> AXI_DAC_REG_CUSTOM_CTRL,
>>>>> + AXI_DAC_ADDRESS,
>>>>> + FIELD_PREP(AXI_DAC_ADDRESS,
>>>>> reg));
>>>>> + if (ret)
>>>>> + return ret;
>>>>> +
>>>>> + ret = regmap_update_bits(st->regmap,
>>>>> AXI_DAC_REG_CUSTOM_CTRL,
>>>>> + AXI_DAC_TRANSFER_DATA,
>>>>> + AXI_DAC_TRANSFER_DATA);
>>>>> + if (ret)
>>>>> + return ret;
>>>>> +
>>>>> + ret = regmap_read_poll_timeout(st->regmap,
>>>>> + AXI_DAC_REG_CUSTOM_CTRL,
>>>>> ival,
>>>>> + ival &
>>>>> AXI_DAC_TRANSFER_DATA,
>>>>> + 10, 100 * KILO);
>>>>> + if (ret)
>>>>> + return ret;
>>>>> +
>>>>> + return regmap_clear_bits(st->regmap,
>>>>> AXI_DAC_REG_CUSTOM_CTRL,
>>>>> + AXI_DAC_TRANSFER_DATA);
>>>>> + }
>>>>> +
>>>>> + return -EINVAL;
>>>>> +}
>>>>> +
>>>>> +static int axi_dac_bus_reg_read(struct iio_backend *back,
>>>>> + u32 reg, void *val, size_t size)
>>>> As for write, I'd just use an unsigned int * for val like
>>>> regmap does.
>>> Ok, so initial choice was unsigned int, further thinking of
>>> possible future busses drive the choice to void *.
>>>
>>> Let me know, i can switch to unsigned int in case.
>> I would just go with unsigned int or at a push u64 *
>>
>>>
>>>>
>>>>> +{
>>>>> + struct axi_dac_state *st = iio_backend_get_priv(back);
>>>>> +
>>>>> + if (!st->bus_type)
>>>>> + return -EOPNOTSUPP;
>>>>> +
>>>>> + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
>>>> It got mentioned in binding review but if this isn't QSPI, even
>>>> if similar don't call it that.
>>> It's a bit difficult to find a different name, physically,
>>> it is a QSPI, 4 lanes + clock + cs, and datasheet is naming it Quad SPI.
>>> But looking the data protocol, it's a bit different.
>> is QSPI actually defined anywhere? I assumed it would be like
>> SPI for which everything is so flexible you can build whatever you like.
>>
>>> QSPI has instruction, address and data.
>>> Here we have just ADDR and DATA.
>>>
> I'm not sure the instruction is really relevant for this. From a quick look, it
> feels like something used for accessing external flash memory like spi-nors. So,
> I would not be surprised if things are just like Jonathan said and this is just
> flexible as spi (being that extra instruction field a protocol defined for flash
> memory - where one typically sees this interface)
Ok, so QSPI is the hardware, and the protocol on it may vary for the target
chip/application.
Looks like DDR makes the 33MUPS rate reachable, and not all the controllers
have DDR mode. Also some controllers are supposed to work with a QSPI flash
(so with instructions), and likely this reason driven the need to use a
custom IP.
Regards,
Angelo
> - Nuno Sá
--
,,, Angelo Dureghello
:: :. BayLibre -runtime team- Developer
:`___:
`____:
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 3/8] iio: backend adi-axi-dac: backend features
2024-09-05 10:49 ` Nuno Sá
2024-09-05 11:58 ` Angelo Dureghello
@ 2024-09-05 12:11 ` Angelo Dureghello
2024-09-06 5:53 ` Nuno Sá
1 sibling, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-09-05 12:11 UTC (permalink / raw)
To: Nuno Sá, Jonathan Cameron
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
Hi,
sorry forgot to reply about the regmap,
On 05/09/24 12:49 PM, Nuno Sá wrote:
> On Tue, 2024-09-03 at 20:16 +0100, Jonathan Cameron wrote:
>> On Mon, 2 Sep 2024 18:04:51 +0200
>> Angelo Dureghello <adureghello@baylibre.com> wrote:
>>
>>> On 31/08/24 1:34 PM, Jonathan Cameron wrote:
>>>> On Thu, 29 Aug 2024 14:32:01 +0200
>>>> Angelo Dureghello <adureghello@baylibre.com> wrote:
>>>>
>>>>> From: Angelo Dureghello <adureghello@baylibre.com>
>>>>>
>>>>> Extend DAC backend with new features required for the AXI driver
>>>>> version for the a3552r DAC.
>>>>>
>>>>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>>>> Hi Angelo
>>>> Minor comments inline.
>>>>>
>>>>> static int axi_dac_enable(struct iio_backend *back)
>>>>> @@ -460,7 +493,13 @@ static int axi_dac_data_source_set(struct
>>>>> iio_backend *back, unsigned int chan,
>>>>> case IIO_BACKEND_EXTERNAL:
>>>>> return regmap_update_bits(st->regmap,
>>>>>
>>>>> AXI_DAC_REG_CHAN_CNTRL_7(chan),
>>>>> - AXI_DAC_DATA_SEL,
>>>>> AXI_DAC_DATA_DMA);
>>>>> + AXI_DAC_DATA_SEL,
>>>>> + AXI_DAC_DATA_DMA);
>>>> Unrelated change. If you want to change this, separate patch.
>>> Thanks, fixed.
>>>>
>>>>> + case IIO_BACKEND_INTERNAL_RAMP_16:
>>>>> + return regmap_update_bits(st->regmap,
>>>>> +
>>>>> AXI_DAC_REG_CHAN_CNTRL_7(chan),
>>>>> + AXI_DAC_DATA_SEL,
>>>>> +
>>>>> AXI_DAC_DATA_INTERNAL_RAMP_16);
>>>>> default:
>>>>> return -EINVAL;
>>>>> }
>>>>> @@ -518,9 +557,204 @@ static int axi_dac_reg_access(struct iio_backend
>>>>> *back, unsigned int reg,
>>>>> return regmap_write(st->regmap, reg, writeval);
>>>>> }
>>>>>
>>>>> +
>>>>> +static int axi_dac_bus_reg_write(struct iio_backend *back,
>>>>> + u32 reg, void *val, size_t size)
>>>> Maybe just pass an unsigned int for val?
>>>> So follow what regmap does? You will still need the size, but it
>>>> will just be configuration related rather than affecting the type
>>>> of val.
>>>>
>>> void * was used since data size in the future may vary depending
>>> on the bus physical interface.
>>>
>> I doubt it will get bigger than u64. Passing void * is always
>> nasty if we can do something else and this is a register writing
>> operation. I'm yet to meet an ADC or similar with > 64 bit registers
>> (or even one with 64 bit ones!)
> I think the original thinking was to support thinks like appending crc to the
> register read/write. But even in that case, u32 for val might be enough. Not
> sure. Anyways, as you often say with the backend stuff, this is all in the
> kernel so I guess we can change it to unsigned int and change it in the future
> if we need to.
>
> Since you mentioned regmap, I also want to bring something that was discussed
> before the RFC. Basically we talked about having the backend registering it's
> own regmap_bus. Then we would either:
>
> 1) Have a specific get_regmap_bus() callback for the frontend to initialize a
> regmap on;
> 2) Pass this bus into the core and have a new frontend API like
> devm_iio_backend_regmap_init().
>
> Then, on top of the API already provided by regmap (like _update_bit()), the
> frontend could just use regmap independent of having a backend or not.
>
> The current API is likely more generic but tbh (and David and Angelo are aware
> of it) my preferred approach it to use the regmap_bus stuff. I just don't feel
> that strong about it :)
regmap idea seems really nice and a better style.
Honestly, if possible, would not go for it right now.
The main reason is that i am on this work from months and it would
require a quite
big rework (also rearranging more common code, retest, etc) while i am
trying to
finalize a first driver.
If you agree, this could come in a second "cleanup" patchset, but at
least i can
provide an initial support for ad3552r.
>>> Actually, a reg bus write involves several AXI regmap operations.
>>>>
>>>>> +{
>>>>> + struct axi_dac_state *st = iio_backend_get_priv(back);
>>>>> +
>>>>> + if (!st->bus_type)
>>>>> + return -EOPNOTSUPP;
>>>>> +
>>>>> + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
>>>> As below, I'd use a switch and factor out this block as a separate
>>>> bus specific function.
>>> Ok, changed.
>>>>
>>>>> + int ret;
>>>>> + u32 ival;
>>>>> +
>>>>> + if (size != 1 && size != 2)
>>>>> + return -EINVAL;
>>>>> +
>>>>> + switch (size) {
>>>>> + case 1:
>>>>> + ival = FIELD_PREP(AXI_DAC_DATA_WR_8, *(u8
>>>>> *)val);
>>>>> + break;
>>>>> + case 2:
>>>>> + ival = FIELD_PREP(AXI_DAC_DATA_WR_16, *(u16
>>>>> *)val);
>>>>> + break;
>>>>> + default:
>>>>> + return -EINVAL;
>>>> Hopefully compiler won't need this and the above. I'd drop the size != 1..
>>>> check in favour of just doing it in this switch.
>>>>
>>> sure, done.
>>>
>>>
>>>>> + }
>>>>> +
>>>>> + ret = regmap_write(st->regmap, AXI_DAC_CNTRL_DATA_WR,
>>>>> ival);
>>>>> + if (ret)
>>>>> + return ret;
>>>>> +
>>>>> + /*
>>>>> + * Both REG_CNTRL_2 and AXI_DAC_CNTRL_DATA_WR need to
>>>>> know
>>>>> + * the data size. So keeping data size control here
>>>>> only,
>>>>> + * since data size is mandatory for to the current
>>>>> transfer.
>>>>> + * DDR state handled separately by specific backend
>>>>> calls,
>>>>> + * generally all raw register writes are SDR.
>>>>> + */
>>>>> + if (size == 1)
>>>>> + ret = regmap_set_bits(st->regmap,
>>>>> AXI_DAC_REG_CNTRL_2,
>>>>> + AXI_DAC_SYMB_8B);
>>>>> + else
>>>>> + ret = regmap_clear_bits(st->regmap,
>>>>> AXI_DAC_REG_CNTRL_2,
>>>>> + AXI_DAC_SYMB_8B);
>>>>> + if (ret)
>>>>> + return ret;
>>>>> +
>>>>> + ret = regmap_update_bits(st->regmap,
>>>>> AXI_DAC_REG_CUSTOM_CTRL,
>>>>> + AXI_DAC_ADDRESS,
>>>>> + FIELD_PREP(AXI_DAC_ADDRESS,
>>>>> reg));
>>>>> + if (ret)
>>>>> + return ret;
>>>>> +
>>>>> + ret = regmap_update_bits(st->regmap,
>>>>> AXI_DAC_REG_CUSTOM_CTRL,
>>>>> + AXI_DAC_TRANSFER_DATA,
>>>>> + AXI_DAC_TRANSFER_DATA);
>>>>> + if (ret)
>>>>> + return ret;
>>>>> +
>>>>> + ret = regmap_read_poll_timeout(st->regmap,
>>>>> + AXI_DAC_REG_CUSTOM_CTRL,
>>>>> ival,
>>>>> + ival &
>>>>> AXI_DAC_TRANSFER_DATA,
>>>>> + 10, 100 * KILO);
>>>>> + if (ret)
>>>>> + return ret;
>>>>> +
>>>>> + return regmap_clear_bits(st->regmap,
>>>>> AXI_DAC_REG_CUSTOM_CTRL,
>>>>> + AXI_DAC_TRANSFER_DATA);
>>>>> + }
>>>>> +
>>>>> + return -EINVAL;
>>>>> +}
>>>>> +
>>>>> +static int axi_dac_bus_reg_read(struct iio_backend *back,
>>>>> + u32 reg, void *val, size_t size)
>>>> As for write, I'd just use an unsigned int * for val like
>>>> regmap does.
>>> Ok, so initial choice was unsigned int, further thinking of
>>> possible future busses drive the choice to void *.
>>>
>>> Let me know, i can switch to unsigned int in case.
>> I would just go with unsigned int or at a push u64 *
>>
>>>
>>>>
>>>>> +{
>>>>> + struct axi_dac_state *st = iio_backend_get_priv(back);
>>>>> +
>>>>> + if (!st->bus_type)
>>>>> + return -EOPNOTSUPP;
>>>>> +
>>>>> + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
>>>> It got mentioned in binding review but if this isn't QSPI, even
>>>> if similar don't call it that.
>>> It's a bit difficult to find a different name, physically,
>>> it is a QSPI, 4 lanes + clock + cs, and datasheet is naming it Quad SPI.
>>> But looking the data protocol, it's a bit different.
>> is QSPI actually defined anywhere? I assumed it would be like
>> SPI for which everything is so flexible you can build whatever you like.
>>
>>> QSPI has instruction, address and data.
>>> Here we have just ADDR and DATA.
>>>
> I'm not sure the instruction is really relevant for this. From a quick look, it
> feels like something used for accessing external flash memory like spi-nors. So,
> I would not be surprised if things are just like Jonathan said and this is just
> flexible as spi (being that extra instruction field a protocol defined for flash
> memory - where one typically sees this interface)
>
> - Nuno Sá
regards,
Angelo
--
,,, Angelo Dureghello
:: :. BayLibre -runtime team- Developer
:`___:
`____:
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 3/8] iio: backend adi-axi-dac: backend features
2024-09-05 12:11 ` Angelo Dureghello
@ 2024-09-06 5:53 ` Nuno Sá
0 siblings, 0 replies; 54+ messages in thread
From: Nuno Sá @ 2024-09-06 5:53 UTC (permalink / raw)
To: Angelo Dureghello, Jonathan Cameron
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Thu, 2024-09-05 at 14:11 +0200, Angelo Dureghello wrote:
> Hi,
>
> sorry forgot to reply about the regmap,
>
> On 05/09/24 12:49 PM, Nuno Sá wrote:
> > On Tue, 2024-09-03 at 20:16 +0100, Jonathan Cameron wrote:
> > > On Mon, 2 Sep 2024 18:04:51 +0200
> > > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > >
> > > > On 31/08/24 1:34 PM, Jonathan Cameron wrote:
> > > > > On Thu, 29 Aug 2024 14:32:01 +0200
> > > > > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > > > >
> > > > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > > > >
> > > > > > Extend DAC backend with new features required for the AXI driver
> > > > > > version for the a3552r DAC.
> > > > > >
> > > > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > > > Hi Angelo
> > > > > Minor comments inline.
> > > > > >
> > > > > > static int axi_dac_enable(struct iio_backend *back)
> > > > > > @@ -460,7 +493,13 @@ static int axi_dac_data_source_set(struct
> > > > > > iio_backend *back, unsigned int chan,
> > > > > > case IIO_BACKEND_EXTERNAL:
> > > > > > return regmap_update_bits(st->regmap,
> > > > > >
> > > > > > AXI_DAC_REG_CHAN_CNTRL_7(chan),
> > > > > > - AXI_DAC_DATA_SEL,
> > > > > > AXI_DAC_DATA_DMA);
> > > > > > + AXI_DAC_DATA_SEL,
> > > > > > + AXI_DAC_DATA_DMA);
> > > > > Unrelated change. If you want to change this, separate patch.
> > > > Thanks, fixed.
> > > > >
> > > > > > + case IIO_BACKEND_INTERNAL_RAMP_16:
> > > > > > + return regmap_update_bits(st->regmap,
> > > > > > +
> > > > > > AXI_DAC_REG_CHAN_CNTRL_7(chan),
> > > > > > + AXI_DAC_DATA_SEL,
> > > > > > +
> > > > > > AXI_DAC_DATA_INTERNAL_RAMP_16);
> > > > > > default:
> > > > > > return -EINVAL;
> > > > > > }
> > > > > > @@ -518,9 +557,204 @@ static int axi_dac_reg_access(struct iio_backend
> > > > > > *back, unsigned int reg,
> > > > > > return regmap_write(st->regmap, reg, writeval);
> > > > > > }
> > > > > >
> > > > > > +
> > > > > > +static int axi_dac_bus_reg_write(struct iio_backend *back,
> > > > > > + u32 reg, void *val, size_t size)
> > > > > Maybe just pass an unsigned int for val?
> > > > > So follow what regmap does? You will still need the size, but it
> > > > > will just be configuration related rather than affecting the type
> > > > > of val.
> > > > >
> > > > void * was used since data size in the future may vary depending
> > > > on the bus physical interface.
> > > >
> > > I doubt it will get bigger than u64. Passing void * is always
> > > nasty if we can do something else and this is a register writing
> > > operation. I'm yet to meet an ADC or similar with > 64 bit registers
> > > (or even one with 64 bit ones!)
> > I think the original thinking was to support thinks like appending crc to the
> > register read/write. But even in that case, u32 for val might be enough. Not
> > sure. Anyways, as you often say with the backend stuff, this is all in the
> > kernel so I guess we can change it to unsigned int and change it in the future
> > if we need to.
> >
> > Since you mentioned regmap, I also want to bring something that was discussed
> > before the RFC. Basically we talked about having the backend registering it's
> > own regmap_bus. Then we would either:
> >
> > 1) Have a specific get_regmap_bus() callback for the frontend to initialize a
> > regmap on;
> > 2) Pass this bus into the core and have a new frontend API like
> > devm_iio_backend_regmap_init().
> >
> > Then, on top of the API already provided by regmap (like _update_bit()), the
> > frontend could just use regmap independent of having a backend or not.
> >
> > The current API is likely more generic but tbh (and David and Angelo are aware
> > of it) my preferred approach it to use the regmap_bus stuff. I just don't feel
> > that strong about it :)
>
> regmap idea seems really nice and a better style.
>
> Honestly, if possible, would not go for it right now.
> The main reason is that i am on this work from months and it would
> require a quite
> big rework (also rearranging more common code, retest, etc) while i am
> trying to
> finalize a first driver.
>
While I understand your reasoning, I can't really agree with it if we feel regmap is
the better solution. It makes no sense to add something knowing that it will removed
in the next couple of weeks. Actually (and I'm guilty of that too :)), when we say
things like that, odds are we're just leaving things like this.
> If you agree, this could come in a second "cleanup" patchset, but at
> least i can
> provide an initial support for ad3552r.
>
Having said the above, I'm not going to NAK this approach even if it's not my
favorite one :)
- Nuno Sá
> > >
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 3/8] iio: backend adi-axi-dac: backend features
2024-09-05 11:58 ` Angelo Dureghello
@ 2024-09-06 5:54 ` Nuno Sá
0 siblings, 0 replies; 54+ messages in thread
From: Nuno Sá @ 2024-09-06 5:54 UTC (permalink / raw)
To: Angelo Dureghello, Jonathan Cameron
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
devicetree, linux-kernel, dlechner
On Thu, 2024-09-05 at 13:58 +0200, Angelo Dureghello wrote:
> Hi,
>
> On 05/09/24 12:49 PM, Nuno Sá wrote:
> > On Tue, 2024-09-03 at 20:16 +0100, Jonathan Cameron wrote:
> > > On Mon, 2 Sep 2024 18:04:51 +0200
> > > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > >
> > > > On 31/08/24 1:34 PM, Jonathan Cameron wrote:
> > > > > On Thu, 29 Aug 2024 14:32:01 +0200
> > > > > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > > > >
> > > > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > > > >
> > > > > > Extend DAC backend with new features required for the AXI driver
> > > > > > version for the a3552r DAC.
> > > > > >
> > > > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > > > Hi Angelo
> > > > > Minor comments inline.
> > > > > >
> > > > > > static int axi_dac_enable(struct iio_backend *back)
> > > > > > @@ -460,7 +493,13 @@ static int axi_dac_data_source_set(struct
> > > > > > iio_backend *back, unsigned int chan,
> > > > > > case IIO_BACKEND_EXTERNAL:
> > > > > > return regmap_update_bits(st->regmap,
> > > > > >
> > > > > > AXI_DAC_REG_CHAN_CNTRL_7(chan),
> > > > > > - AXI_DAC_DATA_SEL,
> > > > > > AXI_DAC_DATA_DMA);
> > > > > > + AXI_DAC_DATA_SEL,
> > > > > > + AXI_DAC_DATA_DMA);
> > > > > Unrelated change. If you want to change this, separate patch.
> > > > Thanks, fixed.
> > > > >
> > > > > > + case IIO_BACKEND_INTERNAL_RAMP_16:
> > > > > > + return regmap_update_bits(st->regmap,
> > > > > > +
> > > > > > AXI_DAC_REG_CHAN_CNTRL_7(chan),
> > > > > > + AXI_DAC_DATA_SEL,
> > > > > > +
> > > > > > AXI_DAC_DATA_INTERNAL_RAMP_16);
> > > > > > default:
> > > > > > return -EINVAL;
> > > > > > }
> > > > > > @@ -518,9 +557,204 @@ static int axi_dac_reg_access(struct iio_backend
> > > > > > *back, unsigned int reg,
> > > > > > return regmap_write(st->regmap, reg, writeval);
> > > > > > }
> > > > > >
> > > > > > +
> > > > > > +static int axi_dac_bus_reg_write(struct iio_backend *back,
> > > > > > + u32 reg, void *val, size_t size)
> > > > > Maybe just pass an unsigned int for val?
> > > > > So follow what regmap does? You will still need the size, but it
> > > > > will just be configuration related rather than affecting the type
> > > > > of val.
> > > > >
> > > > void * was used since data size in the future may vary depending
> > > > on the bus physical interface.
> > > >
> > > I doubt it will get bigger than u64. Passing void * is always
> > > nasty if we can do something else and this is a register writing
> > > operation. I'm yet to meet an ADC or similar with > 64 bit registers
> > > (or even one with 64 bit ones!)
> > I think the original thinking was to support thinks like appending crc to the
> > register read/write. But even in that case, u32 for val might be enough. Not
> > sure. Anyways, as you often say with the backend stuff, this is all in the
> > kernel so I guess we can change it to unsigned int and change it in the future
> > if we need to.
> >
> > Since you mentioned regmap, I also want to bring something that was discussed
> > before the RFC. Basically we talked about having the backend registering it's
> > own regmap_bus. Then we would either:
> >
> > 1) Have a specific get_regmap_bus() callback for the frontend to initialize a
> > regmap on;
> > 2) Pass this bus into the core and have a new frontend API like
> > devm_iio_backend_regmap_init().
> >
> > Then, on top of the API already provided by regmap (like _update_bit()), the
> > frontend could just use regmap independent of having a backend or not.
> >
> > The current API is likely more generic but tbh (and David and Angelo are aware
> > of it) my preferred approach it to use the regmap_bus stuff. I just don't feel
> > that strong about it :)
> >
> > > > Actually, a reg bus write involves several AXI regmap operations.
> > > > >
> > > > > > +{
> > > > > > + struct axi_dac_state *st = iio_backend_get_priv(back);
> > > > > > +
> > > > > > + if (!st->bus_type)
> > > > > > + return -EOPNOTSUPP;
> > > > > > +
> > > > > > + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
> > > > > As below, I'd use a switch and factor out this block as a separate
> > > > > bus specific function.
> > > > Ok, changed.
> > > > >
> > > > > > + int ret;
> > > > > > + u32 ival;
> > > > > > +
> > > > > > + if (size != 1 && size != 2)
> > > > > > + return -EINVAL;
> > > > > > +
> > > > > > + switch (size) {
> > > > > > + case 1:
> > > > > > + ival = FIELD_PREP(AXI_DAC_DATA_WR_8, *(u8
> > > > > > *)val);
> > > > > > + break;
> > > > > > + case 2:
> > > > > > + ival = FIELD_PREP(AXI_DAC_DATA_WR_16, *(u16
> > > > > > *)val);
> > > > > > + break;
> > > > > > + default:
> > > > > > + return -EINVAL;
> > > > > Hopefully compiler won't need this and the above. I'd drop the size != 1..
> > > > > check in favour of just doing it in this switch.
> > > > >
> > > > sure, done.
> > > >
> > > >
> > > > > > + }
> > > > > > +
> > > > > > + ret = regmap_write(st->regmap, AXI_DAC_CNTRL_DATA_WR,
> > > > > > ival);
> > > > > > + if (ret)
> > > > > > + return ret;
> > > > > > +
> > > > > > + /*
> > > > > > + * Both REG_CNTRL_2 and AXI_DAC_CNTRL_DATA_WR need to
> > > > > > know
> > > > > > + * the data size. So keeping data size control here
> > > > > > only,
> > > > > > + * since data size is mandatory for to the current
> > > > > > transfer.
> > > > > > + * DDR state handled separately by specific backend
> > > > > > calls,
> > > > > > + * generally all raw register writes are SDR.
> > > > > > + */
> > > > > > + if (size == 1)
> > > > > > + ret = regmap_set_bits(st->regmap,
> > > > > > AXI_DAC_REG_CNTRL_2,
> > > > > > + AXI_DAC_SYMB_8B);
> > > > > > + else
> > > > > > + ret = regmap_clear_bits(st->regmap,
> > > > > > AXI_DAC_REG_CNTRL_2,
> > > > > > + AXI_DAC_SYMB_8B);
> > > > > > + if (ret)
> > > > > > + return ret;
> > > > > > +
> > > > > > + ret = regmap_update_bits(st->regmap,
> > > > > > AXI_DAC_REG_CUSTOM_CTRL,
> > > > > > + AXI_DAC_ADDRESS,
> > > > > > + FIELD_PREP(AXI_DAC_ADDRESS,
> > > > > > reg));
> > > > > > + if (ret)
> > > > > > + return ret;
> > > > > > +
> > > > > > + ret = regmap_update_bits(st->regmap,
> > > > > > AXI_DAC_REG_CUSTOM_CTRL,
> > > > > > + AXI_DAC_TRANSFER_DATA,
> > > > > > + AXI_DAC_TRANSFER_DATA);
> > > > > > + if (ret)
> > > > > > + return ret;
> > > > > > +
> > > > > > + ret = regmap_read_poll_timeout(st->regmap,
> > > > > > + AXI_DAC_REG_CUSTOM_CTRL,
> > > > > > ival,
> > > > > > + ival &
> > > > > > AXI_DAC_TRANSFER_DATA,
> > > > > > + 10, 100 * KILO);
> > > > > > + if (ret)
> > > > > > + return ret;
> > > > > > +
> > > > > > + return regmap_clear_bits(st->regmap,
> > > > > > AXI_DAC_REG_CUSTOM_CTRL,
> > > > > > + AXI_DAC_TRANSFER_DATA);
> > > > > > + }
> > > > > > +
> > > > > > + return -EINVAL;
> > > > > > +}
> > > > > > +
> > > > > > +static int axi_dac_bus_reg_read(struct iio_backend *back,
> > > > > > + u32 reg, void *val, size_t size)
> > > > > As for write, I'd just use an unsigned int * for val like
> > > > > regmap does.
> > > > Ok, so initial choice was unsigned int, further thinking of
> > > > possible future busses drive the choice to void *.
> > > >
> > > > Let me know, i can switch to unsigned int in case.
> > > I would just go with unsigned int or at a push u64 *
> > >
> > > >
> > > > >
> > > > > > +{
> > > > > > + struct axi_dac_state *st = iio_backend_get_priv(back);
> > > > > > +
> > > > > > + if (!st->bus_type)
> > > > > > + return -EOPNOTSUPP;
> > > > > > +
> > > > > > + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) {
> > > > > It got mentioned in binding review but if this isn't QSPI, even
> > > > > if similar don't call it that.
> > > > It's a bit difficult to find a different name, physically,
> > > > it is a QSPI, 4 lanes + clock + cs, and datasheet is naming it Quad SPI.
> > > > But looking the data protocol, it's a bit different.
> > > is QSPI actually defined anywhere? I assumed it would be like
> > > SPI for which everything is so flexible you can build whatever you like.
> > >
> > > > QSPI has instruction, address and data.
> > > > Here we have just ADDR and DATA.
> > > >
> > I'm not sure the instruction is really relevant for this. From a quick look, it
> > feels like something used for accessing external flash memory like spi-nors. So,
> > I would not be surprised if things are just like Jonathan said and this is just
> > flexible as spi (being that extra instruction field a protocol defined for flash
> > memory - where one typically sees this interface)
>
> Ok, so QSPI is the hardware, and the protocol on it may vary for the target
> chip/application.
>
> Looks like DDR makes the 33MUPS rate reachable, and not all the controllers
> have DDR mode. Also some controllers are supposed to work with a QSPI flash
> (so with instructions), and likely this reason driven the need to use a
> custom IP.
>
I do understand the custom IP, I just don't understand why not using the spi_engine
IP. Indeed maybe because of DDR (as that is already supported on axi-dac).
- Nuno Sá
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-09-05 9:50 ` Nuno Sá
@ 2024-09-06 8:50 ` Conor Dooley
2024-09-06 8:55 ` Conor Dooley
2024-09-06 11:28 ` Nuno Sá
0 siblings, 2 replies; 54+ messages in thread
From: Conor Dooley @ 2024-09-06 8:50 UTC (permalink / raw)
To: Nuno Sá
Cc: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
Nuno Sá, Jonathan Cameron, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Olivier Moysan, linux-iio, devicetree, linux-kernel,
dlechner
[-- Attachment #1: Type: text/plain, Size: 8173 bytes --]
On Thu, Sep 05, 2024 at 11:50:45AM +0200, Nuno Sá wrote:
> On Fri, 2024-08-30 at 16:33 +0100, Conor Dooley wrote:
> > On Fri, Aug 30, 2024 at 10:19:49AM +0200, Angelo Dureghello wrote:
> > > Hi Conor,
> > >
> > > On 29/08/24 5:46 PM, Conor Dooley wrote:
> > > > On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
> > > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > > >
> > > > > Add bus property.
> > > > RFC it may be, but you do need to explain what this bus-type actually
> > > > describes for commenting on the suitability of the method to be
> > > > meaningful.
> > >
> > > thanks for the feedbacks,
> > >
> > > a "bus" is intended as a generic interface connected to the target,
> > > may be used from a custom IP (fpga) to communicate with the target
> > > device (by read/write(reg and value)) using a special custom interface.
> > >
> > > The bus could also be physically the same of some well-known existing
> > > interfaces (as parallel, lvds or other uncommon interfaces), but using
> > > an uncommon/custom protocol over it.
> > >
> > > In concrete, actually bus-type is added to the backend since the
> > > ad3552r DAC chip can be connected (for maximum speed) by a 5 lanes DDR
> > > parallel bus (interface that i named QSPI, but it's not exactly a QSPI
> > > as a protocol), so it's a device-specific interface.
> > >
> > > With additions in this patchset, other frontends, of course not only
> > > DACs, will be able to add specific busses and read/wrtie to the bus
> > > as needed.
> > >
> > > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > > > ---
> > > > > Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9
> > > > > +++++++++
> > > > > 1 file changed, 9 insertions(+)
> > > > >
> > > > > diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > index a55e9bfc66d7..a7ce72e1cd81 100644
> > > > > --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > @@ -38,6 +38,15 @@ properties:
> > > > > clocks:
> > > > > maxItems: 1
> > > > You mentioned about new compatible strings, does the one currently
> > > > listed in this binding support both bus types?
> >
> > You didn't answer this, and there's insufficient explanation of the
> > "hardware" in this RFC, but I found this which is supposedly the
> > backend:
> > https://github.com/analogdevicesinc/hdl/tree/main/library/axi_ad3552r
> > adi,axi-dac.yaml has a single compatible, and that compatible has
> > nothing to do with "axi_ad3552r" as it is "adi,axi-dac-9.1.b". I would
> > expect either justification for reuse of the compatible, or a brand new
> > compatible for this backend, even if the driver can mostly be reused.
> >
>
> Hi Conor,
>
> So most of these designs have some changes (even if minimal) in the register map
> and the idea (mine actually) with this backend stuff was to keep the backend
> driver (axi-dac/adc) with the generic compatible since all the (different)
> functionality is basically defined by the frontend they connect too and that
> functionality is modeled by IIO backend ops. For some more
> significant/fundamental differences in the IP like this bus controller kind of
> thing, we would add have proper FW properties. The main idea was kind of using
> the frontend + generic backend combo so no need for new compatibles for every
> new design.
>
> It's still early days (at least upstream) for these IP cores and the backend
> code so if you say that we should have new compatibles for every new design that
> has some differences in the register map (even if minimal), I'm of course fine
> with it. I've done it like this because I was (am) kind of afraid for things to
> get complicated fairly quickly both in the bindings and driver (well maybe not
> in the driver). OTOH, it can simplify things a lot as it's way easier to
> identify different implementations of the IP directly in the driver so we have
> way more flexibility.
Most of my opinion on this from a usability perspective for your
customers, rather than how the kernel is going to handle it. If a user
is inserting a preconfigured instance of the IP, for a specific ADC or
DAC, into their design I think it makes more sense to have a compatible,
rather than expect the user to reverse engineer how the IP has been
configured and which properties they should select. My own policy for
Microchip's stuff is that if something has a name or entry in the IP
catalogue then it should have a dedicated compatible, even if it is just a
preconfigured version of some other IP block and I guess what I am
saying here is an extension of that.
I suspect that in many cases the specific compatible won't be required,
and a fallback to the generic one will suffice for the driver, and it
would only be for cases like this, that have "significant/fundamental
differences" that the driver would need the specific one.
>
> > Could you please link to whatever ADI wiki has detailed information on
> > how this stuff works so that I can look at it to better understand the
> > axes of configuration here?
> >
> > > >
> > > > Making the bus type decision based on compatible only really makes sense
> > > > if they're different versions of the IP, but not if they're different
> > > > configuration options for a given version.
> > > >
> > > > > + bus-type:
> > >
> > > DAC IP on fpga actually respects same structure and register set, except
> > > for a named "custom" register that may use specific bitfields depending
> > > on the application of the IP.
> >
> > To paraphrase:
> > "The register map is the same, except for the bit that is different".
> > If ADI is shipping several different configurations of this IP for
> > different DACs, I'd be expecting different compatibles for each backend
> > to be honest.
>
> Yes, pretty much we have a generic core with most of the designs being based on
> it but with some slight differences. At least for the new ones, almost all of
> them have slight deviations from the generic/base core.
>
> > If each DAC specific backend was to have a unique compatible, would the
> > type of bus used be determinable from it? Doesn't have to work for all
> > devices from now until the heath death of the universe, but at least for
> > the devices that you're currently aware of?
> >
>
> My original idea was to have a bus controller boolean for this core at least for
> now that we only have one bus type (so we could assume qspi in the driver). If
> the time comes we need to add support for something else, then we would need
> another property to identify the type.
With a specific compatible, you can "easily" add different defaults. So
the other devices could default to no bus when a bus related property is
required and this one could default to qspi. But unless there are
ADCs/DACs that have a backend that can be configured with different
types of bus, a property for this wouldn't be needed - the compatible
and match data would suffice.
>
> > > > If, as you mentioned, there are multiple bus types, a non-flag property
> > > > does make sense. However, I am really not keen on these "forced" numerical
> > > > properties at all, I'd much rather see strings used here.
> >
> > > > > + maxItems: 1
> > > > > + description: |
> > > > > + Configure bus type:
> > > > > + - 0: none
> > > > > + - 1: qspi
> >
> > Also, re-reading the cover letter, it says "this platform driver uses a 4
> > lanes parallel bus, plus a clock line, similar to a qspi."
> > I don't think we should call this "qspi" if it is not actually qspi,
> > that's just confusing.
> >
>
> Just by looking at the datasheet it feels like typical qspi to be honest. And,
> fwiw, even if not really qspi, this is how the datasheet names the interface.
Right, just a phrasing issue in the cover letter I guess :)
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-09-06 8:50 ` Conor Dooley
@ 2024-09-06 8:55 ` Conor Dooley
2024-09-06 11:28 ` Nuno Sá
1 sibling, 0 replies; 54+ messages in thread
From: Conor Dooley @ 2024-09-06 8:55 UTC (permalink / raw)
To: Nuno Sá
Cc: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
Nuno Sá, Jonathan Cameron, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Olivier Moysan, linux-iio, devicetree, linux-kernel,
dlechner
[-- Attachment #1: Type: text/plain, Size: 1274 bytes --]
On Fri, Sep 06, 2024 at 09:50:30AM +0100, Conor Dooley wrote:
> On Thu, Sep 05, 2024 at 11:50:45AM +0200, Nuno Sá wrote:
> > On Fri, 2024-08-30 at 16:33 +0100, Conor Dooley wrote:
> > > On Fri, Aug 30, 2024 at 10:19:49AM +0200, Angelo Dureghello wrote:
> > > > > > + maxItems: 1
> > > > > > + description: |
> > > > > > + Configure bus type:
> > > > > > + - 0: none
> > > > > > + - 1: qspi
> > >
> > > Also, re-reading the cover letter, it says "this platform driver uses a 4
> > > lanes parallel bus, plus a clock line, similar to a qspi."
> > > I don't think we should call this "qspi" if it is not actually qspi,
> > > that's just confusing.
> > >
> >
> > Just by looking at the datasheet it feels like typical qspi to be honest. And,
> > fwiw, even if not really qspi, this is how the datasheet names the interface.
>
> Right, just a phrasing issue in the cover letter I guess :)
The other thing that this brings into question, and I forget if I said
it before (perhaps to David on IRC) was whether or not the ADC/DAC needs
to be a child of the backend, if the backend is providing the SPI bus
that the device is attached to. Why would it not be the case, if as you
say, it appears to be a real qspi controller?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-09-02 9:32 ` Angelo Dureghello
2024-09-03 19:18 ` Jonathan Cameron
@ 2024-09-06 9:04 ` Conor Dooley
2024-09-06 11:32 ` Nuno Sá
1 sibling, 1 reply; 54+ messages in thread
From: Conor Dooley @ 2024-09-06 9:04 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan, linux-iio, devicetree, linux-kernel, dlechner
[-- Attachment #1: Type: text/plain, Size: 6229 bytes --]
On Mon, Sep 02, 2024 at 11:32:37AM +0200, Angelo Dureghello wrote:
> Hi Conor,
>
>
> On 30/08/24 5:33 PM, Conor Dooley wrote:
> > On Fri, Aug 30, 2024 at 10:19:49AM +0200, Angelo Dureghello wrote:
> > > Hi Conor,
> > >
> > > On 29/08/24 5:46 PM, Conor Dooley wrote:
> > > > On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
> > > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > > >
> > > > > Add bus property.
> > > > RFC it may be, but you do need to explain what this bus-type actually
> > > > describes for commenting on the suitability of the method to be
> > > > meaningful.
> > > thanks for the feedbacks,
> > >
> > > a "bus" is intended as a generic interface connected to the target,
> > > may be used from a custom IP (fpga) to communicate with the target
> > > device (by read/write(reg and value)) using a special custom interface.
> > >
> > > The bus could also be physically the same of some well-known existing
> > > interfaces (as parallel, lvds or other uncommon interfaces), but using
> > > an uncommon/custom protocol over it.
> > >
> > > In concrete, actually bus-type is added to the backend since the
> > > ad3552r DAC chip can be connected (for maximum speed) by a 5 lanes DDR
> > > parallel bus (interface that i named QSPI, but it's not exactly a QSPI
> > > as a protocol), so it's a device-specific interface.
> > >
> > > With additions in this patchset, other frontends, of course not only
> > > DACs, will be able to add specific busses and read/wrtie to the bus
> > > as needed.
> > >
> > > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > > > ---
> > > > > Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9 +++++++++
> > > > > 1 file changed, 9 insertions(+)
> > > > >
> > > > > diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > index a55e9bfc66d7..a7ce72e1cd81 100644
> > > > > --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > @@ -38,6 +38,15 @@ properties:
> > > > > clocks:
> > > > > maxItems: 1
> > > > You mentioned about new compatible strings, does the one currently
> > > > listed in this binding support both bus types?
> > You didn't answer this, and there's insufficient explanation of the
> > "hardware" in this RFC, but I found this which is supposedly the
> > backend:
> > https://github.com/analogdevicesinc/hdl/tree/main/library/axi_ad3552r
> > adi,axi-dac.yaml has a single compatible, and that compatible has
> > nothing to do with "axi_ad3552r" as it is "adi,axi-dac-9.1.b". I would
> > expect either justification for reuse of the compatible, or a brand new
> > compatible for this backend, even if the driver can mostly be reused.
> >
> > Could you please link to whatever ADI wiki has detailed information on
> > how this stuff works so that I can look at it to better understand the
> > axes of configuration here?
>
> https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
>
> that has same structure and register set of the generic ADI AXI-DAC IP:
> https://wiki.analog.com/resources/fpga/docs/axi_dac_ip
>
>
> > > > Making the bus type decision based on compatible only really makes sense
> > > > if they're different versions of the IP, but not if they're different
> > > > configuration options for a given version.
> > > >
> > > > > + bus-type:
> > > DAC IP on fpga actually respects same structure and register set, except
> > > for a named "custom" register that may use specific bitfields depending
> > > on the application of the IP.
> > To paraphrase:
> > "The register map is the same, except for the bit that is different".
> > If ADI is shipping several different configurations of this IP for
> > different DACs, I'd be expecting different compatibles for each backend
> > to be honest
>
> i am still quite new to this fpga-based implementations, at least for how
> such IPs are actually interfacing to the linux subsystem, so i may miss
> some point.
>
> About the "adi,axi-dac-9.1.b" compatible, the generic DAC IP register set
> is mostly the same structure of this ad3552r IP (links above), except for
> bitfields in the DAC_CUSTOM_CTRL register.
>
> My choice for now was to add a bus-type property.
>
> Not an HDL expert, but i think a different bus means, from an hardware point
> of
> view, a different IP in terms of internal fpga circuitry, even if not as a
> register-set.
Depending on whether or not the unmodified driver can be used with this
IP (so the QSPI bus stuff would need to be optional) then a fallback
should be used given the degree of similarity. It, however, seems likely
that is not the case, and without the QSPI bus there'd be no way to
communicate with the device. Is there any reason to use this IP as a
backend, without connecting the QSPI bus at all, leaving the ADC/DAC on
a regular SPI bus?
>
>
> > .
> > If each DAC specific backend was to have a unique compatible, would the
> > type of bus used be determinable from it? Doesn't have to work for all
> > devices from now until the heath death of the universe, but at least for
> > the devices that you're currently aware of?
> >
> > > > If, as you mentioned, there are multiple bus types, a non-flag property
> > > > does make sense. However, I am really not keen on these "forced" numerical
> > > > properties at all, I'd much rather see strings used here.
> > > > > + maxItems: 1
> > > > > + description: |
> > > > > + Configure bus type:
> > > > > + - 0: none
> > > > > + - 1: qspi
> > Also, re-reading the cover letter, it says "this platform driver uses a 4
> > lanes parallel bus, plus a clock line, similar to a qspi."
> > I don't think we should call this "qspi" if it is not actually qspi,
> > that's just confusing.
>
> Agree, name should be something different.
Nuno's comment appears to disagree, and that is /is/ actually a qspi
controller. Please see my comments to him about parentage.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-09-06 8:50 ` Conor Dooley
2024-09-06 8:55 ` Conor Dooley
@ 2024-09-06 11:28 ` Nuno Sá
1 sibling, 0 replies; 54+ messages in thread
From: Nuno Sá @ 2024-09-06 11:28 UTC (permalink / raw)
To: Conor Dooley
Cc: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
Nuno Sá, Jonathan Cameron, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Olivier Moysan, linux-iio, devicetree, linux-kernel,
dlechner
On Fri, 2024-09-06 at 09:50 +0100, Conor Dooley wrote:
> On Thu, Sep 05, 2024 at 11:50:45AM +0200, Nuno Sá wrote:
> > On Fri, 2024-08-30 at 16:33 +0100, Conor Dooley wrote:
> > > On Fri, Aug 30, 2024 at 10:19:49AM +0200, Angelo Dureghello wrote:
> > > > Hi Conor,
> > > >
> > > > On 29/08/24 5:46 PM, Conor Dooley wrote:
> > > > > On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
> > > > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > > > >
> > > > > > Add bus property.
> > > > > RFC it may be, but you do need to explain what this bus-type actually
> > > > > describes for commenting on the suitability of the method to be
> > > > > meaningful.
> > > >
> > > > thanks for the feedbacks,
> > > >
> > > > a "bus" is intended as a generic interface connected to the target,
> > > > may be used from a custom IP (fpga) to communicate with the target
> > > > device (by read/write(reg and value)) using a special custom interface.
> > > >
> > > > The bus could also be physically the same of some well-known existing
> > > > interfaces (as parallel, lvds or other uncommon interfaces), but using
> > > > an uncommon/custom protocol over it.
> > > >
> > > > In concrete, actually bus-type is added to the backend since the
> > > > ad3552r DAC chip can be connected (for maximum speed) by a 5 lanes DDR
> > > > parallel bus (interface that i named QSPI, but it's not exactly a QSPI
> > > > as a protocol), so it's a device-specific interface.
> > > >
> > > > With additions in this patchset, other frontends, of course not only
> > > > DACs, will be able to add specific busses and read/wrtie to the bus
> > > > as needed.
> > > >
> > > > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > > > > ---
> > > > > > Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9
> > > > > > +++++++++
> > > > > > 1 file changed, 9 insertions(+)
> > > > > >
> > > > > > diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > index a55e9bfc66d7..a7ce72e1cd81 100644
> > > > > > --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > @@ -38,6 +38,15 @@ properties:
> > > > > > clocks:
> > > > > > maxItems: 1
> > > > > You mentioned about new compatible strings, does the one currently
> > > > > listed in this binding support both bus types?
> > >
> > > You didn't answer this, and there's insufficient explanation of the
> > > "hardware" in this RFC, but I found this which is supposedly the
> > > backend:
> > > https://github.com/analogdevicesinc/hdl/tree/main/library/axi_ad3552r
> > > adi,axi-dac.yaml has a single compatible, and that compatible has
> > > nothing to do with "axi_ad3552r" as it is "adi,axi-dac-9.1.b". I would
> > > expect either justification for reuse of the compatible, or a brand new
> > > compatible for this backend, even if the driver can mostly be reused.
> > >
> >
> > Hi Conor,
> >
> > So most of these designs have some changes (even if minimal) in the register map
> > and the idea (mine actually) with this backend stuff was to keep the backend
> > driver (axi-dac/adc) with the generic compatible since all the (different)
> > functionality is basically defined by the frontend they connect too and that
> > functionality is modeled by IIO backend ops. For some more
> > significant/fundamental differences in the IP like this bus controller kind of
> > thing, we would add have proper FW properties. The main idea was kind of using
> > the frontend + generic backend combo so no need for new compatibles for every
> > new design.
> >
> > It's still early days (at least upstream) for these IP cores and the backend
> > code so if you say that we should have new compatibles for every new design that
> > has some differences in the register map (even if minimal), I'm of course fine
> > with it. I've done it like this because I was (am) kind of afraid for things to
> > get complicated fairly quickly both in the bindings and driver (well maybe not
> > in the driver). OTOH, it can simplify things a lot as it's way easier to
> > identify different implementations of the IP directly in the driver so we have
> > way more flexibility.
>
> Most of my opinion on this from a usability perspective for your
> customers, rather than how the kernel is going to handle it. If a user
> is inserting a preconfigured instance of the IP, for a specific ADC or
> DAC, into their design I think it makes more sense to have a compatible,
> rather than expect the user to reverse engineer how the IP has been
> configured and which properties they should select. My own policy for
> Microchip's stuff is that if something has a name or entry in the IP
> catalogue then it should have a dedicated compatible, even if it is just a
> preconfigured version of some other IP block and I guess what I am
> saying here is an extension of that.
>
Hmm, indeed the above makes sense...
> I suspect that in many cases the specific compatible won't be required,
> and a fallback to the generic one will suffice for the driver, and it
> would only be for cases like this, that have "significant/fundamental
> differences" that the driver would need the specific one.
>
Hopefully yes :)
> >
> > > Could you please link to whatever ADI wiki has detailed information on
> > > how this stuff works so that I can look at it to better understand the
> > > axes of configuration here?
> > >
> > > > >
> > > > > Making the bus type decision based on compatible only really makes sense
> > > > > if they're different versions of the IP, but not if they're different
> > > > > configuration options for a given version.
> > > > >
> > > > > > + bus-type:
> > > >
> > > > DAC IP on fpga actually respects same structure and register set, except
> > > > for a named "custom" register that may use specific bitfields depending
> > > > on the application of the IP.
> > >
> > > To paraphrase:
> > > "The register map is the same, except for the bit that is different".
> > > If ADI is shipping several different configurations of this IP for
> > > different DACs, I'd be expecting different compatibles for each backend
> > > to be honest.
> >
> > Yes, pretty much we have a generic core with most of the designs being based on
> > it but with some slight differences. At least for the new ones, almost all of
> > them have slight deviations from the generic/base core.
> >
> > > If each DAC specific backend was to have a unique compatible, would the
> > > type of bus used be determinable from it? Doesn't have to work for all
> > > devices from now until the heath death of the universe, but at least for
> > > the devices that you're currently aware of?
> > >
> >
> > My original idea was to have a bus controller boolean for this core at least for
> > now that we only have one bus type (so we could assume qspi in the driver). If
> > the time comes we need to add support for something else, then we would need
> > another property to identify the type.
>
> With a specific compatible, you can "easily" add different defaults. So
> the other devices could default to no bus when a bus related property is
> required and this one could default to qspi. But unless there are
> ADCs/DACs that have a backend that can be configured with different
> types of bus, a property for this wouldn't be needed - the compatible
> and match data would suffice.
>
Agreed...
- Nuno Sá
> > > > >
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-09-06 9:04 ` Conor Dooley
@ 2024-09-06 11:32 ` Nuno Sá
2024-09-07 8:53 ` Angelo Dureghello
0 siblings, 1 reply; 54+ messages in thread
From: Nuno Sá @ 2024-09-06 11:32 UTC (permalink / raw)
To: Conor Dooley, Angelo Dureghello
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan, linux-iio, devicetree, linux-kernel, dlechner
On Fri, 2024-09-06 at 10:04 +0100, Conor Dooley wrote:
> On Mon, Sep 02, 2024 at 11:32:37AM +0200, Angelo Dureghello wrote:
> > Hi Conor,
> >
> >
> > On 30/08/24 5:33 PM, Conor Dooley wrote:
> > > On Fri, Aug 30, 2024 at 10:19:49AM +0200, Angelo Dureghello wrote:
> > > > Hi Conor,
> > > >
> > > > On 29/08/24 5:46 PM, Conor Dooley wrote:
> > > > > On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
> > > > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > > > >
> > > > > > Add bus property.
> > > > > RFC it may be, but you do need to explain what this bus-type actually
> > > > > describes for commenting on the suitability of the method to be
> > > > > meaningful.
> > > > thanks for the feedbacks,
> > > >
> > > > a "bus" is intended as a generic interface connected to the target,
> > > > may be used from a custom IP (fpga) to communicate with the target
> > > > device (by read/write(reg and value)) using a special custom interface.
> > > >
> > > > The bus could also be physically the same of some well-known existing
> > > > interfaces (as parallel, lvds or other uncommon interfaces), but using
> > > > an uncommon/custom protocol over it.
> > > >
> > > > In concrete, actually bus-type is added to the backend since the
> > > > ad3552r DAC chip can be connected (for maximum speed) by a 5 lanes DDR
> > > > parallel bus (interface that i named QSPI, but it's not exactly a QSPI
> > > > as a protocol), so it's a device-specific interface.
> > > >
> > > > With additions in this patchset, other frontends, of course not only
> > > > DACs, will be able to add specific busses and read/wrtie to the bus
> > > > as needed.
> > > >
> > > > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > > > > ---
> > > > > > Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9
> > > > > > +++++++++
> > > > > > 1 file changed, 9 insertions(+)
> > > > > >
> > > > > > diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > index a55e9bfc66d7..a7ce72e1cd81 100644
> > > > > > --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > @@ -38,6 +38,15 @@ properties:
> > > > > > clocks:
> > > > > > maxItems: 1
> > > > > You mentioned about new compatible strings, does the one currently
> > > > > listed in this binding support both bus types?
> > > You didn't answer this, and there's insufficient explanation of the
> > > "hardware" in this RFC, but I found this which is supposedly the
> > > backend:
> > > https://github.com/analogdevicesinc/hdl/tree/main/library/axi_ad3552r
> > > adi,axi-dac.yaml has a single compatible, and that compatible has
> > > nothing to do with "axi_ad3552r" as it is "adi,axi-dac-9.1.b". I would
> > > expect either justification for reuse of the compatible, or a brand new
> > > compatible for this backend, even if the driver can mostly be reused.
> > >
> > > Could you please link to whatever ADI wiki has detailed information on
> > > how this stuff works so that I can look at it to better understand the
> > > axes of configuration here?
> >
> > https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
> >
> > that has same structure and register set of the generic ADI AXI-DAC IP:
> > https://wiki.analog.com/resources/fpga/docs/axi_dac_ip
> >
> >
> > > > > Making the bus type decision based on compatible only really makes sense
> > > > > if they're different versions of the IP, but not if they're different
> > > > > configuration options for a given version.
> > > > >
> > > > > > + bus-type:
> > > > DAC IP on fpga actually respects same structure and register set, except
> > > > for a named "custom" register that may use specific bitfields depending
> > > > on the application of the IP.
> > > To paraphrase:
> > > "The register map is the same, except for the bit that is different".
> > > If ADI is shipping several different configurations of this IP for
> > > different DACs, I'd be expecting different compatibles for each backend
> > > to be honest
> >
> > i am still quite new to this fpga-based implementations, at least for how
> > such IPs are actually interfacing to the linux subsystem, so i may miss
> > some point.
> >
> > About the "adi,axi-dac-9.1.b" compatible, the generic DAC IP register set
> > is mostly the same structure of this ad3552r IP (links above), except for
> > bitfields in the DAC_CUSTOM_CTRL register.
> >
> > My choice for now was to add a bus-type property.
> >
> > Not an HDL expert, but i think a different bus means, from an hardware point
> > of
> > view, a different IP in terms of internal fpga circuitry, even if not as a
> > register-set.
>
> Depending on whether or not the unmodified driver can be used with this
> IP (so the QSPI bus stuff would need to be optional) then a fallback
> should be used given the degree of similarity. It, however, seems likely
> that is not the case, and without the QSPI bus there'd be no way to
> communicate with the device. Is there any reason to use this IP as a
> backend, without connecting the QSPI bus at all, leaving the ADC/DAC on
> a regular SPI bus?
>
Somewhere in my replies, I'm doing the exact same question to myself. We probably
need to speak with the FPGA folks but I guess (hope) they had a good reason for this.
- Nuno Sá
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-09-06 11:32 ` Nuno Sá
@ 2024-09-07 8:53 ` Angelo Dureghello
2024-09-09 12:17 ` Conor Dooley
0 siblings, 1 reply; 54+ messages in thread
From: Angelo Dureghello @ 2024-09-07 8:53 UTC (permalink / raw)
To: Nuno Sá, Conor Dooley
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan, linux-iio, devicetree, linux-kernel, dlechner
On 06/09/24 1:32 PM, Nuno Sá wrote:
> On Fri, 2024-09-06 at 10:04 +0100, Conor Dooley wrote:
>> On Mon, Sep 02, 2024 at 11:32:37AM +0200, Angelo Dureghello wrote:
>>> Hi Conor,
>>>
>>>
>>> On 30/08/24 5:33 PM, Conor Dooley wrote:
>>>> On Fri, Aug 30, 2024 at 10:19:49AM +0200, Angelo Dureghello wrote:
>>>>> Hi Conor,
>>>>>
>>>>> On 29/08/24 5:46 PM, Conor Dooley wrote:
>>>>>> On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
>>>>>>> From: Angelo Dureghello <adureghello@baylibre.com>
>>>>>>>
>>>>>>> Add bus property.
>>>>>> RFC it may be, but you do need to explain what this bus-type actually
>>>>>> describes for commenting on the suitability of the method to be
>>>>>> meaningful.
>>>>> thanks for the feedbacks,
>>>>>
>>>>> a "bus" is intended as a generic interface connected to the target,
>>>>> may be used from a custom IP (fpga) to communicate with the target
>>>>> device (by read/write(reg and value)) using a special custom interface.
>>>>>
>>>>> The bus could also be physically the same of some well-known existing
>>>>> interfaces (as parallel, lvds or other uncommon interfaces), but using
>>>>> an uncommon/custom protocol over it.
>>>>>
>>>>> In concrete, actually bus-type is added to the backend since the
>>>>> ad3552r DAC chip can be connected (for maximum speed) by a 5 lanes DDR
>>>>> parallel bus (interface that i named QSPI, but it's not exactly a QSPI
>>>>> as a protocol), so it's a device-specific interface.
>>>>>
>>>>> With additions in this patchset, other frontends, of course not only
>>>>> DACs, will be able to add specific busses and read/wrtie to the bus
>>>>> as needed.
>>>>>
>>>>>>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>>>>>>> ---
>>>>>>> Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9
>>>>>>> +++++++++
>>>>>>> 1 file changed, 9 insertions(+)
>>>>>>>
>>>>>>> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>> b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>> index a55e9bfc66d7..a7ce72e1cd81 100644
>>>>>>> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>> @@ -38,6 +38,15 @@ properties:
>>>>>>> clocks:
>>>>>>> maxItems: 1
>>>>>> You mentioned about new compatible strings, does the one currently
>>>>>> listed in this binding support both bus types?
>>>> You didn't answer this, and there's insufficient explanation of the
>>>> "hardware" in this RFC, but I found this which is supposedly the
>>>> backend:
>>>> https://github.com/analogdevicesinc/hdl/tree/main/library/axi_ad3552r
>>>> adi,axi-dac.yaml has a single compatible, and that compatible has
>>>> nothing to do with "axi_ad3552r" as it is "adi,axi-dac-9.1.b". I would
>>>> expect either justification for reuse of the compatible, or a brand new
>>>> compatible for this backend, even if the driver can mostly be reused.
>>>>
>>>> Could you please link to whatever ADI wiki has detailed information on
>>>> how this stuff works so that I can look at it to better understand the
>>>> axes of configuration here?
>>> https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
>>>
>>> that has same structure and register set of the generic ADI AXI-DAC IP:
>>> https://wiki.analog.com/resources/fpga/docs/axi_dac_ip
>>>
>>>
>>>>>> Making the bus type decision based on compatible only really makes sense
>>>>>> if they're different versions of the IP, but not if they're different
>>>>>> configuration options for a given version.
>>>>>>
>>>>>>> + bus-type:
>>>>> DAC IP on fpga actually respects same structure and register set, except
>>>>> for a named "custom" register that may use specific bitfields depending
>>>>> on the application of the IP.
>>>> To paraphrase:
>>>> "The register map is the same, except for the bit that is different".
>>>> If ADI is shipping several different configurations of this IP for
>>>> different DACs, I'd be expecting different compatibles for each backend
>>>> to be honest
>>> i am still quite new to this fpga-based implementations, at least for how
>>> such IPs are actually interfacing to the linux subsystem, so i may miss
>>> some point.
>>>
>>> About the "adi,axi-dac-9.1.b" compatible, the generic DAC IP register set
>>> is mostly the same structure of this ad3552r IP (links above), except for
>>> bitfields in the DAC_CUSTOM_CTRL register.
>>>
>>> My choice for now was to add a bus-type property.
>>>
>>> Not an HDL expert, but i think a different bus means, from an hardware point
>>> of
>>> view, a different IP in terms of internal fpga circuitry, even if not as a
>>> register-set.
>> Depending on whether or not the unmodified driver can be used with this
>> IP (so the QSPI bus stuff would need to be optional) then a fallback
>> should be used given the degree of similarity. It, however, seems likely
>> that is not the case, and without the QSPI bus there'd be no way to
>> communicate with the device. Is there any reason to use this IP as a
>> backend, without connecting the QSPI bus at all, leaving the ADC/DAC on
>> a regular SPI bus?
>>
> Somewhere in my replies, I'm doing the exact same question to myself. We probably
> need to speak with the FPGA folks but I guess (hope) they had a good reason for this.
>
> - Nuno Sá
to clarify a bit the custom (fpga-based) QSPI need, i did some checks in the
datasheets:
1. ADI is actually supporting ad3552r by eval-ad3552r-fmcx eval boards,
with specific fmc connector for the ZedBoard (zynq7000). This is the
current focused hardware for this job.
2. Zynq7000 std non-fpga controller is designed to control flash memories,
but can operate in "raw I/O" mode, so it may work with ad3552r, but is not
supporting DDR, even if it may reach 100Mhz clock.
3. ad3552r accepts a maximum clock of 66Mhz. So for ZedBoard maximum speed
of 33MUPS cannot be reached without DDR.
4. ad3552r requires DDR only in the data part, and in DDR mode we
may also send some "non-loop" reg read/write, so requiring also the
address to be sent in SDR. Not sure how many QSPI controllers in the
market are
working this way, even if it seems quite standard, looks like not many
are actually
supporting DDR. There may be, but not actually in the priority of my
customer
right now. And in that case, we could extend the generic spi ad3552r.c.
Regards,
--
,,, Angelo Dureghello
:: :. BayLibre -runtime team- Developer
:`___:
`____:
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 2/8] iio: backend: extend features
2024-09-05 10:28 ` Nuno Sá
@ 2024-09-07 14:02 ` Jonathan Cameron
0 siblings, 0 replies; 54+ messages in thread
From: Jonathan Cameron @ 2024-09-07 14:02 UTC (permalink / raw)
To: Nuno Sá
Cc: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
Nuno Sá, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Olivier Moysan, linux-iio, devicetree, linux-kernel, dlechner
On Thu, 05 Sep 2024 12:28:51 +0200
Nuno Sá <noname.nuno@gmail.com> wrote:
> On Wed, 2024-09-04 at 14:01 +0200, Angelo Dureghello wrote:
> > Hi Jonathan,
> >
> > On 03/09/24 9:11 PM, Jonathan Cameron wrote:
> > > On Mon, 2 Sep 2024 16:03:22 +0200
> > > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > >
> > > > Hi Jonathan,
> > > >
> > > > thanks for the feedbacks,
> > > >
> > > > On 31/08/24 1:23 PM, Jonathan Cameron wrote:
> > > > > On Thu, 29 Aug 2024 14:32:00 +0200
> > > > > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > > > >
> > > > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > > > >
> > > > > > Extend backend features with new calls needed later on this
> > > > > > patchset from axi version of ad3552r.
> > > > > >
> > > > > > A bus type property has been added to the devicetree to
> > > > > > inform the backend about the type of bus (interface) in use
> > > > > > bu the IP.
> > > > > >
> > > > > > The follwoing calls are added:
> > > > > >
> > > > > > iio_backend_ext_sync_enable
> > > > > > enable synchronize channels on external trigger
> > > > > > iio_backend_ext_sync_disable
> > > > > > disable synchronize channels on external trigger
> > > > > > iio_backend_ddr_enable
> > > > > > enable ddr bus transfer
> > > > > > iio_backend_ddr_disable
> > > > > > disable ddr bus transfer
> > > > > > iio_backend_set_bus_mode
> > > > > > select the type of bus, so that specific read / write
> > > > > > operations are performed accordingly
> > > > > > iio_backend_buffer_enable
> > > > > > enable buffer
> > > > > > iio_backend_buffer_disable
> > > > > > disable buffer
> > > > > > iio_backend_data_transfer_addr
> > > > > > define the target register address where the DAC sample
> > > > > > will be written.
> > > > > > iio_backend_bus_reg_read
> > > > > > generic bus read, bus-type dependent
> > > > > > iio_backend_bus_read_write
> > > > > > generic bus write, bus-type dependent
> > > > > >
> > > > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > > > > ---
> > > > > > drivers/iio/industrialio-backend.c | 151
> > > > > > +++++++++++++++++++++++++++++++++++++
> > > > > > include/linux/iio/backend.h | 24 ++++++
> > > > > > 2 files changed, 175 insertions(+)
> > > > > >
> > > > > > diff --git a/drivers/iio/industrialio-backend.c
> > > > > > b/drivers/iio/industrialio-backend.c
> > > > > > index a52a6b61c8b5..1f60c8626be7 100644
> > > > > > --- a/drivers/iio/industrialio-backend.c
> > > > > > +++ b/drivers/iio/industrialio-backend.c
> > > > > > @@ -718,6 +718,157 @@ static int __devm_iio_backend_get(struct device
> > > > > > *dev, struct iio_backend *back)
> > > > > > return 0;
> > > > > > }
> > > > >
> > > > > > +
> > > > > > +/**
> > > > > > + * iio_backend_buffer_enable - Enable data buffering
> > > > > Data buffering is a very vague term. Perhaps some more detail on what
> > > > > this means?
> > > > for this DAC IP, it is the dma buffer where i write the samples,
> > > > for other non-dac frontends may be something different, so i kept it
> > > > generic. Not sure what a proper name may be, maybe
> > > >
> > > > "Enable optional data buffer" ?
> > > How do you 'enable' a buffer? Enable writing into it maybe?
> >
> > for the current case, this is done using the custom register
> > of the AXI IP, enabling a "stream".
> >
> > return regmap_set_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
> > AXI_DAC_STREAM_ENABLE);
> >
> > Functionally, looks like dma data is processed (sent over qspi)
> > when the stream is enabled.
> >
> > Maybe a name as "stream_enable" would me more appropriate ?
> > "Stream" seems less generic btw.
> >
Ok. Maybe "enable buffer filling" or something like that?
>
> Yes, stream enable is very specific for this usecase. This is basically
> connected to typical IIO buffering. So maybe we could either:
>
> 1) Embed struct iio_buffer_setup_ops in the backend ops struct;
> 2) Or just define directly the ones we need now in backend ops.
Structurally whatever makes sense - I was just quibbling over the
documentation ;)
>
> > > >
> > > > > > + * @back: Backend device
> > > > > > + *
> > > > > > + * RETURNS:
> > > > > > + * 0 on success, negative error number on failure.
> > > > > > + */
> > > > > > +int iio_backend_buffer_enable(struct iio_backend *back)
> > > > > > +{
> > > > > > + return iio_backend_op_call(back, buffer_enable);
> > > > > > +}
> > > > > > +EXPORT_SYMBOL_NS_GPL(iio_backend_buffer_enable, IIO_BACKEND);
> > > > > > +
> > > > > > +/**
> > > > > > +/**
> > > > > > + * iio_backend_bus_reg_read - Read from the interface bus
> > > > > > + * @back: Backend device
> > > > > > + * @reg: Register valule
> > > > > > + * @val: Pointer to register value
> > > > > > + * @size: Size, in bytes
> > > > > > + *
> > > > > > + * A backend may operate on a specific interface with a related bus.
> > > > > > + * Read from the interface bus.
> > > > > So this is effectively routing control plane data through the offloaded
> > > > > bus? That sounds a lot more like a conventional bus than IIO backend.
> > > > > Perhaps it should be presented as that with the IIO device attached
> > > > > to that bus? I don't fully understand what is wired up here.
> > > > >
> > > > Mainly, an IP may include a bus as 16bit parallel, or LVDS, or similar
> > > > to QSPI as in my case (ad3552r).
> > > ok.
> > >
> > > If this is a bus used for both control and dataplane, then we should really
> > > be presenting it as a bus (+ offload) similar to do for spi + offload.
> > >
>
> Yes, indeed. In this case we also use the axi-dac core for controlling the
> frontend device (accessing it's register) which is fairly weird. But not sure
> how we can do it differently. For the spi_engine that is really a spi controller
> with the extra offloading capability. For this one, it's now "acting" as a spi
> controller but in the future it may also "act" as a parallel controller (the
> axi-adc already is in works for that with the ad7606 series).
>
> I was also very skeptical when I first saw these new functions but I'm not
> really sure how to do it differently. I mean, it also does not make much sense
> to have an additional bus driver as the register maps are the same. Not sure if
> turning it in a MFD device, helps...
Hmm. A given adi-axi-adc interface is going to be one of (or something else)
1) SPI(ish) controller + offloads like this one.
2) Parallel bus - data only
3) Parallel bus with control.
Maybe we argue these are tightly coupled enough that we don't care but it
feels like a direction that might bite us in the long run, particularly
if we end up dt bindings that are hard to work with if we change
how this fits together - imagine an SPI engine with a mode that does work
for this + an SPI offload engine that works with that.
Then the binding here will be hard to deal with.
>
> FWIW, I still don't fully understand why can't we have this supported by the
> spi_engine core. My guess is that we need features from the axi-dac (for the
> dataplane) so we are incorporating the controlplane on it instead of going
> spi_engine + axi-dac.
>
> Also want to leave a quick note about LVDS (that was mentioned). That interface
> is typically only used for data so I'm not seeing any special handling like this
> for that interface.
Makes sense. I'm a bit surprised that the parallel bus being used for control
is on the list given that is also a bit messy to do (need some signalling that
direction is changing or a lot of wires).
Jonathan
>
> - Nuno Sá
> > >
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi
2024-09-05 9:16 ` Nuno Sá
@ 2024-09-07 14:12 ` Jonathan Cameron
2024-09-09 7:37 ` Nuno Sá
0 siblings, 1 reply; 54+ messages in thread
From: Jonathan Cameron @ 2024-09-07 14:12 UTC (permalink / raw)
To: Nuno Sá
Cc: David Lechner, Angelo Dureghello, Lars-Peter Clausen,
Michael Hennerich, Nuno Sá, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Olivier Moysan, linux-iio, devicetree, linux-kernel,
Mark Brown
On Thu, 05 Sep 2024 11:16:03 +0200
Nuno Sá <noname.nuno@gmail.com> wrote:
> On Tue, 2024-09-03 at 20:39 +0100, Jonathan Cameron wrote:
> > On Tue, 3 Sep 2024 11:17:24 -0500
> > David Lechner <dlechner@baylibre.com> wrote:
> >
> > > On 9/3/24 3:34 AM, Angelo Dureghello wrote:
> > > > Hi Jonathan and all,
> > > >
> > > >
> > > > On 31/08/24 1:38 PM, Jonathan Cameron wrote:
> > > > > On Thu, 29 Aug 2024 14:31:58 +0200
> > > > > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > > > >
> > > > > > Hi, asking for comments for this patchset, that is mostly
> > > > > > ready, at least feature-complete and functionally tested.
> > > > > >
> > > > > > I am introducing ad3552r-axi variant, controlled from a fpga-based
> > > > > > AXI IP, as a platform driver, using the DAC backend. The patchset is
> > > > > > actually based on linux-iio, since some needed DAC backend features
> > > > > > was already there on that repo only, still to be merged in mainline.
> > > > > >
> > > > > > Comments i would like to ask are:
> > > > > >
> > > > > > - i added some devicetree bindings inside current ad3552r yaml,
> > > > > > device is the same, so i wouldn't create a different yaml file.
> > > > > Agreed. If same device, it's usually better to keep it in one file.
> > > > >
> > > > > > - if it's ok adding the bus-type property in the DAC backend:
> > > > > > actually, this platform driver uses a 4 lanes parallel bus, plus
> > > > > > a clock line, similar to a qspi. This to read an write registers
> > > > > > and as well to send samples at double data rate. Other DAC may
> > > > > > need "parallel" or "lvds" in the future.
> > > > > If it is for register read + write as well, sounds to me like you need
> > > > > to treat this as a new bus type, possibly then combined with a
> > > > > backend, or something similar to spi offload?
> > > > >
> > > > > What bus does this currently sit on in your DT bindings?
> > > > > (add an example)
> > > >
> > > >
> > > > &amba {
> > > >
> > > > ref_clk: clk@44B00000 {
> > > > compatible = "adi,axi-clkgen-2.00.a";
> > > > reg = <0x44B00000 0x10000>;
> > > > #clock-cells = <0>;
> > > > clocks = <&clkc 15>, <&clkc 15>;
> > > > clock-names = "s_axi_aclk", "clkin1";
> > > > clock-output-names = "ref_clk";
> > > > };
> > > >
> > > > dac_tx_dma: dma-controller@0x44a30000 {
> > > > compatible = "adi,axi-dmac-1.00.a";
> > > > reg = <0x44a30000 0x10000>;
> > > > #dma-cells = <1>;
> > > > interrupt-parent = <&intc>;
> > > > interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
> > > > clocks = <&clkc 15>;
> > > >
> > > > adi,channels {
> > > > #size-cells = <0>;
> > > > #address-cells = <1>;
> > > >
> > > > dma-channel@0 {
> > > > reg = <0>;
> > > > adi,source-bus-width = <32>;
> > > > adi,source-bus-type = <0>;
> > > > adi,destination-bus-width = <32>;
> > > > adi,destination-bus-type = <1>;
> > > > };
> > > > };
> > > > };
> > > >
> > > > backend: controller@44a70000 {
> > > > compatible = "adi,axi-dac-9.1.b";
> > > > reg = <0x44a70000 0x1000>;
> > > > dmas = <&dac_tx_dma 0>;
> > > > dma-names = "tx";
> > > > #io-backend-cells = <0>;
> > > > clocks = <&ref_clk>;
> > > > bus-type = <1>; /* IIO QSPI */
> > > > };
> > > >
> > > > axi-ad3552r {
> > > > compatible = "adi,ad3552r";
> > > > reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
> > > > io-backends = <&backend>;
> > > > #address-cells = <1>;
> > > > #size-cells = <0>;
> > > > channel@0 {
> > > > reg = <0>;
> > > > adi,output-range-microvolt = <(-10000000) (10000000)>;
> > > > };
> > > > };
> > >
> > > Shouldn't the axi-ad3552r node be one level higher since it isn't
> > > a memory-mapped device, but rather an external chip?
> > Definitely not where it currently is..
> > >
> > > But based on the other feedback we got in this series and some
> > > #devicetree IRC chat here is an alternate binding suggestion we
> > > could consider.
> > >
> > > First, even though the FPGA IP block for use with AD3225R uses
> > > the same register map as the AXI DAC IP block, some of the
> > > registers behave differently, so it makes sense to have a
> > > different compatible string rather than using the bus-type
> > > property to tell the difference between the two IP blocks.
> > > There are likely more differences than just the bus type.
> >
> > I'd be amazed if they managed to keep things that similar
> > given totally different buses.
> >
>
> Yeah, I was trying to avoid new compatibles as much as I can because things can
> get pretty confusing (with lots of new compatibles and quirks) pretty quickly.
> Typically yes, most designs have slight differences between them (with new
> features and so on) but so far I was trying (thinking) to have those as a
> generic new backend op (plus a matching binding property if needed). For this
> particular case, I'm fairly sure we could get away with the bus controller
> property and having different implementations depending on the bus being
> implemented. For the other bits that might differ between designs (eg: DDR
> support) is up to frontends to call it or not (depending on they having that
> feature or not).
That breaks down if the backend you happen to be using (maybe a new
one hasn't been written yet) is missing the DDR feature but the front end
device can run with or without it.
Unless the hardware makes this discoverable you'll have the backend driver
writing some enable bit that does nothing.
Maybe it's a case of using fallback compatibles - so define more specific
ones but with a fallback to one that doesn't provide the fancy features
and only covers thins all IPs support.
> Naturally we need that the IPs having DDR support to not have
> the same thing supported in different registers but we do control that since
> these are FPGA cores.
>
> All the above said, I'm fine with new compatibles but we need to draw a line
> when we add new ones. If the reasoning is the IP has some new bits or new
> registers, then things can get very confusing (even more if we think about
> fallback compatibles) as most of the new designs have some quirks (even if
> minimal). So I would say to add new compatibles when things get different enough
> that a sane/generic API is not doable.
If you can influence the IP designers, the usual solution to this is
discoverability of features. So standard register that all IP carries that
has flags for each feature that has ever been implemented.
If not, best option is each IP gets a compatible but we assume fallbacks
are fine until they aren't.
Jonathan
>
> > >
> > > Second, technically, the AXI DAC IP block can't be used as
> > > a generic SPI controller, so it wouldn't make sense to put
> > > it in drivers/spi.
> >
> > I wonder if there is any precedence of restricted controllers
> > for SPI? (For i2c we have the smbus ones as a vaguely similar
> > example). +CC Mark.
> >
> > > But, from wiring point of view, it could
> > > still make sense to use SPI DT bindings since we have SPI
> > > wiring. At the same time, the AXI DAC IP block is also
> > > providing extra functionality in addition to the SPI bus
> > > so it makes sense to keep the io-backend bindings for those
> > > extra bits.
> > >
> > > backend: spi@44a70000 {
> > > compatible = "adi,axi-dac-ad3225r";
> > > reg = <0x44a70000 0x1000>;
> > > dmas = <&dac_tx_dma 0>;
> > > dma-names = "tx";
> > > #io-backend-cells = <0>;
> > > clocks = <&ref_clk>;
> > >
> > > #address-cells = <1>;
> > > #size-cells = <0>;
> > >
> > > dac@0 {
> > > compatible = "adi,ad3552r";
> > > reg = <0>;
> > >
> > > /*
> > > * Not sure how right this is - attempting to say that
> > > * the QSPI select pin is hardwired high, so the 4 SPI I/O
> > > * pins on the DAC are always functioning as SDIO0/1/2/3
> > > * as opposed to the usual 2 SDI/SDO pins and 2 unused.
> > > */
> > > spi-3-wire;
> > > spi-tx-bus-width = <4>;
> > > spi-rx-bus-width = <4>;
> > >
> > > reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
> > > io-backends = <&backend>;
> > >
> > > #address-cells = <1>;
> > > #size-cells = <0>;
> > >
> > > channel@0 {
> > > reg = <0>;
> > > adi,output-range-microvolt = <(-10000000) (10000000)>;
> > > };
> > > };
> > > };
> >
> > That's definitely an improvement. It's a little strange to have
> > a reference back to the parent but I'm fine with that.
> >
>
> Agreed...
>
> - Nuno Sá
>
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi
2024-09-07 14:12 ` Jonathan Cameron
@ 2024-09-09 7:37 ` Nuno Sá
2024-09-09 18:59 ` Jonathan Cameron
0 siblings, 1 reply; 54+ messages in thread
From: Nuno Sá @ 2024-09-09 7:37 UTC (permalink / raw)
To: Jonathan Cameron
Cc: David Lechner, Angelo Dureghello, Lars-Peter Clausen,
Michael Hennerich, Nuno Sá, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Olivier Moysan, linux-iio, devicetree, linux-kernel,
Mark Brown
On Sat, 2024-09-07 at 15:12 +0100, Jonathan Cameron wrote:
> On Thu, 05 Sep 2024 11:16:03 +0200
> Nuno Sá <noname.nuno@gmail.com> wrote:
>
> > On Tue, 2024-09-03 at 20:39 +0100, Jonathan Cameron wrote:
> > > On Tue, 3 Sep 2024 11:17:24 -0500
> > > David Lechner <dlechner@baylibre.com> wrote:
> > >
> > > > On 9/3/24 3:34 AM, Angelo Dureghello wrote:
> > > > > Hi Jonathan and all,
> > > > >
> > > > >
> > > > > On 31/08/24 1:38 PM, Jonathan Cameron wrote:
> > > > > > On Thu, 29 Aug 2024 14:31:58 +0200
> > > > > > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > > > > >
> > > > > > > Hi, asking for comments for this patchset, that is mostly
> > > > > > > ready, at least feature-complete and functionally tested.
> > > > > > >
> > > > > > > I am introducing ad3552r-axi variant, controlled from a fpga-based
> > > > > > > AXI IP, as a platform driver, using the DAC backend. The patchset
> > > > > > > is
> > > > > > > actually based on linux-iio, since some needed DAC backend
> > > > > > > features
> > > > > > > was already there on that repo only, still to be merged in
> > > > > > > mainline.
> > > > > > >
> > > > > > > Comments i would like to ask are:
> > > > > > >
> > > > > > > - i added some devicetree bindings inside current ad3552r yaml,
> > > > > > > device is the same, so i wouldn't create a different yaml
> > > > > > > file.
> > > > > > Agreed. If same device, it's usually better to keep it in one file.
> > > > > >
> > > > > > > - if it's ok adding the bus-type property in the DAC backend:
> > > > > > > actually, this platform driver uses a 4 lanes parallel bus,
> > > > > > > plus
> > > > > > > a clock line, similar to a qspi. This to read an write
> > > > > > > registers
> > > > > > > and as well to send samples at double data rate. Other DAC may
> > > > > > > need "parallel" or "lvds" in the future.
> > > > > > If it is for register read + write as well, sounds to me like you
> > > > > > need
> > > > > > to treat this as a new bus type, possibly then combined with a
> > > > > > backend, or something similar to spi offload?
> > > > > >
> > > > > > What bus does this currently sit on in your DT bindings?
> > > > > > (add an example)
> > > > >
> > > > >
> > > > > &amba {
> > > > >
> > > > > ref_clk: clk@44B00000 {
> > > > > compatible = "adi,axi-clkgen-2.00.a";
> > > > > reg = <0x44B00000 0x10000>;
> > > > > #clock-cells = <0>;
> > > > > clocks = <&clkc 15>, <&clkc 15>;
> > > > > clock-names = "s_axi_aclk", "clkin1";
> > > > > clock-output-names = "ref_clk";
> > > > > };
> > > > >
> > > > > dac_tx_dma: dma-controller@0x44a30000 {
> > > > > compatible = "adi,axi-dmac-1.00.a";
> > > > > reg = <0x44a30000 0x10000>;
> > > > > #dma-cells = <1>;
> > > > > interrupt-parent = <&intc>;
> > > > > interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
> > > > > clocks = <&clkc 15>;
> > > > >
> > > > > adi,channels {
> > > > > #size-cells = <0>;
> > > > > #address-cells = <1>;
> > > > >
> > > > > dma-channel@0 {
> > > > > reg = <0>;
> > > > > adi,source-bus-width = <32>;
> > > > > adi,source-bus-type = <0>;
> > > > > adi,destination-bus-width = <32>;
> > > > > adi,destination-bus-type = <1>;
> > > > > };
> > > > > };
> > > > > };
> > > > >
> > > > > backend: controller@44a70000 {
> > > > > compatible = "adi,axi-dac-9.1.b";
> > > > > reg = <0x44a70000 0x1000>;
> > > > > dmas = <&dac_tx_dma 0>;
> > > > > dma-names = "tx";
> > > > > #io-backend-cells = <0>;
> > > > > clocks = <&ref_clk>;
> > > > > bus-type = <1>; /* IIO QSPI */
> > > > > };
> > > > >
> > > > > axi-ad3552r {
> > > > > compatible = "adi,ad3552r";
> > > > > reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
> > > > > io-backends = <&backend>;
> > > > > #address-cells = <1>;
> > > > > #size-cells = <0>;
> > > > > channel@0 {
> > > > > reg = <0>;
> > > > > adi,output-range-microvolt = <(-10000000) (10000000)>;
> > > > > };
> > > > > };
> > > >
> > > > Shouldn't the axi-ad3552r node be one level higher since it isn't
> > > > a memory-mapped device, but rather an external chip?
> > > Definitely not where it currently is..
> > > >
> > > > But based on the other feedback we got in this series and some
> > > > #devicetree IRC chat here is an alternate binding suggestion we
> > > > could consider.
> > > >
> > > > First, even though the FPGA IP block for use with AD3225R uses
> > > > the same register map as the AXI DAC IP block, some of the
> > > > registers behave differently, so it makes sense to have a
> > > > different compatible string rather than using the bus-type
> > > > property to tell the difference between the two IP blocks.
> > > > There are likely more differences than just the bus type.
> > >
> > > I'd be amazed if they managed to keep things that similar
> > > given totally different buses.
> > >
> >
> > Yeah, I was trying to avoid new compatibles as much as I can because things
> > can
> > get pretty confusing (with lots of new compatibles and quirks) pretty
> > quickly.
> > Typically yes, most designs have slight differences between them (with new
> > features and so on) but so far I was trying (thinking) to have those as a
> > generic new backend op (plus a matching binding property if needed). For
> > this
> > particular case, I'm fairly sure we could get away with the bus controller
> > property and having different implementations depending on the bus being
> > implemented. For the other bits that might differ between designs (eg: DDR
> > support) is up to frontends to call it or not (depending on they having that
> > feature or not).
>
> That breaks down if the backend you happen to be using (maybe a new
> one hasn't been written yet) is missing the DDR feature but the front end
> device can run with or without it.
> Unless the hardware makes this discoverable you'll have the backend driver
> writing some enable bit that does nothing.
>
> Maybe it's a case of using fallback compatibles - so define more specific
> ones but with a fallback to one that doesn't provide the fancy features
> and only covers thins all IPs support.
>
> > Naturally we need that the IPs having DDR support to not have
> > the same thing supported in different registers but we do control that since
> > these are FPGA cores.
> >
> > All the above said, I'm fine with new compatibles but we need to draw a line
> > when we add new ones. If the reasoning is the IP has some new bits or new
> > registers, then things can get very confusing (even more if we think about
> > fallback compatibles) as most of the new designs have some quirks (even if
> > minimal). So I would say to add new compatibles when things get different
> > enough
> > that a sane/generic API is not doable.
>
> If you can influence the IP designers, the usual solution to this is
> discoverability of features. So standard register that all IP carries that
> has flags for each feature that has ever been implemented.
>
That get's messy. We do have some flags for some of the more generic features
(I'm using them in the backends when available). But we have (and will have) so
many variations of these designs that it get's hard to get it right all the
time. And for thing like this bus quirk a flag itself may be not enough to
distinguish between different implementations...
Last time I spoke with the designers, they are thinking about just adding a set
of custom registers that (always the same range I think) for these IPs and then
leave it up to the driver implementation to deal with the different
implementations of the registers. Not sure if it's the best approach but it
feels like they're getting tired of dealing with all the subtle changes between
the different devices these IPs connect too :)
On the IIO backend "world", frontends are the ones with the knowledge of what
these custom registers could implement and so, it's very doable for backends to
export a range of valid registers for frontends to "directly" (of course not
reading/writing directly :)) access. Feels a bit hacky but also a bit
reasonable... Anyways, all of the above is still just speculation so not sure if
it will happen at all. Just some ramblings from me :)
> If not, best option is each IP gets a compatible but we assume fallbacks
> are fine until they aren't.
>
Yeah, Conor made some compelling arguments about using new compatibles. At
least, for the more complicated cases like this.
- Nuno Sá
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property
2024-09-07 8:53 ` Angelo Dureghello
@ 2024-09-09 12:17 ` Conor Dooley
0 siblings, 0 replies; 54+ messages in thread
From: Conor Dooley @ 2024-09-09 12:17 UTC (permalink / raw)
To: Angelo Dureghello
Cc: Nuno Sá, Conor Dooley, Lars-Peter Clausen, Michael Hennerich,
Nuno Sá, Jonathan Cameron, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Olivier Moysan, linux-iio, devicetree, linux-kernel,
dlechner
[-- Attachment #1: Type: text/plain, Size: 7969 bytes --]
On Sat, Sep 07, 2024 at 10:53:07AM +0200, Angelo Dureghello wrote:
>
> On 06/09/24 1:32 PM, Nuno Sá wrote:
> > On Fri, 2024-09-06 at 10:04 +0100, Conor Dooley wrote:
> > > On Mon, Sep 02, 2024 at 11:32:37AM +0200, Angelo Dureghello wrote:
> > > > Hi Conor,
> > > >
> > > >
> > > > On 30/08/24 5:33 PM, Conor Dooley wrote:
> > > > > On Fri, Aug 30, 2024 at 10:19:49AM +0200, Angelo Dureghello wrote:
> > > > > > Hi Conor,
> > > > > >
> > > > > > On 29/08/24 5:46 PM, Conor Dooley wrote:
> > > > > > > On Thu, Aug 29, 2024 at 02:32:02PM +0200, Angelo Dureghello wrote:
> > > > > > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > > > > > >
> > > > > > > > Add bus property.
> > > > > > > RFC it may be, but you do need to explain what this bus-type actually
> > > > > > > describes for commenting on the suitability of the method to be
> > > > > > > meaningful.
> > > > > > thanks for the feedbacks,
> > > > > >
> > > > > > a "bus" is intended as a generic interface connected to the target,
> > > > > > may be used from a custom IP (fpga) to communicate with the target
> > > > > > device (by read/write(reg and value)) using a special custom interface.
> > > > > >
> > > > > > The bus could also be physically the same of some well-known existing
> > > > > > interfaces (as parallel, lvds or other uncommon interfaces), but using
> > > > > > an uncommon/custom protocol over it.
> > > > > >
> > > > > > In concrete, actually bus-type is added to the backend since the
> > > > > > ad3552r DAC chip can be connected (for maximum speed) by a 5 lanes DDR
> > > > > > parallel bus (interface that i named QSPI, but it's not exactly a QSPI
> > > > > > as a protocol), so it's a device-specific interface.
> > > > > >
> > > > > > With additions in this patchset, other frontends, of course not only
> > > > > > DACs, will be able to add specific busses and read/wrtie to the bus
> > > > > > as needed.
> > > > > >
> > > > > > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > > > > > > ---
> > > > > > > > Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 9
> > > > > > > > +++++++++
> > > > > > > > 1 file changed, 9 insertions(+)
> > > > > > > >
> > > > > > > > diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > > > b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > > > index a55e9bfc66d7..a7ce72e1cd81 100644
> > > > > > > > --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > > > +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > > > @@ -38,6 +38,15 @@ properties:
> > > > > > > > clocks:
> > > > > > > > maxItems: 1
> > > > > > > You mentioned about new compatible strings, does the one currently
> > > > > > > listed in this binding support both bus types?
> > > > > You didn't answer this, and there's insufficient explanation of the
> > > > > "hardware" in this RFC, but I found this which is supposedly the
> > > > > backend:
> > > > > https://github.com/analogdevicesinc/hdl/tree/main/library/axi_ad3552r
> > > > > adi,axi-dac.yaml has a single compatible, and that compatible has
> > > > > nothing to do with "axi_ad3552r" as it is "adi,axi-dac-9.1.b". I would
> > > > > expect either justification for reuse of the compatible, or a brand new
> > > > > compatible for this backend, even if the driver can mostly be reused.
> > > > >
> > > > > Could you please link to whatever ADI wiki has detailed information on
> > > > > how this stuff works so that I can look at it to better understand the
> > > > > axes of configuration here?
> > > > https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
> > > >
> > > > that has same structure and register set of the generic ADI AXI-DAC IP:
> > > > https://wiki.analog.com/resources/fpga/docs/axi_dac_ip
> > > >
> > > >
> > > > > > > Making the bus type decision based on compatible only really makes sense
> > > > > > > if they're different versions of the IP, but not if they're different
> > > > > > > configuration options for a given version.
> > > > > > >
> > > > > > > > + bus-type:
> > > > > > DAC IP on fpga actually respects same structure and register set, except
> > > > > > for a named "custom" register that may use specific bitfields depending
> > > > > > on the application of the IP.
> > > > > To paraphrase:
> > > > > "The register map is the same, except for the bit that is different".
> > > > > If ADI is shipping several different configurations of this IP for
> > > > > different DACs, I'd be expecting different compatibles for each backend
> > > > > to be honest
> > > > i am still quite new to this fpga-based implementations, at least for how
> > > > such IPs are actually interfacing to the linux subsystem, so i may miss
> > > > some point.
> > > >
> > > > About the "adi,axi-dac-9.1.b" compatible, the generic DAC IP register set
> > > > is mostly the same structure of this ad3552r IP (links above), except for
> > > > bitfields in the DAC_CUSTOM_CTRL register.
> > > >
> > > > My choice for now was to add a bus-type property.
> > > >
> > > > Not an HDL expert, but i think a different bus means, from an hardware point
> > > > of
> > > > view, a different IP in terms of internal fpga circuitry, even if not as a
> > > > register-set.
> > >
> > > Depending on whether or not the unmodified driver can be used with this
> > > IP (so the QSPI bus stuff would need to be optional) then a fallback
> > > should be used given the degree of similarity. It, however, seems likely
> > > that is not the case, and without the QSPI bus there'd be no way to
> > > communicate with the device. Is there any reason to use this IP as a
> > > backend, without connecting the QSPI bus at all, leaving the ADC/DAC on
> > > a regular SPI bus?
> > >
> > Somewhere in my replies, I'm doing the exact same question to myself. We probably
> > need to speak with the FPGA folks but I guess (hope) they had a good reason for this.
>
> to clarify a bit the custom (fpga-based) QSPI need, i did some checks in the
> datasheets:
>
> 1. ADI is actually supporting ad3552r by eval-ad3552r-fmcx eval boards,
> with specific fmc connector for the ZedBoard (zynq7000). This is the
> current focused hardware for this job.
"currently focused" being the key words! Since it is FPGA IP, you've got
no control over where it is being used, so the particular use case you're
developing for is not really that important.
> 2. Zynq7000 std non-fpga controller is designed to control flash memories,
> but can operate in "raw I/O" mode, so it may work with ad3552r, but is not
> supporting DDR, even if it may reach 100Mhz clock.
>
> 3. ad3552r accepts a maximum clock of 66Mhz. So for ZedBoard maximum speed
> of 33MUPS cannot be reached without DDR.
>
> 4. ad3552r requires DDR only in the data part, and in DDR mode we
> may also send some "non-loop" reg read/write, so requiring also the
> address to be sent in SDR. Not sure how many QSPI controllers in the market
> are
> working this way, even if it seems quite standard, looks like not many are
> actually
> supporting DDR. There may be, but not actually in the priority of my
> customer
> right now. And in that case, we could extend the generic spi ad3552r.c.
I think you need to ignore your use case here, and just consider whether or
not this IP can be used as a backend without the QSPI feature. That's
probably an easier thing to determine than whether or not there's another
controller out there that can satisfy the constraints. The docs say it
"interfaces", but that's such a generic word that it ultimately means
close to nothing.. There's the sync ability, but from my reading of the
github.io page, it doesn't do anything when the axi-dac is not actually
in the data path.
Cheers,
Conor.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi
2024-09-09 7:37 ` Nuno Sá
@ 2024-09-09 18:59 ` Jonathan Cameron
0 siblings, 0 replies; 54+ messages in thread
From: Jonathan Cameron @ 2024-09-09 18:59 UTC (permalink / raw)
To: Nuno Sá
Cc: David Lechner, Angelo Dureghello, Lars-Peter Clausen,
Michael Hennerich, Nuno Sá, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Olivier Moysan, linux-iio, devicetree, linux-kernel,
Mark Brown
On Mon, 09 Sep 2024 09:37:35 +0200
Nuno Sá <noname.nuno@gmail.com> wrote:
> On Sat, 2024-09-07 at 15:12 +0100, Jonathan Cameron wrote:
> > On Thu, 05 Sep 2024 11:16:03 +0200
> > Nuno Sá <noname.nuno@gmail.com> wrote:
> >
> > > On Tue, 2024-09-03 at 20:39 +0100, Jonathan Cameron wrote:
> > > > On Tue, 3 Sep 2024 11:17:24 -0500
> > > > David Lechner <dlechner@baylibre.com> wrote:
> > > >
> > > > > On 9/3/24 3:34 AM, Angelo Dureghello wrote:
> > > > > > Hi Jonathan and all,
> > > > > >
> > > > > >
> > > > > > On 31/08/24 1:38 PM, Jonathan Cameron wrote:
> > > > > > > On Thu, 29 Aug 2024 14:31:58 +0200
> > > > > > > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > > > > > >
> > > > > > > > Hi, asking for comments for this patchset, that is mostly
> > > > > > > > ready, at least feature-complete and functionally tested.
> > > > > > > >
> > > > > > > > I am introducing ad3552r-axi variant, controlled from a fpga-based
> > > > > > > > AXI IP, as a platform driver, using the DAC backend. The patchset
> > > > > > > > is
> > > > > > > > actually based on linux-iio, since some needed DAC backend
> > > > > > > > features
> > > > > > > > was already there on that repo only, still to be merged in
> > > > > > > > mainline.
> > > > > > > >
> > > > > > > > Comments i would like to ask are:
> > > > > > > >
> > > > > > > > - i added some devicetree bindings inside current ad3552r yaml,
> > > > > > > > device is the same, so i wouldn't create a different yaml
> > > > > > > > file.
> > > > > > > Agreed. If same device, it's usually better to keep it in one file.
> > > > > > >
> > > > > > > > - if it's ok adding the bus-type property in the DAC backend:
> > > > > > > > actually, this platform driver uses a 4 lanes parallel bus,
> > > > > > > > plus
> > > > > > > > a clock line, similar to a qspi. This to read an write
> > > > > > > > registers
> > > > > > > > and as well to send samples at double data rate. Other DAC may
> > > > > > > > need "parallel" or "lvds" in the future.
> > > > > > > If it is for register read + write as well, sounds to me like you
> > > > > > > need
> > > > > > > to treat this as a new bus type, possibly then combined with a
> > > > > > > backend, or something similar to spi offload?
> > > > > > >
> > > > > > > What bus does this currently sit on in your DT bindings?
> > > > > > > (add an example)
> > > > > >
> > > > > >
> > > > > > &amba {
> > > > > >
> > > > > > ref_clk: clk@44B00000 {
> > > > > > compatible = "adi,axi-clkgen-2.00.a";
> > > > > > reg = <0x44B00000 0x10000>;
> > > > > > #clock-cells = <0>;
> > > > > > clocks = <&clkc 15>, <&clkc 15>;
> > > > > > clock-names = "s_axi_aclk", "clkin1";
> > > > > > clock-output-names = "ref_clk";
> > > > > > };
> > > > > >
> > > > > > dac_tx_dma: dma-controller@0x44a30000 {
> > > > > > compatible = "adi,axi-dmac-1.00.a";
> > > > > > reg = <0x44a30000 0x10000>;
> > > > > > #dma-cells = <1>;
> > > > > > interrupt-parent = <&intc>;
> > > > > > interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
> > > > > > clocks = <&clkc 15>;
> > > > > >
> > > > > > adi,channels {
> > > > > > #size-cells = <0>;
> > > > > > #address-cells = <1>;
> > > > > >
> > > > > > dma-channel@0 {
> > > > > > reg = <0>;
> > > > > > adi,source-bus-width = <32>;
> > > > > > adi,source-bus-type = <0>;
> > > > > > adi,destination-bus-width = <32>;
> > > > > > adi,destination-bus-type = <1>;
> > > > > > };
> > > > > > };
> > > > > > };
> > > > > >
> > > > > > backend: controller@44a70000 {
> > > > > > compatible = "adi,axi-dac-9.1.b";
> > > > > > reg = <0x44a70000 0x1000>;
> > > > > > dmas = <&dac_tx_dma 0>;
> > > > > > dma-names = "tx";
> > > > > > #io-backend-cells = <0>;
> > > > > > clocks = <&ref_clk>;
> > > > > > bus-type = <1>; /* IIO QSPI */
> > > > > > };
> > > > > >
> > > > > > axi-ad3552r {
> > > > > > compatible = "adi,ad3552r";
> > > > > > reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
> > > > > > io-backends = <&backend>;
> > > > > > #address-cells = <1>;
> > > > > > #size-cells = <0>;
> > > > > > channel@0 {
> > > > > > reg = <0>;
> > > > > > adi,output-range-microvolt = <(-10000000) (10000000)>;
> > > > > > };
> > > > > > };
> > > > >
> > > > > Shouldn't the axi-ad3552r node be one level higher since it isn't
> > > > > a memory-mapped device, but rather an external chip?
> > > > Definitely not where it currently is..
> > > > >
> > > > > But based on the other feedback we got in this series and some
> > > > > #devicetree IRC chat here is an alternate binding suggestion we
> > > > > could consider.
> > > > >
> > > > > First, even though the FPGA IP block for use with AD3225R uses
> > > > > the same register map as the AXI DAC IP block, some of the
> > > > > registers behave differently, so it makes sense to have a
> > > > > different compatible string rather than using the bus-type
> > > > > property to tell the difference between the two IP blocks.
> > > > > There are likely more differences than just the bus type.
> > > >
> > > > I'd be amazed if they managed to keep things that similar
> > > > given totally different buses.
> > > >
> > >
> > > Yeah, I was trying to avoid new compatibles as much as I can because things
> > > can
> > > get pretty confusing (with lots of new compatibles and quirks) pretty
> > > quickly.
> > > Typically yes, most designs have slight differences between them (with new
> > > features and so on) but so far I was trying (thinking) to have those as a
> > > generic new backend op (plus a matching binding property if needed). For
> > > this
> > > particular case, I'm fairly sure we could get away with the bus controller
> > > property and having different implementations depending on the bus being
> > > implemented. For the other bits that might differ between designs (eg: DDR
> > > support) is up to frontends to call it or not (depending on they having that
> > > feature or not).
> >
> > That breaks down if the backend you happen to be using (maybe a new
> > one hasn't been written yet) is missing the DDR feature but the front end
> > device can run with or without it.
> > Unless the hardware makes this discoverable you'll have the backend driver
> > writing some enable bit that does nothing.
> >
> > Maybe it's a case of using fallback compatibles - so define more specific
> > ones but with a fallback to one that doesn't provide the fancy features
> > and only covers thins all IPs support.
> >
> > > Naturally we need that the IPs having DDR support to not have
> > > the same thing supported in different registers but we do control that since
> > > these are FPGA cores.
> > >
> > > All the above said, I'm fine with new compatibles but we need to draw a line
> > > when we add new ones. If the reasoning is the IP has some new bits or new
> > > registers, then things can get very confusing (even more if we think about
> > > fallback compatibles) as most of the new designs have some quirks (even if
> > > minimal). So I would say to add new compatibles when things get different
> > > enough
> > > that a sane/generic API is not doable.
> >
> > If you can influence the IP designers, the usual solution to this is
> > discoverability of features. So standard register that all IP carries that
> > has flags for each feature that has ever been implemented.
> >
>
> That get's messy. We do have some flags for some of the more generic features
> (I'm using them in the backends when available). But we have (and will have) so
> many variations of these designs that it get's hard to get it right all the
> time. And for thing like this bus quirk a flag itself may be not enough to
> distinguish between different implementations...
>
> Last time I spoke with the designers, they are thinking about just adding a set
> of custom registers that (always the same range I think) for these IPs and then
> leave it up to the driver implementation to deal with the different
> implementations of the registers. Not sure if it's the best approach but it
> feels like they're getting tired of dealing with all the subtle changes between
> the different devices these IPs connect too :)
>
> On the IIO backend "world", frontends are the ones with the knowledge of what
> these custom registers could implement and so, it's very doable for backends to
> export a range of valid registers for frontends to "directly" (of course not
> reading/writing directly :)) access. Feels a bit hacky but also a bit
> reasonable... Anyways, all of the above is still just speculation so not sure if
> it will happen at all. Just some ramblings from me :)
>
>
> > If not, best option is each IP gets a compatible but we assume fallbacks
> > are fine until they aren't.
> >
>
> Yeah, Conor made some compelling arguments about using new compatibles. At
> least, for the more complicated cases like this.
Agreed. With explanation above, we would still want the backends
to be able to protect against a front end asking for things they don't
support. Might not need to do that all the time, but if we don't
have a compatible to deal with incompatibilities we won't be able to
fix it when problems occur.
Old IP, newer driver would be the likely nasty case though other
way around is possible too (new IP, old driver)
Jonathan
>
> - Nuno Sá
^ permalink raw reply [flat|nested] 54+ messages in thread
end of thread, other threads:[~2024-09-09 18:59 UTC | newest]
Thread overview: 54+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-29 12:31 [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Angelo Dureghello
2024-08-29 12:31 ` [PATCH RFC 1/8] dt-bindings: iio: dac: ad3552r: add io-backend property Angelo Dureghello
2024-08-29 12:32 ` [PATCH RFC 2/8] iio: backend: extend features Angelo Dureghello
2024-08-31 11:23 ` Jonathan Cameron
2024-09-02 14:03 ` Angelo Dureghello
2024-09-03 19:11 ` Jonathan Cameron
2024-09-04 12:01 ` Angelo Dureghello
2024-09-05 10:28 ` Nuno Sá
2024-09-07 14:02 ` Jonathan Cameron
2024-08-29 12:32 ` [PATCH RFC 3/8] iio: backend adi-axi-dac: backend features Angelo Dureghello
2024-08-31 11:34 ` Jonathan Cameron
2024-09-02 16:04 ` Angelo Dureghello
2024-09-03 19:16 ` Jonathan Cameron
2024-09-05 10:49 ` Nuno Sá
2024-09-05 11:58 ` Angelo Dureghello
2024-09-06 5:54 ` Nuno Sá
2024-09-05 12:11 ` Angelo Dureghello
2024-09-06 5:53 ` Nuno Sá
2024-08-29 12:32 ` [PATCH RFC 4/8] dt-bindings: iio: dac: add adi axi-dac bus property Angelo Dureghello
2024-08-29 13:39 ` Rob Herring (Arm)
2024-08-29 15:46 ` Conor Dooley
2024-08-30 8:16 ` Krzysztof Kozlowski
2024-08-30 15:06 ` Conor Dooley
2024-08-30 8:19 ` Angelo Dureghello
2024-08-30 15:33 ` Conor Dooley
2024-09-02 9:32 ` Angelo Dureghello
2024-09-03 19:18 ` Jonathan Cameron
2024-09-06 9:04 ` Conor Dooley
2024-09-06 11:32 ` Nuno Sá
2024-09-07 8:53 ` Angelo Dureghello
2024-09-09 12:17 ` Conor Dooley
2024-09-05 9:50 ` Nuno Sá
2024-09-06 8:50 ` Conor Dooley
2024-09-06 8:55 ` Conor Dooley
2024-09-06 11:28 ` Nuno Sá
2024-08-29 12:32 ` [PATCH RFC 5/8] iio: dac: ad3552r: changes to use FIELD_PREP Angelo Dureghello
2024-08-31 11:48 ` Jonathan Cameron
2024-09-02 16:15 ` Angelo Dureghello
2024-09-03 19:19 ` Jonathan Cameron
2024-08-29 12:32 ` [PATCH RFC 6/8] iio: dac: ad3552r: extract common code (no changes in behavior intended) Angelo Dureghello
2024-08-29 12:32 ` [PATCH RFC 7/8] iio: dac: ad3552r: add axi platform driver Angelo Dureghello
2024-08-31 12:13 ` Jonathan Cameron
2024-09-03 8:17 ` Angelo Dureghello
2024-09-03 19:28 ` Jonathan Cameron
2024-08-29 12:32 ` [PATCH RFC 8/8] iio: ABI: add DAC sysfs synchronous_mode parameter Angelo Dureghello
2024-08-31 12:15 ` Jonathan Cameron
2024-08-31 11:38 ` [RFC PATCH 0/8] iio: dac: introducing ad3552r-axi Jonathan Cameron
2024-09-03 8:34 ` Angelo Dureghello
2024-09-03 16:17 ` David Lechner
2024-09-03 19:39 ` Jonathan Cameron
2024-09-05 9:16 ` Nuno Sá
2024-09-07 14:12 ` Jonathan Cameron
2024-09-09 7:37 ` Nuno Sá
2024-09-09 18:59 ` Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).