devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP
@ 2024-09-05 15:17 Angelo Dureghello
  2024-09-05 15:17 ` [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property Angelo Dureghello
                   ` (10 more replies)
  0 siblings, 11 replies; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-05 15:17 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, David Lechner,
	Angelo Dureghello

The serie comes from the previously discussed RFC, that i
converted to a normal patch from this v2.

Purpose is to add ad3552r AXI DAC (fpga-based) support.

The fpga DAC IP has been created to reach the maximum speed
(33MUPS) supported from the ad3552r. To obtain the maximum
transfer rate, the custom module has been implemented using
the QSPI lines in DDR mode, using a dma buffer.

The design is actually using the DAC backend since the register
map is the same of the generic DAC IP, except for some customized
bitfields. For this reason, a new "compatible" has been added
in adi-axi-dac.c.

Also, backend has been extended with all the needed functions
needed for this use case, keeping the names gneric.

Note: the following patch is actually for linux-iio/testing
---
Changes in v2: 
- use unsigned int on bus_reg_read/write
- add a compatible in axi-dac backend for the ad3552r DAC IP
- minor code alignment fixes
- fix a return value not checked
- change devicetree structure setting ad3552r-axi as a backend
  subnode
- add synchronous_mode_available in the ABI doc

Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
Co-developed-by: David Lechner <dlechner@baylibre.com>
Co-developed-by: Nuno Sá <nuno.sa@analog.com>

---
Angelo Dureghello (9):
      dt-bindings: iio: dac: ad3552r: add io-backend property
      iio: backend: extend features
      iio: backend adi-axi-dac: extend features
      iio: backend adi-axi-dac: add registering of child fdt node
      dt-bindings: iio: dac: add ad3552r axi-dac compatible
      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        |  16 +
 .../devicetree/bindings/iio/dac/adi,ad3552r.yaml   |  42 +-
 .../devicetree/bindings/iio/dac/adi,axi-dac.yaml   |   1 +
 drivers/iio/dac/Kconfig                            |  11 +
 drivers/iio/dac/Makefile                           |   3 +-
 drivers/iio/dac/ad3552r-axi.c                      | 567 +++++++++++++++++++++
 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                      | 282 +++++++++-
 drivers/iio/industrialio-backend.c                 | 157 ++++++
 include/linux/iio/backend.h                        |  33 ++
 12 files changed, 1532 insertions(+), 336 deletions(-)
---
base-commit: 8b6f7caca90addc22eb4ae958639048001096003
change-id: 20240905-wip-bl-ad3552r-axi-v0-iio-testing-1ef516b10ef0

Best regards,
-- 

  o/ QW5nZWxvIER1cmVnaGVsbG8=
   www.kernel-space.org
    e: angelo at kernel-space.org
      c: +39 388 8550663
       


^ permalink raw reply	[flat|nested] 63+ messages in thread

* [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-05 15:17 [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP Angelo Dureghello
@ 2024-09-05 15:17 ` Angelo Dureghello
  2024-09-05 16:28   ` Rob Herring (Arm)
  2024-09-08 12:29   ` Jonathan Cameron
  2024-09-05 15:17 ` [PATCH v2 2/9] iio: backend: extend features Angelo Dureghello
                   ` (9 subsequent siblings)
  10 siblings, 2 replies; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-05 15:17 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, David Lechner,
	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   | 42 ++++++++++++++++++++--
 1 file changed, 40 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..a6ce863ca93c 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
@@ -60,12 +60,30 @@ 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 ]
+
 patternProperties:
   "^channel@([0-1])$":
     type: object
@@ -207,8 +225,6 @@ allOf:
 
 required:
   - compatible
-  - reg
-  - spi-max-frequency
 
 additionalProperties: false
 
@@ -238,4 +254,26 @@ examples:
             };
         };
     };
+
+  - |
+    backend: axi_dac@44a70000 {
+        compatible = "adi,axi-dac-ad3552r";
+        reg = <0x44a70000 0x1000>;
+        dmas = <&dac_tx_dma 0>;
+        dma-names = "tx";
+        #io-backend-cells = <0>;
+        clocks = <&ref_clk>;
+        dac {
+            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 = <(-10000000) (10000000)>;
+            };
+        };
+    };
+
 ...

-- 
2.45.0.rc1


^ permalink raw reply related	[flat|nested] 63+ messages in thread

* [PATCH v2 2/9] iio: backend: extend features
  2024-09-05 15:17 [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP Angelo Dureghello
  2024-09-05 15:17 ` [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property Angelo Dureghello
@ 2024-09-05 15:17 ` Angelo Dureghello
  2024-09-08 12:38   ` Jonathan Cameron
  2024-09-05 15:17 ` [PATCH v2 3/9] iio: backend adi-axi-dac: " Angelo Dureghello
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-05 15:17 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, David Lechner,
	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 | 157 +++++++++++++++++++++++++++++++++++++
 include/linux/iio/backend.h        |  33 ++++++++
 2 files changed, 190 insertions(+)

diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
index 20b3b5212da7..231bef4b560e 100644
--- a/drivers/iio/industrialio-backend.c
+++ b/drivers/iio/industrialio-backend.c
@@ -718,6 +718,163 @@ 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 iio buffering
+ * @back: Backend device
+ *
+ * Enabling the buffer, buffer data is processed and sent out from the
+ * bus interface.
+ *
+ * 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_buffer_disable - Disable iio buffering
+ * @back: Backend device
+ *
+ * Disabling the buffer, buffer data transfer on the bus interface
+ * is stopped.
+ *
+ * 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_data_transfer_addr - Set data address.
+ * @back: Backend device
+ * @address: Data register address
+ *
+ * Some devices may need to inform the backend about an address
+ * 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
+ * @data_size: Transfer data 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,
+			     unsigned int *val, size_t data_size)
+{
+	if (!data_size)
+		return -EINVAL;
+
+	return iio_backend_op_call(back, bus_reg_read, reg, val, data_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
+ * @data_size: Transfer data 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,
+			      unsigned int val, size_t data_size)
+{
+	if (!data_size)
+		return -EINVAL;
+
+	return iio_backend_op_call(back, bus_reg_write, reg, val, data_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..eb8c5bb74bb5 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
 };
 
@@ -89,6 +91,15 @@ enum iio_backend_sample_trigger {
  * @read_raw: Read a channel attribute from a backend device
  * @debugfs_print_chan_status: Print channel status into a buffer.
  * @debugfs_reg_access: Read or write register value of backend.
+ * @ext_sync_enable: Enable external synchronization.
+ * @ext_sync_disable: Disable external synchronization.
+ * @ddr_enable: Enable interface DDR (Double Data Rate) mode.
+ * @ddr_disable: Disable interface DDR (Double Data Rate) mode.
+ * @buffer_enable: Enable data buffer.
+ * @buffer_disable: Disable data buffer.
+ * @data_transfer_addr: Set data address.
+ * @bus_reg_read: Read from the interface bus.
+ * @bus_reg_write: Write on the interface bus.
  **/
 struct iio_backend_ops {
 	int (*enable)(struct iio_backend *back);
@@ -129,6 +140,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,
+			    unsigned int *val, size_t data_size);
+	int (*bus_reg_write)(struct iio_backend *back, u32 reg,
+			     unsigned int val, size_t data_size);
 };
 
 /**
@@ -164,6 +186,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,
+			     unsigned int *val, size_t data_size);
+int iio_backend_bus_reg_write(struct iio_backend *back, u32 reg,
+			      unsigned int val, size_t data_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] 63+ messages in thread

* [PATCH v2 3/9] iio: backend adi-axi-dac: extend features
  2024-09-05 15:17 [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP Angelo Dureghello
  2024-09-05 15:17 ` [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property Angelo Dureghello
  2024-09-05 15:17 ` [PATCH v2 2/9] iio: backend: extend features Angelo Dureghello
@ 2024-09-05 15:17 ` Angelo Dureghello
  2024-09-08 15:11   ` Jonathan Cameron
  2024-09-08 15:40   ` Christophe JAILLET
  2024-09-05 15:17 ` [PATCH v2 4/9] iio: backend adi-axi-dac: add registering of child fdt node Angelo Dureghello
                   ` (7 subsequent siblings)
  10 siblings, 2 replies; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-05 15:17 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, David Lechner,
	Angelo Dureghello

From: Angelo Dureghello <adureghello@baylibre.com>

Extend DAC backend with new features required for the AXI driver
version for the ad3552r DAC. Mainly, a new compatible string has
been added to support a DAC IP very similar to the generic DAC IP
but with some customizations to work with the ad3552r.

Then, a serie of generic functions has been added to match with
ad3552r needs. Function names has been kept generic as much as
possible, to allow re-utilization from other frontend drivers.

Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
Co-developed-by: David Lechner <dlechner@baylibre.com>
Co-developed-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/iio/dac/adi-axi-dac.c | 267 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 257 insertions(+), 10 deletions(-)

diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
index 0cb00f3bec04..cc31e1dcd1df 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,25 @@
 #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_DDR_QSPI,
+};
+
+struct axi_dac_info {
+	unsigned int version;
+	int bus_type;
 };
 
 struct axi_dac_state {
@@ -77,6 +114,7 @@ struct axi_dac_state {
 	 * data/variables.
 	 */
 	struct mutex lock;
+	const struct axi_dac_info *info;
 	u64 dac_clk;
 	u32 reg_config;
 	bool int_tone;
@@ -461,6 +499,11 @@ static int axi_dac_data_source_set(struct iio_backend *back, unsigned int chan,
 		return regmap_update_bits(st->regmap,
 					  AXI_DAC_REG_CHAN_CNTRL_7(chan),
 					  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 +561,192 @@ 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,
+				 unsigned int val, size_t data_size)
+{
+	struct axi_dac_state *st = iio_backend_get_priv(back);
+
+	switch (st->info->bus_type) {
+	case AXI_DAC_BUS_TYPE_DDR_QSPI: {
+		int ret;
+		u32 ival;
+
+		if (data_size == 2)
+			ival = FIELD_PREP(AXI_DAC_DATA_WR_16, val);
+		else
+			ival = FIELD_PREP(AXI_DAC_DATA_WR_8, val);
+
+		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 (data_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);
+		}
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int axi_dac_bus_reg_read(struct iio_backend *back, u32 reg,
+				unsigned int *val, size_t data_size)
+{
+	struct axi_dac_state *st = iio_backend_get_priv(back);
+
+	switch (st->info->bus_type) {
+	case AXI_DAC_BUS_TYPE_DDR_QSPI: {
+		int ret;
+		u32 bval;
+
+		bval = 0;
+		ret = axi_dac_bus_reg_write(back, AXI_DAC_RD_ADDR(reg), 0,
+					    data_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);
+		}
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 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 +754,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),
 };
 
@@ -545,8 +781,8 @@ static const struct regmap_config axi_dac_regmap_config = {
 
 static int axi_dac_probe(struct platform_device *pdev)
 {
-	const unsigned int *expected_ver;
 	struct axi_dac_state *st;
+	const struct axi_dac_info *info;
 	void __iomem *base;
 	unsigned int ver;
 	struct clk *clk;
@@ -556,10 +792,12 @@ static int axi_dac_probe(struct platform_device *pdev)
 	if (!st)
 		return -ENOMEM;
 
-	expected_ver = device_get_match_data(&pdev->dev);
-	if (!expected_ver)
+	info = device_get_match_data(&pdev->dev);
+	if (!info)
 		return -ENODEV;
 
+	st->info = info;
+
 	clk = devm_clk_get_enabled(&pdev->dev, NULL);
 	if (IS_ERR(clk))
 		return dev_err_probe(&pdev->dev, PTR_ERR(clk),
@@ -588,12 +826,13 @@ static int axi_dac_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	if (ADI_AXI_PCORE_VER_MAJOR(ver) != ADI_AXI_PCORE_VER_MAJOR(*expected_ver)) {
+	if (ADI_AXI_PCORE_VER_MAJOR(ver) !=
+		ADI_AXI_PCORE_VER_MAJOR(st->info->version)) {
 		dev_err(&pdev->dev,
 			"Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
-			ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
-			ADI_AXI_PCORE_VER_MINOR(*expected_ver),
-			ADI_AXI_PCORE_VER_PATCH(*expected_ver),
+			ADI_AXI_PCORE_VER_MAJOR(st->info->version),
+			ADI_AXI_PCORE_VER_MINOR(st->info->version),
+			ADI_AXI_PCORE_VER_PATCH(st->info->version),
 			ADI_AXI_PCORE_VER_MAJOR(ver),
 			ADI_AXI_PCORE_VER_MINOR(ver),
 			ADI_AXI_PCORE_VER_PATCH(ver));
@@ -631,10 +870,18 @@ static int axi_dac_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static unsigned int axi_dac_9_1_b_info = ADI_AXI_PCORE_VER(9, 1, 'b');
+static const struct axi_dac_info dac_generic = {
+	.version = ADI_AXI_PCORE_VER(9, 1, 'b'),
+};
+
+static const struct axi_dac_info dac_ad3552r = {
+	.version = ADI_AXI_PCORE_VER(9, 1, 'b'),
+	.bus_type = AXI_DAC_BUS_TYPE_DDR_QSPI,
+};
 
 static const struct of_device_id axi_dac_of_match[] = {
-	{ .compatible = "adi,axi-dac-9.1.b", .data = &axi_dac_9_1_b_info },
+	{ .compatible = "adi,axi-dac-9.1.b", .data = &dac_generic },
+	{ .compatible = "adi,axi-dac-ad3552r", .data = &dac_ad3552r },
 	{}
 };
 MODULE_DEVICE_TABLE(of, axi_dac_of_match);

-- 
2.45.0.rc1


^ permalink raw reply related	[flat|nested] 63+ messages in thread

* [PATCH v2 4/9] iio: backend adi-axi-dac: add registering of child fdt node
  2024-09-05 15:17 [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP Angelo Dureghello
                   ` (2 preceding siblings ...)
  2024-09-05 15:17 ` [PATCH v2 3/9] iio: backend adi-axi-dac: " Angelo Dureghello
@ 2024-09-05 15:17 ` Angelo Dureghello
  2024-09-05 19:19   ` David Lechner
  2024-09-05 15:17 ` [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible Angelo Dureghello
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-05 15:17 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, David Lechner,
	Angelo Dureghello

From: Angelo Dureghello <adureghello@baylibre.com>

Change to obtain the fdt use case as reported in the
adi,ad3552r.yaml file in this patchset, with the DAC device that
is actually using the backend set as a child node of the backend.

To obtain this, registering all the child fdt nodes as platform
devices.

Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
Co-developed-by: David Lechner <dlechner@baylibre.com>
Co-developed-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/iio/dac/adi-axi-dac.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
index cc31e1dcd1df..e883cd557b6a 100644
--- a/drivers/iio/dac/adi-axi-dac.c
+++ b/drivers/iio/dac/adi-axi-dac.c
@@ -783,6 +783,7 @@ static int axi_dac_probe(struct platform_device *pdev)
 {
 	struct axi_dac_state *st;
 	const struct axi_dac_info *info;
+	struct platform_device *child_pdev;
 	void __iomem *base;
 	unsigned int ver;
 	struct clk *clk;
@@ -862,6 +863,20 @@ static int axi_dac_probe(struct platform_device *pdev)
 		return dev_err_probe(&pdev->dev, ret,
 				     "failed to register iio backend\n");
 
+	device_for_each_child_node_scoped(&pdev->dev, child) {
+		struct platform_device_info pi;
+
+		memset(&pi, 0, sizeof(pi));
+
+		pi.name = fwnode_get_name(child);
+		pi.id = PLATFORM_DEVID_AUTO;
+		pi.fwnode = child;
+
+		child_pdev = platform_device_register_full(&pi);
+		if (IS_ERR(child_pdev))
+			return PTR_ERR(child_pdev);
+	}
+
 	dev_info(&pdev->dev, "AXI DAC IP core (%d.%.2d.%c) probed\n",
 		 ADI_AXI_PCORE_VER_MAJOR(ver),
 		 ADI_AXI_PCORE_VER_MINOR(ver),

-- 
2.45.0.rc1


^ permalink raw reply related	[flat|nested] 63+ messages in thread

* [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-05 15:17 [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP Angelo Dureghello
                   ` (3 preceding siblings ...)
  2024-09-05 15:17 ` [PATCH v2 4/9] iio: backend adi-axi-dac: add registering of child fdt node Angelo Dureghello
@ 2024-09-05 15:17 ` Angelo Dureghello
  2024-09-05 16:28   ` Rob Herring (Arm)
                     ` (2 more replies)
  2024-09-05 15:17 ` [PATCH v2 6/9] iio: dac: ad3552r: changes to use FIELD_PREP Angelo Dureghello
                   ` (5 subsequent siblings)
  10 siblings, 3 replies; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-05 15:17 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, David Lechner,
	Angelo Dureghello

From: Angelo Dureghello <adureghello@baylibre.com>

Add a new compatible for the ad3552r variant of the generic DAC IP.

The ad3552r DAC IP variant is very similar to the generic DAC IP,
register map is the same, but some register fields are specific to
this IP, and also, a DDR QSPI bus has been included in the IP.

Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
---
 Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
index a55e9bfc66d7..c0cccb7a99a4 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
@@ -24,6 +24,7 @@ properties:
   compatible:
     enum:
       - adi,axi-dac-9.1.b
+      - adi,axi-dac-ad3552r
 
   reg:
     maxItems: 1

-- 
2.45.0.rc1


^ permalink raw reply related	[flat|nested] 63+ messages in thread

* [PATCH v2 6/9] iio: dac: ad3552r: changes to use FIELD_PREP
  2024-09-05 15:17 [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP Angelo Dureghello
                   ` (4 preceding siblings ...)
  2024-09-05 15:17 ` [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible Angelo Dureghello
@ 2024-09-05 15:17 ` Angelo Dureghello
  2024-09-05 20:59   ` David Lechner
  2024-09-08 15:14   ` Jonathan Cameron
  2024-09-05 15:17 ` [PATCH v2 7/9] iio: dac: ad3552r: extract common code (no changes in behavior intended) Angelo Dureghello
                   ` (4 subsequent siblings)
  10 siblings, 2 replies; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-05 15:17 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, David Lechner,
	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 removed 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] 63+ messages in thread

* [PATCH v2 7/9] iio: dac: ad3552r: extract common code (no changes in behavior intended)
  2024-09-05 15:17 [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP Angelo Dureghello
                   ` (5 preceding siblings ...)
  2024-09-05 15:17 ` [PATCH v2 6/9] iio: dac: ad3552r: changes to use FIELD_PREP Angelo Dureghello
@ 2024-09-05 15:17 ` Angelo Dureghello
  2024-09-08 15:42   ` Jonathan Cameron
  2024-09-08 15:53   ` Christophe JAILLET
  2024-09-05 15:17 ` [PATCH v2 8/9] iio: dac: ad3552r: add axi platform driver Angelo Dureghello
                   ` (3 subsequent siblings)
  10 siblings, 2 replies; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-05 15:17 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, David Lechner,
	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);
 
-	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] 63+ messages in thread

* [PATCH v2 8/9] iio: dac: ad3552r: add axi platform driver
  2024-09-05 15:17 [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP Angelo Dureghello
                   ` (6 preceding siblings ...)
  2024-09-05 15:17 ` [PATCH v2 7/9] iio: dac: ad3552r: extract common code (no changes in behavior intended) Angelo Dureghello
@ 2024-09-05 15:17 ` Angelo Dureghello
  2024-09-05 20:40   ` David Lechner
                     ` (2 more replies)
  2024-09-05 15:17 ` [PATCH v2 9/9] iio: ABI: add DAC sysfs synchronous_mode parameter Angelo Dureghello
                   ` (2 subsequent siblings)
  10 siblings, 3 replies; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-05 15:17 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, David Lechner,
	Angelo Dureghello

From: Angelo Dureghello <adureghello@baylibre.com>

Add support for ad3552r-axi, where ad3552r has to be controlled
by the custom (fpga-based) ad3552r AXI DAC IP.

Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
Co-developed-by: David Lechner <dlechner@baylibre.com>
Co-developed-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/iio/dac/Kconfig       |  11 +
 drivers/iio/dac/Makefile      |   1 +
 drivers/iio/dac/ad3552r-axi.c | 567 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 579 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..a9311f29f45d
--- /dev/null
+++ b/drivers/iio/dac/ad3552r-axi.c
@@ -0,0 +1,567 @@
+// 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/backend.h>
+#include <linux/iio/buffer.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/units.h>
+
+#include "ad3552r.h"
+
+enum ad3552r_synchronous_mode_status {
+	AD3552R_NO_SYNC,
+	AD3552R_EXT_SYNC_ARM,
+};
+
+struct ad3552r_axi_model_data {
+	const char *model_name;
+	enum ad3552r_id chip_id;
+	unsigned int num_hw_channels;
+};
+
+struct ad3552r_axi_state {
+	const struct ad3552r_axi_model_data *model_data;
+	struct gpio_desc *reset_gpio;
+	struct device *dev;
+	struct iio_backend *back;
+	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_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 (*indio_dev->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;
+
+	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 (ext synch ability) is enabled 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_sync;
+
+	err = iio_backend_buffer_enable(st->back);
+	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 SDR 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;
+
+	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;
+	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;
+
+	err = iio_backend_bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+					AD3552R_SCRATCH_PAD_TEST_VAL1, 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;
+	}
+
+	err = iio_backend_bus_reg_write(st->back,
+					AD3552R_REG_ADDR_SCRATCH_PAD,
+					AD3552R_SCRATCH_PAD_TEST_VAL2, 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;
+
+	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 != st->model_data->chip_id) {
+		dev_err(st->dev, "Chip ID mismatch. Expected 0x%x, Read 0x%x\n",
+			AD3552R_ID, id);
+	}
+
+	err = iio_backend_bus_reg_write(st->back,
+					AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
+					AD3552R_REF_INIT, 1);
+	if (err)
+		return err;
+
+	err = iio_backend_bus_reg_write(st->back,
+					AD3552R_REG_ADDR_TRANSFER_REGISTER,
+					AD3552R_TRANSFER_INIT, 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->model_data->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, &reg);
+
+	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),
+					reg, 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),
+					reg, 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 = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+	.output = 1, \
+	.indexed = 1, \
+	.channel = (ch), \
+	.scan_index = (ch), \
+	.scan_type = { \
+		.sign = 'u', \
+		.realbits = 16, \
+		.storagebits = 16, \
+		.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,
+};
+
+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;
+
+	st->model_data = device_get_match_data(&pdev->dev);
+
+	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 ad3552r_axi_model_data ad3552r_model_data = {
+	.model_name = "ad3552r",
+	.chip_id = AD3552R_ID,
+	.num_hw_channels = 2,
+};
+
+static const struct of_device_id ad3552r_axi_of_id[] = {
+	{ .compatible = "adi,ad3552r", .data = &ad3552r_model_data },
+	{ }
+};
+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] 63+ messages in thread

* [PATCH v2 9/9] iio: ABI: add DAC sysfs synchronous_mode parameter
  2024-09-05 15:17 [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP Angelo Dureghello
                   ` (7 preceding siblings ...)
  2024-09-05 15:17 ` [PATCH v2 8/9] iio: dac: ad3552r: add axi platform driver Angelo Dureghello
@ 2024-09-05 15:17 ` Angelo Dureghello
  2024-09-05 19:14   ` David Lechner
  2024-09-05 19:46 ` [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP David Lechner
  2024-09-06  9:07 ` Conor Dooley
  10 siblings, 1 reply; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-05 15:17 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, David Lechner,
	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 | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-bus-iio-dac b/Documentation/ABI/testing/sysfs-bus-iio-dac
index 810eaac5533c..2f4960c79385 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio-dac
+++ b/Documentation/ABI/testing/sysfs-bus-iio-dac
@@ -59,3 +59,19 @@ 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:
+		Arm or disarm a wait-for-synchronization flag. Arming this flag
+		means the DAC will wait for a synchronizatiopn signal on a
+		specific internal or external wired connection. I.e., there are
+		cases where multiple DACs IP are built in the same chip or fpga
+		design, and they need to start the data stream synchronized.
+
+What:		/sys/bus/iio/devices/iio:deviceX/out_voltage_synchronous_mode_available
+KernelVersion:	6.13
+Contact:	linux-iio@vger.kernel.org
+Description:
+		List of available values for synchronous_mode.

-- 
2.45.0.rc1


^ permalink raw reply related	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-05 15:17 ` [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property Angelo Dureghello
@ 2024-09-05 16:28   ` Rob Herring (Arm)
  2024-09-05 19:51     ` David Lechner
  2024-09-08 12:29   ` Jonathan Cameron
  1 sibling, 1 reply; 63+ messages in thread
From: Rob Herring (Arm) @ 2024-09-05 16:28 UTC (permalink / raw)
  To: Angelo Dureghello
  Cc: Lars-Peter Clausen, linux-iio, Jonathan Cameron,
	Krzysztof Kozlowski, Nuno Sá, linux-kernel,
	Michael Hennerich, Olivier Moysan, devicetree, David Lechner,
	Conor Dooley


On Thu, 05 Sep 2024 17:17:31 +0200, Angelo Dureghello wrote:
> 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   | 42 ++++++++++++++++++++--
>  1 file changed, 40 insertions(+), 2 deletions(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/iio/dac/adi,ad3552r.example.dtb: /example-1/axi_dac@44a70000: failed to match any schema with compatible: ['adi,axi-dac-ad3552r']

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240905-wip-bl-ad3552r-axi-v0-iio-testing-v2-1-87d669674c00@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] 63+ messages in thread

* Re: [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-05 15:17 ` [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible Angelo Dureghello
@ 2024-09-05 16:28   ` Rob Herring (Arm)
  2024-09-05 21:08   ` David Lechner
  2024-09-06  7:22   ` Krzysztof Kozlowski
  2 siblings, 0 replies; 63+ messages in thread
From: Rob Herring (Arm) @ 2024-09-05 16:28 UTC (permalink / raw)
  To: Angelo Dureghello
  Cc: Jonathan Cameron, devicetree, Krzysztof Kozlowski, Olivier Moysan,
	linux-iio, David Lechner, Lars-Peter Clausen, Conor Dooley,
	Michael Hennerich, Nuno Sá, linux-kernel


On Thu, 05 Sep 2024 17:17:35 +0200, Angelo Dureghello wrote:
> From: Angelo Dureghello <adureghello@baylibre.com>
> 
> Add a new compatible for the ad3552r variant of the generic DAC IP.
> 
> The ad3552r DAC IP variant is very similar to the generic DAC IP,
> register map is the same, but some register fields are specific to
> this IP, and also, a DDR QSPI bus has been included in the IP.
> 
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> ---
>  Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

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,ad3552r.example.dtb: axi_dac@44a70000: 'dac' does not match any of the regexes: 'pinctrl-[0-9]+'
	from schema $id: http://devicetree.org/schemas/iio/dac/adi,axi-dac.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240905-wip-bl-ad3552r-axi-v0-iio-testing-v2-5-87d669674c00@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] 63+ messages in thread

* Re: [PATCH v2 9/9] iio: ABI: add DAC sysfs synchronous_mode parameter
  2024-09-05 15:17 ` [PATCH v2 9/9] iio: ABI: add DAC sysfs synchronous_mode parameter Angelo Dureghello
@ 2024-09-05 19:14   ` David Lechner
  2024-09-08 12:26     ` Jonathan Cameron
  0 siblings, 1 reply; 63+ messages in thread
From: David Lechner @ 2024-09-05 19:14 UTC (permalink / raw)
  To: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
	Nuno Sá, Jonathan Cameron, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Olivier Moysan
  Cc: linux-iio, devicetree, linux-kernel

On 9/5/24 10:17 AM, Angelo Dureghello 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 | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-dac b/Documentation/ABI/testing/sysfs-bus-iio-dac
> index 810eaac5533c..2f4960c79385 100644
> --- a/Documentation/ABI/testing/sysfs-bus-iio-dac
> +++ b/Documentation/ABI/testing/sysfs-bus-iio-dac
> @@ -59,3 +59,19 @@ 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:
> +		Arm or disarm a wait-for-synchronization flag. Arming this flag
> +		means the DAC will wait for a synchronizatiopn signal on a
> +		specific internal or external wired connection. I.e., there are
> +		cases where multiple DACs IP are built in the same chip or fpga
> +		design, and they need to start the data stream synchronized.
> +
> +What:		/sys/bus/iio/devices/iio:deviceX/out_voltage_synchronous_mode_available
> +KernelVersion:	6.13
> +Contact:	linux-iio@vger.kernel.org
> +Description:
> +		List of available values for synchronous_mode.
> 

Since this depends on how things are wired, it seems like this should be
something specified in the devicetree, not through sysfs attributes.


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 4/9] iio: backend adi-axi-dac: add registering of child fdt node
  2024-09-05 15:17 ` [PATCH v2 4/9] iio: backend adi-axi-dac: add registering of child fdt node Angelo Dureghello
@ 2024-09-05 19:19   ` David Lechner
  2024-09-06  5:42     ` Nuno Sá
  2024-09-06  7:08     ` Nuno Sá
  0 siblings, 2 replies; 63+ messages in thread
From: David Lechner @ 2024-09-05 19:19 UTC (permalink / raw)
  To: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
	Nuno Sá, Jonathan Cameron, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Olivier Moysan
  Cc: linux-iio, devicetree, linux-kernel

On 9/5/24 10:17 AM, Angelo Dureghello wrote:
> From: Angelo Dureghello <adureghello@baylibre.com>
> 
> Change to obtain the fdt use case as reported in the
> adi,ad3552r.yaml file in this patchset, with the DAC device that
> is actually using the backend set as a child node of the backend.
> 
> To obtain this, registering all the child fdt nodes as platform
> devices.
> 
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> Co-developed-by: David Lechner <dlechner@baylibre.com>
> Co-developed-by: Nuno Sá <nuno.sa@analog.com>
> ---
>  drivers/iio/dac/adi-axi-dac.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
> index cc31e1dcd1df..e883cd557b6a 100644
> --- a/drivers/iio/dac/adi-axi-dac.c
> +++ b/drivers/iio/dac/adi-axi-dac.c
> @@ -783,6 +783,7 @@ static int axi_dac_probe(struct platform_device *pdev)
>  {
>  	struct axi_dac_state *st;
>  	const struct axi_dac_info *info;
> +	struct platform_device *child_pdev;
>  	void __iomem *base;
>  	unsigned int ver;
>  	struct clk *clk;
> @@ -862,6 +863,20 @@ static int axi_dac_probe(struct platform_device *pdev)
>  		return dev_err_probe(&pdev->dev, ret,
>  				     "failed to register iio backend\n");
>  
> +	device_for_each_child_node_scoped(&pdev->dev, child) {

This should use fwnode_for_each_available_child_node() so that it skips
nodes with status != "okay".

Would be nice to introduce a scoped version of this function too.

Also, if we are allowing multiple devices on the bus, the DT bindings
need to have a reg property that is unique for each child.

> +		struct platform_device_info pi;
> +
> +		memset(&pi, 0, sizeof(pi));

struct platform_device_info pi = { };

avoids the need for memset().

> +
> +		pi.name = fwnode_get_name(child);
> +		pi.id = PLATFORM_DEVID_AUTO;
> +		pi.fwnode = child;

Need to have pi.parent = &pdev->dev;

It could also make sense to have all of the primary bus functions
(reg read/write, ddr enable/disable, etc.) passed here as platform
data instead of having everything go through the IIO backend.

> +
> +		child_pdev = platform_device_register_full(&pi);
> +		if (IS_ERR(child_pdev))
> +			return PTR_ERR(child_pdev);

These devices need to be unregistered on any error return and when
the parent device is removed.

> +	}
> +
>  	dev_info(&pdev->dev, "AXI DAC IP core (%d.%.2d.%c) probed\n",
>  		 ADI_AXI_PCORE_VER_MAJOR(ver),
>  		 ADI_AXI_PCORE_VER_MINOR(ver),
> 


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP
  2024-09-05 15:17 [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP Angelo Dureghello
                   ` (8 preceding siblings ...)
  2024-09-05 15:17 ` [PATCH v2 9/9] iio: ABI: add DAC sysfs synchronous_mode parameter Angelo Dureghello
@ 2024-09-05 19:46 ` David Lechner
  2024-09-06  9:07 ` Conor Dooley
  10 siblings, 0 replies; 63+ messages in thread
From: David Lechner @ 2024-09-05 19:46 UTC (permalink / raw)
  To: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
	Nuno Sá, Jonathan Cameron, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Olivier Moysan
  Cc: linux-iio, devicetree, linux-kernel

On 9/5/24 10:17 AM, Angelo Dureghello wrote:
> The serie comes from the previously discussed RFC, that i
> converted to a normal patch from this v2.
> 
> Purpose is to add ad3552r AXI DAC (fpga-based) support.
> 
> The fpga DAC IP has been created to reach the maximum speed
> (33MUPS) supported from the ad3552r. To obtain the maximum
> transfer rate, the custom module has been implemented using
> the QSPI lines in DDR mode, using a dma buffer.
> 
> The design is actually using the DAC backend since the register
> map is the same of the generic DAC IP, except for some customized
> bitfields. For this reason, a new "compatible" has been added
> in adi-axi-dac.c.
> 
> Also, backend has been extended with all the needed functions
> needed for this use case, keeping the names gneric.
> 
> Note: the following patch is actually for linux-iio/testing
> ---
> Changes in v2: 
> - use unsigned int on bus_reg_read/write
> - add a compatible in axi-dac backend for the ad3552r DAC IP
> - minor code alignment fixes
> - fix a return value not checked
> - change devicetree structure setting ad3552r-axi as a backend
>   subnode
> - add synchronous_mode_available in the ABI doc
> 
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> Co-developed-by: David Lechner <dlechner@baylibre.com>
> Co-developed-by: Nuno Sá <nuno.sa@analog.com>
> 
We didn't actually write any of the code, so I don't think
Co-developed-by: is the right way to give us credit. But we
can give our Reviewed-by: tags when this is ready to be merged.


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-05 16:28   ` Rob Herring (Arm)
@ 2024-09-05 19:51     ` David Lechner
  0 siblings, 0 replies; 63+ messages in thread
From: David Lechner @ 2024-09-05 19:51 UTC (permalink / raw)
  To: Rob Herring (Arm), Angelo Dureghello
  Cc: Lars-Peter Clausen, linux-iio, Jonathan Cameron,
	Krzysztof Kozlowski, Nuno Sá, linux-kernel,
	Michael Hennerich, Olivier Moysan, devicetree, Conor Dooley

On 9/5/24 11:28 AM, Rob Herring (Arm) wrote:
> 
> On Thu, 05 Sep 2024 17:17:31 +0200, Angelo Dureghello wrote:
>> 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   | 42 ++++++++++++++++++++--
>>  1 file changed, 40 insertions(+), 2 deletions(-)
>>
> 
> My bot found errors running 'make dt_binding_check' on your patch:
> 
> yamllint warnings/errors:
> 
> dtschema/dtc warnings/errors:
> Documentation/devicetree/bindings/iio/dac/adi,ad3552r.example.dtb: /example-1/axi_dac@44a70000: failed to match any schema with compatible: ['adi,axi-dac-ad3552r']


I think this can be fixed by putting commit "dt-bindings: iio: dac: add ad3552r axi-dac compatible"
first in the series before commit "dt-bindings: iio: dac: ad3552r: add io-backend property".

> 
> doc reference errors (make refcheckdocs):
> 
> See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240905-wip-bl-ad3552r-axi-v0-iio-testing-v2-1-87d669674c00@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] 63+ messages in thread

* Re: [PATCH v2 8/9] iio: dac: ad3552r: add axi platform driver
  2024-09-05 15:17 ` [PATCH v2 8/9] iio: dac: ad3552r: add axi platform driver Angelo Dureghello
@ 2024-09-05 20:40   ` David Lechner
  2024-09-08 15:49     ` Jonathan Cameron
  2024-09-09  9:00     ` Nuno Sá
  2024-09-08 16:07   ` Jonathan Cameron
  2024-09-08 16:28   ` Christophe JAILLET
  2 siblings, 2 replies; 63+ messages in thread
From: David Lechner @ 2024-09-05 20:40 UTC (permalink / raw)
  To: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
	Nuno Sá, Jonathan Cameron, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Olivier Moysan
  Cc: linux-iio, devicetree, linux-kernel

On 9/5/24 10:17 AM, Angelo Dureghello wrote:

...

> +
> +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);

This seems odd to me. How does the backend know what frequency we want?
It would make more sense to me if this somehow indicated that we were
getting the SPI SCLK rate.

> +		if (err != IIO_VAL_INT)

Would be better to call the variable ret instead of err if it can hold
something besides an error code.

> +			return err;
> +
> +		/*
> +		 * Data stream SDR/DDR (clk_in/8 or clk_in/4 update rate).
> +		 * Samplerate has sense in DDR only.

We should also mention that this assumes QSPI in addtion to DDR enabled.

> +		 */
> +		if (st->single_channel)
> +			clk_rate = DIV_ROUND_CLOSEST(clk_rate, 4);
> +		else
> +			clk_rate = DIV_ROUND_CLOSEST(clk_rate, 8);
> +

Having the sample rate depend on how many channels are enabled in
the buffer seems a bit odd. Sampling frequency is not strictly
defined in IIO, so I think it would be fine to always return the
same value no matter how many channels are enabled.

We will just need to document that the sampling frequency is the
rate per sample, not per channel. So if two channels are enabled,
the effective sampling rate per channel is 1/2 of the sampling
rate reported by the sysfs attribute. 

> +		*val = clk_rate;
> +
> +		return IIO_VAL_INT;
> +	}
> +	case IIO_CHAN_INFO_RAW:

Do we need iio_device_claim_direct_scoped() here to prevent attempting
to do register access while a buffered write is in progress?

> +		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_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;

Might want a comment or dev_warn() here. If we put the DAC in DDR
mode but can't put the backend in DDR mode, then things are probably
going to be a bit broken if we can't get the DAC back out of DDR
mode. Not likely to ever get an error here, but it will be helpful
to let readers of the code know why the unwinding isn't exactly
balanced.

> +> +	switch (*indio_dev->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;

Move the switch statement before changing to DDR mode or
goto exit_err here.

> +	}
> +
> +	err = iio_backend_bus_reg_write(st->back, AD3552R_REG_ADDR_STREAM_MODE,
> +					loop_len, 1);
> +	if (err)
> +		goto exit_err;
> +
> +	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 (ext synch ability) is enabled anyway.

EXT_SYNC

> +	 */
> +	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;

		goto exit_err;

If enabling failed, no need to disable.

> +
> +	err = iio_backend_data_format_set(st->back, 0, &fmt);
> +	if (err)
> +		goto exit_err_sync;
> +
> +	err = iio_backend_buffer_enable(st->back);
> +	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;

Looks like iio_backend_ext_sync_disable(st->back); should be called here.

> +
> +	/* Inform DAC to set in SDR 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);
> +}
> +

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 6/9] iio: dac: ad3552r: changes to use FIELD_PREP
  2024-09-05 15:17 ` [PATCH v2 6/9] iio: dac: ad3552r: changes to use FIELD_PREP Angelo Dureghello
@ 2024-09-05 20:59   ` David Lechner
  2024-09-08 15:14   ` Jonathan Cameron
  1 sibling, 0 replies; 63+ messages in thread
From: David Lechner @ 2024-09-05 20:59 UTC (permalink / raw)
  To: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
	Nuno Sá, Jonathan Cameron, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Olivier Moysan
  Cc: linux-iio, devicetree, linux-kernel

On 9/5/24 10:17 AM, Angelo Dureghello 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 removed too.
> 
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> ---
Can we also remove enum ad3552r_dev_attributes and enum ad3552r_ch_attributes?
It looks like they aren't used any more after these changes.


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-05 15:17 ` [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible Angelo Dureghello
  2024-09-05 16:28   ` Rob Herring (Arm)
@ 2024-09-05 21:08   ` David Lechner
  2024-09-06  7:22   ` Krzysztof Kozlowski
  2 siblings, 0 replies; 63+ messages in thread
From: David Lechner @ 2024-09-05 21:08 UTC (permalink / raw)
  To: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
	Nuno Sá, Jonathan Cameron, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Olivier Moysan
  Cc: linux-iio, devicetree, linux-kernel

On 9/5/24 10:17 AM, Angelo Dureghello wrote:
> From: Angelo Dureghello <adureghello@baylibre.com>
> 
> Add a new compatible for the ad3552r variant of the generic DAC IP.
> 
> The ad3552r DAC IP variant is very similar to the generic DAC IP,
> register map is the same, but some register fields are specific to
> this IP, and also, a DDR QSPI bus has been included in the IP.
> 
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> ---
>  Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> index a55e9bfc66d7..c0cccb7a99a4 100644
> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> @@ -24,6 +24,7 @@ properties:
>    compatible:
>      enum:
>        - adi,axi-dac-9.1.b
> +      - adi,axi-dac-ad3552r
>  
>    reg:
>      maxItems: 1
> 

I think we will also need more for child nodes:

patternProperties:
  "^dac@[0-9a-f]+$":
    type: object
    additionalProperties: true

    reg:
      # add more rules for reg here

    required:
      - compatible
      - reg

allOf:
  - if:
      not:
        properties:
          compatible:
            contains:
              - adi,axi-dac-ad3552r
    then:
      patternProperties:
        "^dac@[0-9a-f]+$": false

---

Or use existing SPI bindings.

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 4/9] iio: backend adi-axi-dac: add registering of child fdt node
  2024-09-05 19:19   ` David Lechner
@ 2024-09-06  5:42     ` Nuno Sá
  2024-09-06 13:52       ` David Lechner
  2024-09-06  7:08     ` Nuno Sá
  1 sibling, 1 reply; 63+ messages in thread
From: Nuno Sá @ 2024-09-06  5:42 UTC (permalink / raw)
  To: David Lechner, Angelo Dureghello, Lars-Peter Clausen,
	Michael Hennerich, Nuno Sá, Jonathan Cameron, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Olivier Moysan
  Cc: linux-iio, devicetree, linux-kernel

On Thu, 2024-09-05 at 14:19 -0500, David Lechner wrote:
> On 9/5/24 10:17 AM, Angelo Dureghello wrote:
> > From: Angelo Dureghello <adureghello@baylibre.com>
> > 
> > Change to obtain the fdt use case as reported in the
> > adi,ad3552r.yaml file in this patchset, with the DAC device that
> > is actually using the backend set as a child node of the backend.
> > 
> > To obtain this, registering all the child fdt nodes as platform
> > devices.
> > 
> > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > Co-developed-by: David Lechner <dlechner@baylibre.com>
> > Co-developed-by: Nuno Sá <nuno.sa@analog.com>
> > ---
> >  drivers/iio/dac/adi-axi-dac.c | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> > 
> > diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
> > index cc31e1dcd1df..e883cd557b6a 100644
> > --- a/drivers/iio/dac/adi-axi-dac.c
> > +++ b/drivers/iio/dac/adi-axi-dac.c
> > @@ -783,6 +783,7 @@ static int axi_dac_probe(struct platform_device *pdev)
> >  {
> >  	struct axi_dac_state *st;
> >  	const struct axi_dac_info *info;
> > +	struct platform_device *child_pdev;
> >  	void __iomem *base;
> >  	unsigned int ver;
> >  	struct clk *clk;
> > @@ -862,6 +863,20 @@ static int axi_dac_probe(struct platform_device *pdev)
> >  		return dev_err_probe(&pdev->dev, ret,
> >  				     "failed to register iio backend\n");
> >  
> > +	device_for_each_child_node_scoped(&pdev->dev, child) {
> 
> This should use fwnode_for_each_available_child_node() so that it skips
> nodes with status != "okay".
> 

device_for_each_child_node() already only looks at available nodes IIRC

- Nuno Sá


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 4/9] iio: backend adi-axi-dac: add registering of child fdt node
  2024-09-05 19:19   ` David Lechner
  2024-09-06  5:42     ` Nuno Sá
@ 2024-09-06  7:08     ` Nuno Sá
  2024-09-08 12:36       ` Jonathan Cameron
  1 sibling, 1 reply; 63+ messages in thread
From: Nuno Sá @ 2024-09-06  7:08 UTC (permalink / raw)
  To: David Lechner, Angelo Dureghello, Lars-Peter Clausen,
	Michael Hennerich, Nuno Sá, Jonathan Cameron, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Olivier Moysan
  Cc: linux-iio, devicetree, linux-kernel

On Thu, 2024-09-05 at 14:19 -0500, David Lechner wrote:
> On 9/5/24 10:17 AM, Angelo Dureghello wrote:
> > From: Angelo Dureghello <adureghello@baylibre.com>
> > 
> > Change to obtain the fdt use case as reported in the
> > adi,ad3552r.yaml file in this patchset, with the DAC device that
> > is actually using the backend set as a child node of the backend.
> > 
> > To obtain this, registering all the child fdt nodes as platform
> > devices.
> > 
> > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > Co-developed-by: David Lechner <dlechner@baylibre.com>
> > Co-developed-by: Nuno Sá <nuno.sa@analog.com>
> > ---
> >  drivers/iio/dac/adi-axi-dac.c | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> > 
> > diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
> > index cc31e1dcd1df..e883cd557b6a 100644
> > --- a/drivers/iio/dac/adi-axi-dac.c
> > +++ b/drivers/iio/dac/adi-axi-dac.c
> > @@ -783,6 +783,7 @@ static int axi_dac_probe(struct platform_device *pdev)
> >  {
> >  	struct axi_dac_state *st;
> >  	const struct axi_dac_info *info;
> > +	struct platform_device *child_pdev;
> >  	void __iomem *base;
> >  	unsigned int ver;
> >  	struct clk *clk;
> > @@ -862,6 +863,20 @@ static int axi_dac_probe(struct platform_device *pdev)
> >  		return dev_err_probe(&pdev->dev, ret,
> >  				     "failed to register iio backend\n");
> >  
> > +	device_for_each_child_node_scoped(&pdev->dev, child) {
> 
> This should use fwnode_for_each_available_child_node() so that it skips
> nodes with status != "okay".
> 
> Would be nice to introduce a scoped version of this function too.
> 
> Also, if we are allowing multiple devices on the bus, the DT bindings
> need to have a reg property that is unique for each child.
> 
> > +		struct platform_device_info pi;
> > +
> > +		memset(&pi, 0, sizeof(pi));
> 
> struct platform_device_info pi = { };
> 
> avoids the need for memset().
> 
> > +
> > +		pi.name = fwnode_get_name(child);
> > +		pi.id = PLATFORM_DEVID_AUTO;
> > +		pi.fwnode = child;
> 
> Need to have pi.parent = &pdev->dev;
> 
> It could also make sense to have all of the primary bus functions
> (reg read/write, ddr enable/disable, etc.) passed here as platform
> data instead of having everything go through the IIO backend.

Note that ddr enable/disable is something that makes sense to be in the backend
anyways as it is something that exists in LVDS/CMOS interfaces that are only running
the dataplane. Bus operations like read/write could make sense but that would mean an
interface directly between the axi-dac and the child devices (bypassing the backend
or any other middle layer - maybe we could create a tiny adi-axi-bus layer on the IIO
topdir or any other place in IIO) which I'm not so sure (and is a bit odd). OTOH,
this bus stuff goes a bit out of scope of the backend main idea/goal so yeah... Well,
let's see what others have to say about it but I don't dislike the idea.

> 
> > +
> > +		child_pdev = platform_device_register_full(&pi);
> > +		if (IS_ERR(child_pdev))
> > +			return PTR_ERR(child_pdev);
> 
> These devices need to be unregistered on any error return and when
> the parent device is removed.
> 

Definitely this needs to be tested by manually unbinding the axi-dac device for
example. I'm not really sure how this will look like and if there's any problem in
removing twice the same device (likely there is). The thing is that when we connect a
frontend with it's backend, a devlink is created (that guarantees that the frontend
is removed before the backend). So, I'm fairly confident that if we add a devm action
in here to unregister the child devices, by the time we unregister the child, it
should be already gone (unless driver core somehow handles this).

All of the above needs careful testing but one way out it (and since in here we have
the parent - child relationship), we could add a boolean flag 'skip_devlink' to
'struct iio_backend_info' so that devlinks are skipped on these arrangements. Or we
could automatically detect that the frontend is a child of the backend and skip the
link (though an explicit flag might be better).

- Nuno Sá

> 

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-05 15:17 ` [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible Angelo Dureghello
  2024-09-05 16:28   ` Rob Herring (Arm)
  2024-09-05 21:08   ` David Lechner
@ 2024-09-06  7:22   ` Krzysztof Kozlowski
  2024-09-06  9:11     ` Angelo Dureghello
  2 siblings, 1 reply; 63+ messages in thread
From: Krzysztof Kozlowski @ 2024-09-06  7:22 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,
	David Lechner

On Thu, Sep 05, 2024 at 05:17:35PM +0200, Angelo Dureghello wrote:
> From: Angelo Dureghello <adureghello@baylibre.com>
> 
> Add a new compatible for the ad3552r variant of the generic DAC IP.
> 
> The ad3552r DAC IP variant is very similar to the generic DAC IP,
> register map is the same, but some register fields are specific to
> this IP, and also, a DDR QSPI bus has been included in the IP.
> 
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> ---
>  Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> index a55e9bfc66d7..c0cccb7a99a4 100644
> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> @@ -24,6 +24,7 @@ properties:
>    compatible:
>      enum:
>        - adi,axi-dac-9.1.b
> +      - adi,axi-dac-ad3552r

I am sorry, but what is the product here? It looks like either wrong
order or even completely redundant. What is ad3552r?

And why versions are mixed with real products but without any
compatibility. What does the version express in such case?

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP
  2024-09-05 15:17 [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP Angelo Dureghello
                   ` (9 preceding siblings ...)
  2024-09-05 19:46 ` [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP David Lechner
@ 2024-09-06  9:07 ` Conor Dooley
  2024-09-06  9:44   ` Angelo Dureghello
  10 siblings, 1 reply; 63+ messages in thread
From: Conor Dooley @ 2024-09-06  9:07 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,
	David Lechner

[-- Attachment #1: Type: text/plain, Size: 1438 bytes --]

On Thu, Sep 05, 2024 at 05:17:30PM +0200, Angelo Dureghello wrote:
> The serie comes from the previously discussed RFC, that i
> converted to a normal patch from this v2.
> 
> Purpose is to add ad3552r AXI DAC (fpga-based) support.
> 
> The fpga DAC IP has been created to reach the maximum speed
> (33MUPS) supported from the ad3552r. To obtain the maximum
> transfer rate, the custom module has been implemented using
> the QSPI lines in DDR mode, using a dma buffer.
> 
> The design is actually using the DAC backend since the register
> map is the same of the generic DAC IP, except for some customized
> bitfields. For this reason, a new "compatible" has been added
> in adi-axi-dac.c.
> 
> Also, backend has been extended with all the needed functions
> needed for this use case, keeping the names gneric.
> 
> Note: the following patch is actually for linux-iio/testing
> ---
> Changes in v2: 
> - use unsigned int on bus_reg_read/write
> - add a compatible in axi-dac backend for the ad3552r DAC IP
> - minor code alignment fixes
> - fix a return value not checked
> - change devicetree structure setting ad3552r-axi as a backend
>   subnode
> - add synchronous_mode_available in the ABI doc

Please give reviewers a chance to response to in-progress discussion on
a version before sending a new one. I've left a couple of responses to
v1 that I only had a chance to reply to today due to travel.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-06  7:22   ` Krzysztof Kozlowski
@ 2024-09-06  9:11     ` Angelo Dureghello
  2024-09-06  9:37       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-06  9:11 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
	Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Olivier Moysan, linux-iio, devicetree, linux-kernel,
	David Lechner

Hi Krzysztof,

On 06/09/24 9:22 AM, Krzysztof Kozlowski wrote:
> On Thu, Sep 05, 2024 at 05:17:35PM +0200, Angelo Dureghello wrote:
>> From: Angelo Dureghello <adureghello@baylibre.com>
>>
>> Add a new compatible for the ad3552r variant of the generic DAC IP.
>>
>> The ad3552r DAC IP variant is very similar to the generic DAC IP,
>> register map is the same, but some register fields are specific to
>> this IP, and also, a DDR QSPI bus has been included in the IP.
>>
>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>> ---
>>   Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 1 +
>>   1 file changed, 1 insertion(+)
>>
>> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>> index a55e9bfc66d7..c0cccb7a99a4 100644
>> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>> @@ -24,6 +24,7 @@ properties:
>>     compatible:
>>       enum:
>>         - adi,axi-dac-9.1.b
>> +      - adi,axi-dac-ad3552r
> I am sorry, but what is the product here? It looks like either wrong
> order or even completely redundant. What is ad3552r?
>
> And why versions are mixed with real products but without any
> compatibility. What does the version express in such case?

dac-ad3552r IP (fpga) is a variant of the dac IP, very similar,
about the version, it still reads as 9.1.b

so i can eventually change it to:

adi,axi-dac-ad3552-9.1.b

Should be more correct.

> Best regards,
> Krzysztof
>
-- 
  ,,,      Angelo Dureghello
:: :.     BayLibre -runtime team- Developer
:`___:
  `____:


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-06  9:11     ` Angelo Dureghello
@ 2024-09-06  9:37       ` Krzysztof Kozlowski
  2024-09-06 11:53         ` Nuno Sá
  0 siblings, 1 reply; 63+ messages in thread
From: Krzysztof Kozlowski @ 2024-09-06  9:37 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,
	David Lechner

On 06/09/2024 11:11, Angelo Dureghello wrote:
> Hi Krzysztof,
> 
> On 06/09/24 9:22 AM, Krzysztof Kozlowski wrote:
>> On Thu, Sep 05, 2024 at 05:17:35PM +0200, Angelo Dureghello wrote:
>>> From: Angelo Dureghello <adureghello@baylibre.com>
>>>
>>> Add a new compatible for the ad3552r variant of the generic DAC IP.
>>>
>>> The ad3552r DAC IP variant is very similar to the generic DAC IP,
>>> register map is the same, but some register fields are specific to
>>> this IP, and also, a DDR QSPI bus has been included in the IP.
>>>
>>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>>> ---
>>>   Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 1 +
>>>   1 file changed, 1 insertion(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>> index a55e9bfc66d7..c0cccb7a99a4 100644
>>> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>> @@ -24,6 +24,7 @@ properties:
>>>     compatible:
>>>       enum:
>>>         - adi,axi-dac-9.1.b
>>> +      - adi,axi-dac-ad3552r
>> I am sorry, but what is the product here? It looks like either wrong
>> order or even completely redundant. What is ad3552r?
>>
>> And why versions are mixed with real products but without any
>> compatibility. What does the version express in such case?
> 
> dac-ad3552r IP (fpga) is a variant of the dac IP, very similar,
> about the version, it still reads as 9.1.b
> 
> so i can eventually change it to:
> 
> adi,axi-dac-ad3552-9.1.b
> 
> Should be more correct.

No. First ad3552r is the product, so axi-dac is redundant. Second why
adding versions if you have product names? Versioning was allowed
because apparently that's how these are called, but now it turns out it
is not version but names.

Third, versions are useless if you do not use them as fallbacks.

Something this is really broken and I don't know if the binding or this
patch.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP
  2024-09-06  9:07 ` Conor Dooley
@ 2024-09-06  9:44   ` Angelo Dureghello
  0 siblings, 0 replies; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-06  9:44 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,
	David Lechner

Hi Conor,

On 06/09/24 11:07 AM, Conor Dooley wrote:
> On Thu, Sep 05, 2024 at 05:17:30PM +0200, Angelo Dureghello wrote:
>> The serie comes from the previously discussed RFC, that i
>> converted to a normal patch from this v2.
>>
>> Purpose is to add ad3552r AXI DAC (fpga-based) support.
>>
>> The fpga DAC IP has been created to reach the maximum speed
>> (33MUPS) supported from the ad3552r. To obtain the maximum
>> transfer rate, the custom module has been implemented using
>> the QSPI lines in DDR mode, using a dma buffer.
>>
>> The design is actually using the DAC backend since the register
>> map is the same of the generic DAC IP, except for some customized
>> bitfields. For this reason, a new "compatible" has been added
>> in adi-axi-dac.c.
>>
>> Also, backend has been extended with all the needed functions
>> needed for this use case, keeping the names gneric.
>>
>> Note: the following patch is actually for linux-iio/testing
>> ---
>> Changes in v2:
>> - use unsigned int on bus_reg_read/write
>> - add a compatible in axi-dac backend for the ad3552r DAC IP
>> - minor code alignment fixes
>> - fix a return value not checked
>> - change devicetree structure setting ad3552r-axi as a backend
>>    subnode
>> - add synchronous_mode_available in the ABI doc
> Please give reviewers a chance to response to in-progress discussion on
> a version before sending a new one. I've left a couple of responses to
> v1 that I only had a chance to reply to today due to travel.

sure, will wait some more days next time.

Regards,
-- 
  ,,,      Angelo Dureghello
:: :.     BayLibre -runtime team- Developer
:`___:
  `____:


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-06  9:37       ` Krzysztof Kozlowski
@ 2024-09-06 11:53         ` Nuno Sá
  2024-09-06 12:13           ` Krzysztof Kozlowski
  0 siblings, 1 reply; 63+ messages in thread
From: Nuno Sá @ 2024-09-06 11:53 UTC (permalink / raw)
  To: Krzysztof Kozlowski, 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,
	David Lechner

On Fri, 2024-09-06 at 11:37 +0200, Krzysztof Kozlowski wrote:
> On 06/09/2024 11:11, Angelo Dureghello wrote:
> > Hi Krzysztof,
> > 
> > On 06/09/24 9:22 AM, Krzysztof Kozlowski wrote:
> > > On Thu, Sep 05, 2024 at 05:17:35PM +0200, Angelo Dureghello wrote:
> > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > > 
> > > > Add a new compatible for the ad3552r variant of the generic DAC IP.
> > > > 
> > > > The ad3552r DAC IP variant is very similar to the generic DAC IP,
> > > > register map is the same, but some register fields are specific to
> > > > this IP, and also, a DDR QSPI bus has been included in the IP.
> > > > 
> > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > > ---
> > > >   Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 1 +
> > > >   1 file changed, 1 insertion(+)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > index a55e9bfc66d7..c0cccb7a99a4 100644
> > > > --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > @@ -24,6 +24,7 @@ properties:
> > > >     compatible:
> > > >       enum:
> > > >         - adi,axi-dac-9.1.b
> > > > +      - adi,axi-dac-ad3552r
> > > I am sorry, but what is the product here? It looks like either wrong
> > > order or even completely redundant. What is ad3552r?
> > > 
> > > And why versions are mixed with real products but without any
> > > compatibility. What does the version express in such case?
> > 
> > dac-ad3552r IP (fpga) is a variant of the dac IP, very similar,
> > about the version, it still reads as 9.1.b
> > 
> > so i can eventually change it to:
> > 
> > adi,axi-dac-ad3552-9.1.b
> > 
> > Should be more correct.
> 
> No. First ad3552r is the product, so axi-dac is redundant. Second why
> adding versions if you have product names? Versioning was allowed
> because apparently that's how these are called, but now it turns out it
> is not version but names.
> 

Let me try to explain on how this whole thing works...

We have a generic FPGA IP called axi-dac (same story is true for the other axi-adc
IP) which adds some basic and generic capabilities like DDS (Direct digital
synthesis) and the generic one is the compatible existing now. This IP is a so called
IIO backend because it then connects to a real converter (in this case DACs)
extending it's capabilities and also serving as an interface between another block
(typical DMA as this is used for really high speed stuff) and the device. Now,
depending on the actual device, we may need to add/modify some features of the IP and
this is what's happening for the ad3552r DAC (it's still build on top of the base
generic axi-adc). And in this design the IP is also acting as a qspi controller for
actually controlling the configuration of the device while, typically, IIO backends
are meant to only care about the dataplane. With all of this, there are discussions
still happening on the RFC (Angelo was too fast with this version) between using
different properties or new compatibles for changes so significant like this on the
generic IP. See the thread where Conor is also involved.

> Third, versions are useless if you do not use them as fallbacks.
> 

In this particular case we can't use the generic IP as a fallback since without the
bus controller feature the device can't really work. But it can happen we increase
the version on the generic core and use the existing version as fallback 

> Something this is really broken and I don't know if the binding or this
> patch.

Having said the above, I'm really not sure if what we have is the best approach but
these are also early days (upstream) for this so we should still be able to change
things if we need too. I'm fairly sure there's still no one relying on this so we
should be able to change things in a breaking way (if we need to be that extreme).

Thanks!
- Nuno Sá

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-06 11:53         ` Nuno Sá
@ 2024-09-06 12:13           ` Krzysztof Kozlowski
  2024-09-06 13:52             ` Nuno Sá
  0 siblings, 1 reply; 63+ messages in thread
From: Krzysztof Kozlowski @ 2024-09-06 12:13 UTC (permalink / raw)
  To: Nuno Sá, 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,
	David Lechner

On 06/09/2024 13:53, Nuno Sá wrote:
> On Fri, 2024-09-06 at 11:37 +0200, Krzysztof Kozlowski wrote:
>> On 06/09/2024 11:11, Angelo Dureghello wrote:
>>> Hi Krzysztof,
>>>
>>> On 06/09/24 9:22 AM, Krzysztof Kozlowski wrote:
>>>> On Thu, Sep 05, 2024 at 05:17:35PM +0200, Angelo Dureghello wrote:
>>>>> From: Angelo Dureghello <adureghello@baylibre.com>
>>>>>
>>>>> Add a new compatible for the ad3552r variant of the generic DAC IP.
>>>>>
>>>>> The ad3552r DAC IP variant is very similar to the generic DAC IP,
>>>>> register map is the same, but some register fields are specific to
>>>>> this IP, and also, a DDR QSPI bus has been included in the IP.
>>>>>
>>>>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>>>>> ---
>>>>>   Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 1 +
>>>>>   1 file changed, 1 insertion(+)
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>> b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>> index a55e9bfc66d7..c0cccb7a99a4 100644
>>>>> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>> @@ -24,6 +24,7 @@ properties:
>>>>>     compatible:
>>>>>       enum:
>>>>>         - adi,axi-dac-9.1.b
>>>>> +      - adi,axi-dac-ad3552r
>>>> I am sorry, but what is the product here? It looks like either wrong
>>>> order or even completely redundant. What is ad3552r?
>>>>
>>>> And why versions are mixed with real products but without any
>>>> compatibility. What does the version express in such case?
>>>
>>> dac-ad3552r IP (fpga) is a variant of the dac IP, very similar,
>>> about the version, it still reads as 9.1.b
>>>
>>> so i can eventually change it to:
>>>
>>> adi,axi-dac-ad3552-9.1.b
>>>
>>> Should be more correct.
>>
>> No. First ad3552r is the product, so axi-dac is redundant. Second why
>> adding versions if you have product names? Versioning was allowed
>> because apparently that's how these are called, but now it turns out it
>> is not version but names.
>>
> 
> Let me try to explain on how this whole thing works...
> 
> We have a generic FPGA IP called axi-dac (same story is true for the other axi-adc
> IP) which adds some basic and generic capabilities like DDS (Direct digital
> synthesis) and the generic one is the compatible existing now. This IP is a so called
> IIO backend because it then connects to a real converter (in this case DACs)
> extending it's capabilities and also serving as an interface between another block
> (typical DMA as this is used for really high speed stuff) and the device. Now,
> depending on the actual device, we may need to add/modify some features of the IP and
> this is what's happening for the ad3552r DAC (it's still build on top of the 

What is "ad3552"? DAC right? Then as I said axi-dac is redundant. We do
not call ti,tmp451 a ti,sensor-tmp451, right?

If ad3552 is something else, then the order of naming is not correct.
Product name is always the first.


> generic axi-adc). And in this design the IP is also acting as a qspi controller for
> actually controlling the configuration of the device while, typically, IIO backends
> are meant to only care about the dataplane. With all of this, there are discussions
> still happening on the RFC (Angelo was too fast with this version) between using
> different properties or new compatibles for changes so significant like this on the
> generic IP. See the thread where Conor is also involved.

1. Then what does it mean for "adi,axi-dac-9.1.b"?

2. Is there any real customer product which uses this compatible alone?

If you need to come up with customized compatibles, it means versioned
one is not enough.

If this is 9.1.b but not usable as 9.1.b ("for changes so significant
like this on"), then I claim 9.1.b compatible is useless.

> 
>> Third, versions are useless if you do not use them as fallbacks.
>>
> 
> In this particular case we can't use the generic IP as a fallback since without the
> bus controller feature the device can't really work. But it can happen we increase
> the version on the generic core and use the existing version as fallback 
> 
>> Something this is really broken and I don't know if the binding or this
>> patch.
> 
> Having said the above, I'm really not sure if what we have is the best approach but
> these are also early days (upstream) for this so we should still be able to change
> things if we need too. I'm fairly sure there's still no one relying on this so we
> should be able to change things in a breaking way (if we need to be that extreme).

DT maintainers consistently (before someone here calls me inconsistent)
propose not to use versioned compatibles if they map one-to-one to
products or if they cannot be used alone. Several generic IP blocks like
Synopsys or Cadence, match the latter - the customization from customer
is needed, thus snps/cdns IP-block compatible is not usable.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-06 12:13           ` Krzysztof Kozlowski
@ 2024-09-06 13:52             ` Nuno Sá
  2024-09-06 14:04               ` David Lechner
  2024-09-06 16:43               ` Krzysztof Kozlowski
  0 siblings, 2 replies; 63+ messages in thread
From: Nuno Sá @ 2024-09-06 13:52 UTC (permalink / raw)
  To: Krzysztof Kozlowski, 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,
	David Lechner

On Fri, 2024-09-06 at 14:13 +0200, Krzysztof Kozlowski wrote:
> On 06/09/2024 13:53, Nuno Sá wrote:
> > On Fri, 2024-09-06 at 11:37 +0200, Krzysztof Kozlowski wrote:
> > > On 06/09/2024 11:11, Angelo Dureghello wrote:
> > > > Hi Krzysztof,
> > > > 
> > > > On 06/09/24 9:22 AM, Krzysztof Kozlowski wrote:
> > > > > On Thu, Sep 05, 2024 at 05:17:35PM +0200, Angelo Dureghello wrote:
> > > > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > > > > 
> > > > > > Add a new compatible for the ad3552r variant of the generic DAC IP.
> > > > > > 
> > > > > > The ad3552r DAC IP variant is very similar to the generic DAC IP,
> > > > > > register map is the same, but some register fields are specific to
> > > > > > this IP, and also, a DDR QSPI bus has been included in the IP.
> > > > > > 
> > > > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > > > > ---
> > > > > >   Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 1 +
> > > > > >   1 file changed, 1 insertion(+)
> > > > > > 
> > > > > > diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > index a55e9bfc66d7..c0cccb7a99a4 100644
> > > > > > --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
> > > > > > @@ -24,6 +24,7 @@ properties:
> > > > > >     compatible:
> > > > > >       enum:
> > > > > >         - adi,axi-dac-9.1.b
> > > > > > +      - adi,axi-dac-ad3552r
> > > > > I am sorry, but what is the product here? It looks like either wrong
> > > > > order or even completely redundant. What is ad3552r?
> > > > > 
> > > > > And why versions are mixed with real products but without any
> > > > > compatibility. What does the version express in such case?
> > > > 
> > > > dac-ad3552r IP (fpga) is a variant of the dac IP, very similar,
> > > > about the version, it still reads as 9.1.b
> > > > 
> > > > so i can eventually change it to:
> > > > 
> > > > adi,axi-dac-ad3552-9.1.b
> > > > 
> > > > Should be more correct.
> > > 
> > > No. First ad3552r is the product, so axi-dac is redundant. Second why
> > > adding versions if you have product names? Versioning was allowed
> > > because apparently that's how these are called, but now it turns out it
> > > is not version but names.
> > > 
> > 
> > Let me try to explain on how this whole thing works...
> > 
> > We have a generic FPGA IP called axi-dac (same story is true for the other axi-
> > adc
> > IP) which adds some basic and generic capabilities like DDS (Direct digital
> > synthesis) and the generic one is the compatible existing now. This IP is a so
> > called
> > IIO backend because it then connects to a real converter (in this case DACs)
> > extending it's capabilities and also serving as an interface between another
> > block
> > (typical DMA as this is used for really high speed stuff) and the device. Now,
> > depending on the actual device, we may need to add/modify some features of the IP
> > and
> > this is what's happening for the ad3552r DAC (it's still build on top of the 
> 
> What is "ad3552"? DAC right? Then as I said axi-dac is redundant. We do
> not call ti,tmp451 a ti,sensor-tmp451, right?
> 

Yes, I agree the DAC part is redundant. But I think the axi prefix (or suffix) is
meaningful to differentiate it from the bindings for the device itself.

> If ad3552 is something else, then the order of naming is not correct.
> Product name is always the first.
> 
> 
> > generic axi-adc). And in this design the IP is also acting as a qspi controller
> > for
> > actually controlling the configuration of the device while, typically, IIO
> > backends
> > are meant to only care about the dataplane. With all of this, there are
> > discussions
> > still happening on the RFC (Angelo was too fast with this version) between using
> > different properties or new compatibles for changes so significant like this on
> > the
> > generic IP. See the thread where Conor is also involved.
> 
> 1. Then what does it mean for "adi,axi-dac-9.1.b"?
> 

IIUC, it means that the generic IP cannot really be used with the ad3552r DAC given
the qspi specific bits.

> 2. Is there any real customer product which uses this compatible alone?
> 

Yes, we do have devices that can work with the generic IP.

> If you need to come up with customized compatibles, it means versioned
> one is not enough.
> 

Note this was something that was suggested to Angelo. There's also the option to just
use typical FW properties like the original RFC to describe the HW changes in the IP.
But Conor made some good points on using different compatibles when changes go this
far as being also a bus controller...

> If this is 9.1.b but not usable as 9.1.b ("for changes so significant
> like this on"), then I claim 9.1.b compatible is useless.
> 

The 9.1.b versioning refers to the generic IP version and the custom design for
interfacing with the ad3552r DAC is also based on that version of the generic IP. It
already happened (for non upstream versions of the IP) for the HW folks to increase
the versioning (major) of the generic IP with some breaking change and then new
designs will be based on the newer version. On the driver we use the major number to
detect mismatches between driver expectations and what we really have in HW.

> > 
> > > Third, versions are useless if you do not use them as fallbacks.
> > > 
> > 
> > In this particular case we can't use the generic IP as a fallback since without
> > the
> > bus controller feature the device can't really work. But it can happen we
> > increase
> > the version on the generic core and use the existing version as fallback 
> > 
> > > Something this is really broken and I don't know if the binding or this
> > > patch.
> > 
> > Having said the above, I'm really not sure if what we have is the best approach
> > but
> > these are also early days (upstream) for this so we should still be able to
> > change
> > things if we need too. I'm fairly sure there's still no one relying on this so we
> > should be able to change things in a breaking way (if we need to be that
> > extreme).
> 
> DT maintainers consistently (before someone here calls me inconsistent)
> propose not to use versioned compatibles if they map one-to-one to
> products or if they cannot be used alone. Several generic IP blocks like
> Synopsys or Cadence, match the latter - the customization from customer
> is needed, thus snps/cdns IP-block compatible is not usable.
> 

Given what you're saying above (and IIUC) one thing I can see we doing would be to
forget about the version and assume the generic compatible cannot be used alone (so
adi,axi-dac). I mean, it always has to connect to real device. So we could use the
device name in the compatible and code the expected version for that project (instead
of being part of the compatible name). I guess it's similar on what's happening on
the macb driver? But in that case we do have a cdns,macb compatible that can be used
alone I think.

Only problem I could see with this is that if we have a project adi,axi-foo based on
version 9.1.b and then HW folks move on and introduce 10.0.a and re-do axi-foo on top
of the new core version. Would it then be ok to come up with a compatible like axi-
foo-v2 or axi-foo-10-0-a?

Not sure if any of the above makes much sense...

- Nuno Sá 


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 4/9] iio: backend adi-axi-dac: add registering of child fdt node
  2024-09-06  5:42     ` Nuno Sá
@ 2024-09-06 13:52       ` David Lechner
  0 siblings, 0 replies; 63+ messages in thread
From: David Lechner @ 2024-09-06 13:52 UTC (permalink / raw)
  To: Nuno Sá, Angelo Dureghello, Lars-Peter Clausen,
	Michael Hennerich, Nuno Sá, Jonathan Cameron, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Olivier Moysan
  Cc: linux-iio, devicetree, linux-kernel

On 9/6/24 12:42 AM, Nuno Sá wrote:
> On Thu, 2024-09-05 at 14:19 -0500, David Lechner wrote:
>> On 9/5/24 10:17 AM, Angelo Dureghello wrote:
>>> From: Angelo Dureghello <adureghello@baylibre.com>
>>>
>>> Change to obtain the fdt use case as reported in the
>>> adi,ad3552r.yaml file in this patchset, with the DAC device that
>>> is actually using the backend set as a child node of the backend.
>>>
>>> To obtain this, registering all the child fdt nodes as platform
>>> devices.
>>>
>>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>>> Co-developed-by: David Lechner <dlechner@baylibre.com>
>>> Co-developed-by: Nuno Sá <nuno.sa@analog.com>
>>> ---
>>>  drivers/iio/dac/adi-axi-dac.c | 15 +++++++++++++++
>>>  1 file changed, 15 insertions(+)
>>>
>>> diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
>>> index cc31e1dcd1df..e883cd557b6a 100644
>>> --- a/drivers/iio/dac/adi-axi-dac.c
>>> +++ b/drivers/iio/dac/adi-axi-dac.c
>>> @@ -783,6 +783,7 @@ static int axi_dac_probe(struct platform_device *pdev)
>>>  {
>>>  	struct axi_dac_state *st;
>>>  	const struct axi_dac_info *info;
>>> +	struct platform_device *child_pdev;
>>>  	void __iomem *base;
>>>  	unsigned int ver;
>>>  	struct clk *clk;
>>> @@ -862,6 +863,20 @@ static int axi_dac_probe(struct platform_device *pdev)
>>>  		return dev_err_probe(&pdev->dev, ret,
>>>  				     "failed to register iio backend\n");
>>>  
>>> +	device_for_each_child_node_scoped(&pdev->dev, child) {
>>
>> This should use fwnode_for_each_available_child_node() so that it skips
>> nodes with status != "okay".
>>
> 
> device_for_each_child_node() already only looks at available nodes IIRC
> 
> - Nuno Sá
> 

Ah, you are right, I did not dig deep enough.

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-06 13:52             ` Nuno Sá
@ 2024-09-06 14:04               ` David Lechner
  2024-09-06 16:36                 ` Krzysztof Kozlowski
  2024-09-06 16:43               ` Krzysztof Kozlowski
  1 sibling, 1 reply; 63+ messages in thread
From: David Lechner @ 2024-09-06 14:04 UTC (permalink / raw)
  To: Nuno Sá, Krzysztof Kozlowski, 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

On 9/6/24 8:52 AM, Nuno Sá wrote:
> On Fri, 2024-09-06 at 14:13 +0200, Krzysztof Kozlowski wrote:
>> On 06/09/2024 13:53, Nuno Sá wrote:
>>> On Fri, 2024-09-06 at 11:37 +0200, Krzysztof Kozlowski wrote:
>>>> On 06/09/2024 11:11, Angelo Dureghello wrote:
>>>>> Hi Krzysztof,
>>>>>
>>>>> On 06/09/24 9:22 AM, Krzysztof Kozlowski wrote:
>>>>>> On Thu, Sep 05, 2024 at 05:17:35PM +0200, Angelo Dureghello wrote:
>>>>>>> From: Angelo Dureghello <adureghello@baylibre.com>
>>>>>>>
>>>>>>> Add a new compatible for the ad3552r variant of the generic DAC IP.
>>>>>>>
>>>>>>> The ad3552r DAC IP variant is very similar to the generic DAC IP,
>>>>>>> register map is the same, but some register fields are specific to
>>>>>>> this IP, and also, a DDR QSPI bus has been included in the IP.
>>>>>>>
>>>>>>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>>>>>>> ---
>>>>>>>   Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 1 +
>>>>>>>   1 file changed, 1 insertion(+)
>>>>>>>
>>>>>>> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>> b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>> index a55e9bfc66d7..c0cccb7a99a4 100644
>>>>>>> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>> @@ -24,6 +24,7 @@ properties:
>>>>>>>     compatible:
>>>>>>>       enum:
>>>>>>>         - adi,axi-dac-9.1.b
>>>>>>> +      - adi,axi-dac-ad3552r
>>>>>> I am sorry, but what is the product here? It looks like either wrong
>>>>>> order or even completely redundant. What is ad3552r?
>>>>>>
>>>>>> And why versions are mixed with real products but without any
>>>>>> compatibility. What does the version express in such case?
>>>>>
>>>>> dac-ad3552r IP (fpga) is a variant of the dac IP, very similar,
>>>>> about the version, it still reads as 9.1.b
>>>>>
>>>>> so i can eventually change it to:
>>>>>
>>>>> adi,axi-dac-ad3552-9.1.b
>>>>>
>>>>> Should be more correct.
>>>>
>>>> No. First ad3552r is the product, so axi-dac is redundant. Second why
>>>> adding versions if you have product names? Versioning was allowed
>>>> because apparently that's how these are called, but now it turns out it
>>>> is not version but names.
>>>>
>>>
>>> Let me try to explain on how this whole thing works...
>>>
>>> We have a generic FPGA IP called axi-dac (same story is true for the other axi-
>>> adc
>>> IP) which adds some basic and generic capabilities like DDS (Direct digital
>>> synthesis) and the generic one is the compatible existing now. This IP is a so
>>> called
>>> IIO backend because it then connects to a real converter (in this case DACs)
>>> extending it's capabilities and also serving as an interface between another
>>> block
>>> (typical DMA as this is used for really high speed stuff) and the device. Now,
>>> depending on the actual device, we may need to add/modify some features of the IP
>>> and
>>> this is what's happening for the ad3552r DAC (it's still build on top of the 
>>
>> What is "ad3552"? DAC right? Then as I said axi-dac is redundant. We do
>> not call ti,tmp451 a ti,sensor-tmp451, right?
>>
> 
> Yes, I agree the DAC part is redundant. But I think the axi prefix (or suffix) is
> meaningful to differentiate it from the bindings for the device itself.
> 
The binding is for this [1] IP core. The documentation calls the core
"AXI AD3552R", so I agree that "adi,axi-ad2552r" is the most sensible
compatible name.

http://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-06 14:04               ` David Lechner
@ 2024-09-06 16:36                 ` Krzysztof Kozlowski
  2024-09-06 16:42                   ` David Lechner
  0 siblings, 1 reply; 63+ messages in thread
From: Krzysztof Kozlowski @ 2024-09-06 16:36 UTC (permalink / raw)
  To: David Lechner, Nuno Sá, 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

On 06/09/2024 16:04, David Lechner wrote:
> On 9/6/24 8:52 AM, Nuno Sá wrote:
>> On Fri, 2024-09-06 at 14:13 +0200, Krzysztof Kozlowski wrote:
>>> On 06/09/2024 13:53, Nuno Sá wrote:
>>>> On Fri, 2024-09-06 at 11:37 +0200, Krzysztof Kozlowski wrote:
>>>>> On 06/09/2024 11:11, Angelo Dureghello wrote:
>>>>>> Hi Krzysztof,
>>>>>>
>>>>>> On 06/09/24 9:22 AM, Krzysztof Kozlowski wrote:
>>>>>>> On Thu, Sep 05, 2024 at 05:17:35PM +0200, Angelo Dureghello wrote:
>>>>>>>> From: Angelo Dureghello <adureghello@baylibre.com>
>>>>>>>>
>>>>>>>> Add a new compatible for the ad3552r variant of the generic DAC IP.
>>>>>>>>
>>>>>>>> The ad3552r DAC IP variant is very similar to the generic DAC IP,
>>>>>>>> register map is the same, but some register fields are specific to
>>>>>>>> this IP, and also, a DDR QSPI bus has been included in the IP.
>>>>>>>>
>>>>>>>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>>>>>>>> ---
>>>>>>>>   Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 1 +
>>>>>>>>   1 file changed, 1 insertion(+)
>>>>>>>>
>>>>>>>> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>>> b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>>> index a55e9bfc66d7..c0cccb7a99a4 100644
>>>>>>>> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>>> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>>> @@ -24,6 +24,7 @@ properties:
>>>>>>>>     compatible:
>>>>>>>>       enum:
>>>>>>>>         - adi,axi-dac-9.1.b
>>>>>>>> +      - adi,axi-dac-ad3552r
>>>>>>> I am sorry, but what is the product here? It looks like either wrong
>>>>>>> order or even completely redundant. What is ad3552r?
>>>>>>>
>>>>>>> And why versions are mixed with real products but without any
>>>>>>> compatibility. What does the version express in such case?
>>>>>>
>>>>>> dac-ad3552r IP (fpga) is a variant of the dac IP, very similar,
>>>>>> about the version, it still reads as 9.1.b
>>>>>>
>>>>>> so i can eventually change it to:
>>>>>>
>>>>>> adi,axi-dac-ad3552-9.1.b
>>>>>>
>>>>>> Should be more correct.
>>>>>
>>>>> No. First ad3552r is the product, so axi-dac is redundant. Second why
>>>>> adding versions if you have product names? Versioning was allowed
>>>>> because apparently that's how these are called, but now it turns out it
>>>>> is not version but names.
>>>>>
>>>>
>>>> Let me try to explain on how this whole thing works...
>>>>
>>>> We have a generic FPGA IP called axi-dac (same story is true for the other axi-
>>>> adc
>>>> IP) which adds some basic and generic capabilities like DDS (Direct digital
>>>> synthesis) and the generic one is the compatible existing now. This IP is a so
>>>> called
>>>> IIO backend because it then connects to a real converter (in this case DACs)
>>>> extending it's capabilities and also serving as an interface between another
>>>> block
>>>> (typical DMA as this is used for really high speed stuff) and the device. Now,
>>>> depending on the actual device, we may need to add/modify some features of the IP
>>>> and
>>>> this is what's happening for the ad3552r DAC (it's still build on top of the 
>>>
>>> What is "ad3552"? DAC right? Then as I said axi-dac is redundant. We do
>>> not call ti,tmp451 a ti,sensor-tmp451, right?
>>>
>>
>> Yes, I agree the DAC part is redundant. But I think the axi prefix (or suffix) is
>> meaningful to differentiate it from the bindings for the device itself.
>>
> The binding is for this [1] IP core. The documentation calls the core
> "AXI AD3552R", so I agree that "adi,axi-ad2552r" is the most sensible
> compatible name.
> 
> http://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html

I don't see any AXI here:
https://www.analog.com/en/products/ad3552r.html
Neither here:
https://www.analog.com/media/en/technical-documentation/data-sheets/ad3552r.pdf

Are these different?

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-06 16:36                 ` Krzysztof Kozlowski
@ 2024-09-06 16:42                   ` David Lechner
  2024-09-06 16:44                     ` Krzysztof Kozlowski
  0 siblings, 1 reply; 63+ messages in thread
From: David Lechner @ 2024-09-06 16:42 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Nuno Sá, 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

On 9/6/24 11:36 AM, Krzysztof Kozlowski wrote:
> On 06/09/2024 16:04, David Lechner wrote:
>> On 9/6/24 8:52 AM, Nuno Sá wrote:
>>> On Fri, 2024-09-06 at 14:13 +0200, Krzysztof Kozlowski wrote:
>>>> On 06/09/2024 13:53, Nuno Sá wrote:
>>>>> On Fri, 2024-09-06 at 11:37 +0200, Krzysztof Kozlowski wrote:
>>>>>> On 06/09/2024 11:11, Angelo Dureghello wrote:
>>>>>>> Hi Krzysztof,
>>>>>>>
>>>>>>> On 06/09/24 9:22 AM, Krzysztof Kozlowski wrote:
>>>>>>>> On Thu, Sep 05, 2024 at 05:17:35PM +0200, Angelo Dureghello wrote:
>>>>>>>>> From: Angelo Dureghello <adureghello@baylibre.com>
>>>>>>>>>
>>>>>>>>> Add a new compatible for the ad3552r variant of the generic DAC IP.
>>>>>>>>>
>>>>>>>>> The ad3552r DAC IP variant is very similar to the generic DAC IP,
>>>>>>>>> register map is the same, but some register fields are specific to
>>>>>>>>> this IP, and also, a DDR QSPI bus has been included in the IP.
>>>>>>>>>
>>>>>>>>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>>>>>>>>> ---
>>>>>>>>>   Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 1 +
>>>>>>>>>   1 file changed, 1 insertion(+)
>>>>>>>>>
>>>>>>>>> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>>>> b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>>>> index a55e9bfc66d7..c0cccb7a99a4 100644
>>>>>>>>> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>>>> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>>>> @@ -24,6 +24,7 @@ properties:
>>>>>>>>>     compatible:
>>>>>>>>>       enum:
>>>>>>>>>         - adi,axi-dac-9.1.b
>>>>>>>>> +      - adi,axi-dac-ad3552r
>>>>>>>> I am sorry, but what is the product here? It looks like either wrong
>>>>>>>> order or even completely redundant. What is ad3552r?
>>>>>>>>
>>>>>>>> And why versions are mixed with real products but without any
>>>>>>>> compatibility. What does the version express in such case?
>>>>>>>
>>>>>>> dac-ad3552r IP (fpga) is a variant of the dac IP, very similar,
>>>>>>> about the version, it still reads as 9.1.b
>>>>>>>
>>>>>>> so i can eventually change it to:
>>>>>>>
>>>>>>> adi,axi-dac-ad3552-9.1.b
>>>>>>>
>>>>>>> Should be more correct.
>>>>>>
>>>>>> No. First ad3552r is the product, so axi-dac is redundant. Second why
>>>>>> adding versions if you have product names? Versioning was allowed
>>>>>> because apparently that's how these are called, but now it turns out it
>>>>>> is not version but names.
>>>>>>
>>>>>
>>>>> Let me try to explain on how this whole thing works...
>>>>>
>>>>> We have a generic FPGA IP called axi-dac (same story is true for the other axi-
>>>>> adc
>>>>> IP) which adds some basic and generic capabilities like DDS (Direct digital
>>>>> synthesis) and the generic one is the compatible existing now. This IP is a so
>>>>> called
>>>>> IIO backend because it then connects to a real converter (in this case DACs)
>>>>> extending it's capabilities and also serving as an interface between another
>>>>> block
>>>>> (typical DMA as this is used for really high speed stuff) and the device. Now,
>>>>> depending on the actual device, we may need to add/modify some features of the IP
>>>>> and
>>>>> this is what's happening for the ad3552r DAC (it's still build on top of the 
>>>>
>>>> What is "ad3552"? DAC right? Then as I said axi-dac is redundant. We do
>>>> not call ti,tmp451 a ti,sensor-tmp451, right?
>>>>
>>>
>>> Yes, I agree the DAC part is redundant. But I think the axi prefix (or suffix) is
>>> meaningful to differentiate it from the bindings for the device itself.
>>>
>> The binding is for this [1] IP core. The documentation calls the core
>> "AXI AD3552R", so I agree that "adi,axi-ad2552r" is the most sensible
>> compatible name.
>>
>> http://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
> 
> I don't see any AXI here:
> https://www.analog.com/en/products/ad3552r.html
> Neither here:
> https://www.analog.com/media/en/technical-documentation/data-sheets/ad3552r.pdf
> 
> Are these different?


Yes, they are different. AD2553R is the DAC chip itself. But "AXI AD2553R" is an
FPGA IP block designed specifically for use with that chip.


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-06 13:52             ` Nuno Sá
  2024-09-06 14:04               ` David Lechner
@ 2024-09-06 16:43               ` Krzysztof Kozlowski
  1 sibling, 0 replies; 63+ messages in thread
From: Krzysztof Kozlowski @ 2024-09-06 16:43 UTC (permalink / raw)
  To: Nuno Sá, 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,
	David Lechner

On 06/09/2024 15:52, Nuno Sá wrote:
>>>
>>> We have a generic FPGA IP called axi-dac (same story is true for the other axi-
>>> adc
>>> IP) which adds some basic and generic capabilities like DDS (Direct digital
>>> synthesis) and the generic one is the compatible existing now. This IP is a so
>>> called
>>> IIO backend because it then connects to a real converter (in this case DACs)
>>> extending it's capabilities and also serving as an interface between another
>>> block
>>> (typical DMA as this is used for really high speed stuff) and the device. Now,
>>> depending on the actual device, we may need to add/modify some features of the IP
>>> and
>>> this is what's happening for the ad3552r DAC (it's still build on top of the 
>>
>> What is "ad3552"? DAC right? Then as I said axi-dac is redundant. We do
>> not call ti,tmp451 a ti,sensor-tmp451, right?
>>
> 
> Yes, I agree the DAC part is redundant. But I think the axi prefix (or suffix) is
> meaningful to differentiate it from the bindings for the device itself.

I don't understand: what are the bindings for the device itself? What is
this patch/binding if not device itself?

> 
>> If ad3552 is something else, then the order of naming is not correct.
>> Product name is always the first.
>>
>>
>>> generic axi-adc). And in this design the IP is also acting as a qspi controller
>>> for
>>> actually controlling the configuration of the device while, typically, IIO
>>> backends
>>> are meant to only care about the dataplane. With all of this, there are
>>> discussions
>>> still happening on the RFC (Angelo was too fast with this version) between using
>>> different properties or new compatibles for changes so significant like this on
>>> the
>>> generic IP. See the thread where Conor is also involved.
>>
>> 1. Then what does it mean for "adi,axi-dac-9.1.b"?
>>
> 
> IIUC, it means that the generic IP cannot really be used with the ad3552r DAC given
> the qspi specific bits.

ok

> 
>> 2. Is there any real customer product which uses this compatible alone?
>>
> 
> Yes, we do have devices that can work with the generic IP.

Where are they? There is nothing in the upstream, so maybe that's just
misconfigured downstream DTS?

Or maybe these are just some sort of IP core designs which cannot be
used in real case alone/directly.

> 
>> If you need to come up with customized compatibles, it means versioned
>> one is not enough.
>>
> 
> Note this was something that was suggested to Angelo. There's also the option to just
> use typical FW properties like the original RFC to describe the HW changes in the IP.
> But Conor made some good points on using different compatibles when changes go this
> far as being also a bus controller...
> 
>> If this is 9.1.b but not usable as 9.1.b ("for changes so significant
>> like this on"), then I claim 9.1.b compatible is useless.
>>
> 
> The 9.1.b versioning refers to the generic IP version and the custom design for
> interfacing with the ad3552r DAC is also based on that version of the generic IP. It
> already happened (for non upstream versions of the IP) for the HW folks to increase
> the versioning (major) of the generic IP with some breaking change and then new
> designs will be based on the newer version. On the driver we use the major number to
> detect mismatches between driver expectations and what we really have in HW.
> 
>>>
>>>> Third, versions are useless if you do not use them as fallbacks.
>>>>
>>>
>>> In this particular case we can't use the generic IP as a fallback since without
>>> the
>>> bus controller feature the device can't really work. But it can happen we
>>> increase
>>> the version on the generic core and use the existing version as fallback 
>>>
>>>> Something this is really broken and I don't know if the binding or this
>>>> patch.
>>>
>>> Having said the above, I'm really not sure if what we have is the best approach
>>> but
>>> these are also early days (upstream) for this so we should still be able to
>>> change
>>> things if we need too. I'm fairly sure there's still no one relying on this so we
>>> should be able to change things in a breaking way (if we need to be that
>>> extreme).
>>
>> DT maintainers consistently (before someone here calls me inconsistent)
>> propose not to use versioned compatibles if they map one-to-one to
>> products or if they cannot be used alone. Several generic IP blocks like
>> Synopsys or Cadence, match the latter - the customization from customer
>> is needed, thus snps/cdns IP-block compatible is not usable.
>>
> 
> Given what you're saying above (and IIUC) one thing I can see we doing would be to
> forget about the version and assume the generic compatible cannot be used alone (so
> adi,axi-dac). I mean, it always has to connect to real device. So we could use the
> device name in the compatible and code the expected version for that project (instead
> of being part of the compatible name). I guess it's similar on what's happening on
> the macb driver? But in that case we do have a cdns,macb compatible that can be used
> alone I think.
> 
> Only problem I could see with this is that if we have a project adi,axi-foo based on
> version 9.1.b and then HW folks move on and introduce 10.0.a and re-do axi-foo on top
> of the new core version. Would it then be ok to come up with a compatible like axi-
> foo-v2 or axi-foo-10-0-a?
> 
> Not sure if any of the above makes much sense...

None of above make sense because they are again versioned or generic.
Use final product names, assuming they are such.

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible
  2024-09-06 16:42                   ` David Lechner
@ 2024-09-06 16:44                     ` Krzysztof Kozlowski
  0 siblings, 0 replies; 63+ messages in thread
From: Krzysztof Kozlowski @ 2024-09-06 16:44 UTC (permalink / raw)
  To: David Lechner, Nuno Sá, 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

On 06/09/2024 18:42, David Lechner wrote:
> On 9/6/24 11:36 AM, Krzysztof Kozlowski wrote:
>> On 06/09/2024 16:04, David Lechner wrote:
>>> On 9/6/24 8:52 AM, Nuno Sá wrote:
>>>> On Fri, 2024-09-06 at 14:13 +0200, Krzysztof Kozlowski wrote:
>>>>> On 06/09/2024 13:53, Nuno Sá wrote:
>>>>>> On Fri, 2024-09-06 at 11:37 +0200, Krzysztof Kozlowski wrote:
>>>>>>> On 06/09/2024 11:11, Angelo Dureghello wrote:
>>>>>>>> Hi Krzysztof,
>>>>>>>>
>>>>>>>> On 06/09/24 9:22 AM, Krzysztof Kozlowski wrote:
>>>>>>>>> On Thu, Sep 05, 2024 at 05:17:35PM +0200, Angelo Dureghello wrote:
>>>>>>>>>> From: Angelo Dureghello <adureghello@baylibre.com>
>>>>>>>>>>
>>>>>>>>>> Add a new compatible for the ad3552r variant of the generic DAC IP.
>>>>>>>>>>
>>>>>>>>>> The ad3552r DAC IP variant is very similar to the generic DAC IP,
>>>>>>>>>> register map is the same, but some register fields are specific to
>>>>>>>>>> this IP, and also, a DDR QSPI bus has been included in the IP.
>>>>>>>>>>
>>>>>>>>>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>>>>>>>>>> ---
>>>>>>>>>>   Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml | 1 +
>>>>>>>>>>   1 file changed, 1 insertion(+)
>>>>>>>>>>
>>>>>>>>>> diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>>>>> b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>>>>> index a55e9bfc66d7..c0cccb7a99a4 100644
>>>>>>>>>> --- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>>>>> +++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
>>>>>>>>>> @@ -24,6 +24,7 @@ properties:
>>>>>>>>>>     compatible:
>>>>>>>>>>       enum:
>>>>>>>>>>         - adi,axi-dac-9.1.b
>>>>>>>>>> +      - adi,axi-dac-ad3552r
>>>>>>>>> I am sorry, but what is the product here? It looks like either wrong
>>>>>>>>> order or even completely redundant. What is ad3552r?
>>>>>>>>>
>>>>>>>>> And why versions are mixed with real products but without any
>>>>>>>>> compatibility. What does the version express in such case?
>>>>>>>>
>>>>>>>> dac-ad3552r IP (fpga) is a variant of the dac IP, very similar,
>>>>>>>> about the version, it still reads as 9.1.b
>>>>>>>>
>>>>>>>> so i can eventually change it to:
>>>>>>>>
>>>>>>>> adi,axi-dac-ad3552-9.1.b
>>>>>>>>
>>>>>>>> Should be more correct.
>>>>>>>
>>>>>>> No. First ad3552r is the product, so axi-dac is redundant. Second why
>>>>>>> adding versions if you have product names? Versioning was allowed
>>>>>>> because apparently that's how these are called, but now it turns out it
>>>>>>> is not version but names.
>>>>>>>
>>>>>>
>>>>>> Let me try to explain on how this whole thing works...
>>>>>>
>>>>>> We have a generic FPGA IP called axi-dac (same story is true for the other axi-
>>>>>> adc
>>>>>> IP) which adds some basic and generic capabilities like DDS (Direct digital
>>>>>> synthesis) and the generic one is the compatible existing now. This IP is a so
>>>>>> called
>>>>>> IIO backend because it then connects to a real converter (in this case DACs)
>>>>>> extending it's capabilities and also serving as an interface between another
>>>>>> block
>>>>>> (typical DMA as this is used for really high speed stuff) and the device. Now,
>>>>>> depending on the actual device, we may need to add/modify some features of the IP
>>>>>> and
>>>>>> this is what's happening for the ad3552r DAC (it's still build on top of the 
>>>>>
>>>>> What is "ad3552"? DAC right? Then as I said axi-dac is redundant. We do
>>>>> not call ti,tmp451 a ti,sensor-tmp451, right?
>>>>>
>>>>
>>>> Yes, I agree the DAC part is redundant. But I think the axi prefix (or suffix) is
>>>> meaningful to differentiate it from the bindings for the device itself.
>>>>
>>> The binding is for this [1] IP core. The documentation calls the core
>>> "AXI AD3552R", so I agree that "adi,axi-ad2552r" is the most sensible
>>> compatible name.
>>>
>>> http://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
>>
>> I don't see any AXI here:
>> https://www.analog.com/en/products/ad3552r.html
>> Neither here:
>> https://www.analog.com/media/en/technical-documentation/data-sheets/ad3552r.pdf
>>
>> Are these different?
> 
> 
> Yes, they are different. AD2553R is the DAC chip itself. But "AXI AD2553R" is an
> FPGA IP block designed specifically for use with that chip.

OK, this makes sense now. The commit msg said nothing about it. No
distinction and rather confusing "The ad3552r DAC IP".

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 9/9] iio: ABI: add DAC sysfs synchronous_mode parameter
  2024-09-05 19:14   ` David Lechner
@ 2024-09-08 12:26     ` Jonathan Cameron
  0 siblings, 0 replies; 63+ messages in thread
From: Jonathan Cameron @ 2024-09-08 12:26 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

On Thu, 5 Sep 2024 14:14:37 -0500
David Lechner <dlechner@baylibre.com> wrote:

> On 9/5/24 10:17 AM, Angelo Dureghello 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 | 16 ++++++++++++++++
> >  1 file changed, 16 insertions(+)
> > 
> > diff --git a/Documentation/ABI/testing/sysfs-bus-iio-dac b/Documentation/ABI/testing/sysfs-bus-iio-dac
> > index 810eaac5533c..2f4960c79385 100644
> > --- a/Documentation/ABI/testing/sysfs-bus-iio-dac
> > +++ b/Documentation/ABI/testing/sysfs-bus-iio-dac
> > @@ -59,3 +59,19 @@ 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:
> > +		Arm or disarm a wait-for-synchronization flag. Arming this flag
> > +		means the DAC will wait for a synchronizatiopn signal on a
> > +		specific internal or external wired connection. I.e., there are
> > +		cases where multiple DACs IP are built in the same chip or fpga
> > +		design, and they need to start the data stream synchronized.
> > +
> > +What:		/sys/bus/iio/devices/iio:deviceX/out_voltage_synchronous_mode_available
> > +KernelVersion:	6.13
> > +Contact:	linux-iio@vger.kernel.org
> > +Description:
> > +		List of available values for synchronous_mode.
> >   
> 
> Since this depends on how things are wired, it seems like this should be
> something specified in the devicetree, not through sysfs attributes.
> 
Agreed. Smells like a wiring thing given the description.  Is there a case
where it works either way and it is usecase dependent which choice makes
sense?   Superficially it seems likely if a board has this wired, there
is little disadvantage in using it always.

Jonathan

> 


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-05 15:17 ` [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property Angelo Dureghello
  2024-09-05 16:28   ` Rob Herring (Arm)
@ 2024-09-08 12:29   ` Jonathan Cameron
  2024-09-09 11:39     ` Angelo Dureghello
  2024-09-09 12:46     ` Conor Dooley
  1 sibling, 2 replies; 63+ messages in thread
From: Jonathan Cameron @ 2024-09-08 12:29 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, David Lechner

On Thu, 05 Sep 2024 17:17:31 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:

> 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>

>  
>  required:
>    - compatible
> -  - reg
> -  - spi-max-frequency
Sort of feels like both reg and spi-max-frequency
are valid things to specify. 

Maybe we have an excellent IP and dodgy wiring so want
to clamp the frequency (long term - don't need to support
in the driver today).

Maybe we have an axi_dac IP that supports multiple
front end devices?  So maybe just keep reg?
>  
>  additionalProperties: false
>  
> @@ -238,4 +254,26 @@ examples:
>              };
>          };
>      };
> +
> +  - |
> +    backend: axi_dac@44a70000 {
> +        compatible = "adi,axi-dac-ad3552r";
> +        reg = <0x44a70000 0x1000>;
> +        dmas = <&dac_tx_dma 0>;
> +        dma-names = "tx";
> +        #io-backend-cells = <0>;
> +        clocks = <&ref_clk>;
> +        dac {
> +            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 = <(-10000000) (10000000)>;
> +            };
> +        };
> +    };
> +
>  ...
> 


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 4/9] iio: backend adi-axi-dac: add registering of child fdt node
  2024-09-06  7:08     ` Nuno Sá
@ 2024-09-08 12:36       ` Jonathan Cameron
  2024-09-09  7:53         ` Nuno Sá
  0 siblings, 1 reply; 63+ messages in thread
From: Jonathan Cameron @ 2024-09-08 12:36 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

On Fri, 06 Sep 2024 09:08:59 +0200
Nuno Sá <noname.nuno@gmail.com> wrote:

> On Thu, 2024-09-05 at 14:19 -0500, David Lechner wrote:
> > On 9/5/24 10:17 AM, Angelo Dureghello wrote:  
> > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > 
> > > Change to obtain the fdt use case as reported in the
> > > adi,ad3552r.yaml file in this patchset, with the DAC device that
> > > is actually using the backend set as a child node of the backend.
> > > 
> > > To obtain this, registering all the child fdt nodes as platform
> > > devices.
> > > 
> > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > Co-developed-by: David Lechner <dlechner@baylibre.com>
> > > Co-developed-by: Nuno Sá <nuno.sa@analog.com>
> > > ---
> > >  drivers/iio/dac/adi-axi-dac.c | 15 +++++++++++++++
> > >  1 file changed, 15 insertions(+)
> > > 
> > > diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
> > > index cc31e1dcd1df..e883cd557b6a 100644
> > > --- a/drivers/iio/dac/adi-axi-dac.c
> > > +++ b/drivers/iio/dac/adi-axi-dac.c
> > > @@ -783,6 +783,7 @@ static int axi_dac_probe(struct platform_device *pdev)
> > >  {
> > >  	struct axi_dac_state *st;
> > >  	const struct axi_dac_info *info;
> > > +	struct platform_device *child_pdev;
> > >  	void __iomem *base;
> > >  	unsigned int ver;
> > >  	struct clk *clk;
> > > @@ -862,6 +863,20 @@ static int axi_dac_probe(struct platform_device *pdev)
> > >  		return dev_err_probe(&pdev->dev, ret,
> > >  				     "failed to register iio backend\n");
> > >  
> > > +	device_for_each_child_node_scoped(&pdev->dev, child) {  
> > 
> > This should use fwnode_for_each_available_child_node() so that it skips
> > nodes with status != "okay".

Ah. That oddity strikes again...

> > 
> > Would be nice to introduce a scoped version of this function too.
> > 
> > Also, if we are allowing multiple devices on the bus, the DT bindings
> > need to have a reg property that is unique for each child.
> >   
> > > +		struct platform_device_info pi;
> > > +
> > > +		memset(&pi, 0, sizeof(pi));  
> > 
> > struct platform_device_info pi = { };
> > 
> > avoids the need for memset().
> >   
> > > +
> > > +		pi.name = fwnode_get_name(child);
> > > +		pi.id = PLATFORM_DEVID_AUTO;
> > > +		pi.fwnode = child;  
> > 
> > Need to have pi.parent = &pdev->dev;
> > 
> > It could also make sense to have all of the primary bus functions
> > (reg read/write, ddr enable/disable, etc.) passed here as platform
> > data instead of having everything go through the IIO backend.  
> 
> Note that ddr enable/disable is something that makes sense to be in the backend
> anyways as it is something that exists in LVDS/CMOS interfaces that are only running
> the dataplane. Bus operations like read/write could make sense but that would mean an
> interface directly between the axi-dac and the child devices (bypassing the backend
> or any other middle layer - maybe we could create a tiny adi-axi-bus layer on the IIO
> topdir or any other place in IIO) which I'm not so sure (and is a bit odd). OTOH,
> this bus stuff goes a bit out of scope of the backend main idea/goal so yeah... Well,
> let's see what others have to say about it but I don't dislike the idea.

For the read/write using platform data does seem reasonable to me.
Agreed that DDR is dataplane (at least sometimes) so backend ops probably appropriate.

> 
> >   
> > > +
> > > +		child_pdev = platform_device_register_full(&pi);
> > > +		if (IS_ERR(child_pdev))
> > > +			return PTR_ERR(child_pdev);  
> > 
> > These devices need to be unregistered on any error return and when
> > the parent device is removed.
> >   
> 
> Definitely this needs to be tested by manually unbinding the axi-dac device for
> example. I'm not really sure how this will look like and if there's any problem in
> removing twice the same device (likely there is). The thing is that when we connect a
> frontend with it's backend, a devlink is created (that guarantees that the frontend
> is removed before the backend). So, I'm fairly confident that if we add a devm action
> in here to unregister the child devices, by the time we unregister the child, it
> should be already gone (unless driver core somehow handles this).
> 
> All of the above needs careful testing but one way out it (and since in here we have
> the parent - child relationship), we could add a boolean flag 'skip_devlink' to
> 'struct iio_backend_info' so that devlinks are skipped on these arrangements. Or we
> could automatically detect that the frontend is a child of the backend and skip the
> link (though an explicit flag might be better).

Agreed it needs testing but I'm not sure why it would already have gone.
The driver would have unbound, but the platform device /child would still be there
I think at time of removal. Can probably get away with devm to tear
it down when the backend device then goes away.

Maybe I'm missing some subtlety though.

Jonathan


> 
> - Nuno Sá
> 
> >   


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 2/9] iio: backend: extend features
  2024-09-05 15:17 ` [PATCH v2 2/9] iio: backend: extend features Angelo Dureghello
@ 2024-09-08 12:38   ` Jonathan Cameron
  2024-09-09 11:58     ` Angelo Dureghello
  0 siblings, 1 reply; 63+ messages in thread
From: Jonathan Cameron @ 2024-09-08 12: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, David Lechner

On Thu, 05 Sep 2024 17:17:32 +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

The RAMP_16 definition doesn't seem immediately connected to the rest.
+ I'm not sure what it is from the name.

> 
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> ---
>  drivers/iio/industrialio-backend.c | 157 +++++++++++++++++++++++++++++++++++++
>  include/linux/iio/backend.h        |  33 ++++++++
>  2 files changed, 190 insertions(+)
> 
> diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
> index 20b3b5212da7..231bef4b560e 100644
> --- a/drivers/iio/industrialio-backend.c
> +++ b/drivers/iio/industrialio-backend.c
> @@ -718,6 +718,163 @@ static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back)
>  	return 0;
>  }
> diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h
> index 37d56914d485..eb8c5bb74bb5 100644
> --- a/include/linux/iio/backend.h
> +++ b/include/linux/iio/backend.h
>  
>  enum iio_backend_data_source {
>  	IIO_BACKEND_INTERNAL_CONTINUOUS_WAVE,
>  	IIO_BACKEND_EXTERNAL,
> +	IIO_BACKEND_INTERNAL_RAMP_16,

Not obvious what this is so maybe this enum needs docs in general.

>  	IIO_BACKEND_DATA_SOURCE_MAX
>  };

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 3/9] iio: backend adi-axi-dac: extend features
  2024-09-05 15:17 ` [PATCH v2 3/9] iio: backend adi-axi-dac: " Angelo Dureghello
@ 2024-09-08 15:11   ` Jonathan Cameron
  2024-09-08 15:40   ` Christophe JAILLET
  1 sibling, 0 replies; 63+ messages in thread
From: Jonathan Cameron @ 2024-09-08 15: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, David Lechner

On Thu, 05 Sep 2024 17:17:33 +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 ad3552r DAC. Mainly, a new compatible string has
> been added to support a DAC IP very similar to the generic DAC IP
> but with some customizations to work with the ad3552r.
> 
> Then, a serie of generic functions has been added to match with
> ad3552r needs. Function names has been kept generic as much as
> possible, to allow re-utilization from other frontend drivers.
> 
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> Co-developed-by: David Lechner <dlechner@baylibre.com>
> Co-developed-by: Nuno Sá <nuno.sa@analog.com>
A few comments below.

> ---
>  drivers/iio/dac/adi-axi-dac.c | 267 ++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 257 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
> index 0cb00f3bec04..cc31e1dcd1df 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)

Bug?  Either was wrong before or after this change. I've no
idea which.


> +
> +static int axi_dac_bus_reg_write(struct iio_backend *back, u32 reg,
> +				 unsigned int val, size_t data_size)
> +{
> +	struct axi_dac_state *st = iio_backend_get_priv(back);
> +
> +	switch (st->info->bus_type) {
> +	case AXI_DAC_BUS_TYPE_DDR_QSPI: {

...

> +
> +		return regmap_clear_bits(st->regmap, AXI_DAC_REG_CUSTOM_CTRL,
> +					  AXI_DAC_TRANSFER_DATA);
> +		}
> +		break;

Can't get here so drop the break;


> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +}
> +
> +static int axi_dac_bus_reg_read(struct iio_backend *back, u32 reg,
> +				unsigned int *val, size_t data_size)
> +{
> +	struct axi_dac_state *st = iio_backend_get_priv(back);
> +
> +	switch (st->info->bus_type) {
> +	case AXI_DAC_BUS_TYPE_DDR_QSPI: {
> +		int ret;
> +		u32 bval;
> +
> +		bval = 0;
> +		ret = axi_dac_bus_reg_write(back, AXI_DAC_RD_ADDR(reg), 0,
> +					    data_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);
> +		}
> +		break;
Can't get here.

> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +}


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 6/9] iio: dac: ad3552r: changes to use FIELD_PREP
  2024-09-05 15:17 ` [PATCH v2 6/9] iio: dac: ad3552r: changes to use FIELD_PREP Angelo Dureghello
  2024-09-05 20:59   ` David Lechner
@ 2024-09-08 15:14   ` Jonathan Cameron
  2024-09-08 15:15     ` Jonathan Cameron
  1 sibling, 1 reply; 63+ messages in thread
From: Jonathan Cameron @ 2024-09-08 15:14 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, David Lechner

On Thu, 05 Sep 2024 17:17:36 +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 removed too.
> 
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>

If it isn't too hard I would drag this to the start of the patch set
because I'll happily pick it up as a cleanup before any discussion of later
patches is complete.  That will reduce what people need to look at for
future versions.

Jonathan

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 6/9] iio: dac: ad3552r: changes to use FIELD_PREP
  2024-09-08 15:14   ` Jonathan Cameron
@ 2024-09-08 15:15     ` Jonathan Cameron
  0 siblings, 0 replies; 63+ messages in thread
From: Jonathan Cameron @ 2024-09-08 15: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, David Lechner

On Sun, 8 Sep 2024 16:14:20 +0100
Jonathan Cameron <jic23@kernel.org> wrote:

> On Thu, 05 Sep 2024 17:17:36 +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 removed too.
> > 
> > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>  
> 
> If it isn't too hard I would drag this to the start of the patch set
> because I'll happily pick it up as a cleanup before any discussion of later
> patches is complete.  That will reduce what people need to look at for
> future versions.
> 
> Jonathan

I'm being dopey.  None of the earlier patches touched this file
anyway so I can do that once you've addressed David's comment.

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 3/9] iio: backend adi-axi-dac: extend features
  2024-09-05 15:17 ` [PATCH v2 3/9] iio: backend adi-axi-dac: " Angelo Dureghello
  2024-09-08 15:11   ` Jonathan Cameron
@ 2024-09-08 15:40   ` Christophe JAILLET
  1 sibling, 0 replies; 63+ messages in thread
From: Christophe JAILLET @ 2024-09-08 15:40 UTC (permalink / raw)
  To: adureghello
  Cc: Michael.Hennerich, conor+dt, devicetree, dlechner, jic23, krzk+dt,
	lars, linux-iio, linux-kernel, nuno.sa, olivier.moysan, robh

Le 05/09/2024 à 17:17, Angelo Dureghello a écrit :
> From: Angelo Dureghello <adureghello-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> 
> Extend DAC backend with new features required for the AXI driver
> version for the ad3552r DAC. Mainly, a new compatible string has
> been added to support a DAC IP very similar to the generic DAC IP
> but with some customizations to work with the ad3552r.
> 
> Then, a serie of generic functions has been added to match with
> ad3552r needs. Function names has been kept generic as much as
> possible, to allow re-utilization from other frontend drivers.

Hi,

...

> +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));

Having a devm_clk_get() in such a place is really unusual.
Is it correct?

This look like a memory leak to me.

> +
> +		return IIO_VAL_INT;
> +	default:
> +		return -EINVAL;
> +	}
> +}

...

> +		/*
> +		 * 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.

"... for to ..." sounds strange to my *non*-native English ears.

> +		 * DDR state handled separately by specific backend calls,
> +		 * generally all raw register writes are SDR.
> +		 */
> +		if (data_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;

...

> @@ -556,10 +792,12 @@ static int axi_dac_probe(struct platform_device *pdev)
>   	if (!st)
>   		return -ENOMEM;
>   
> -	expected_ver = device_get_match_data(&pdev->dev);
> -	if (!expected_ver)
> +	info = device_get_match_data(&pdev->dev);
> +	if (!info)

writing:
	st->info = device_get_match_data(&pdev->dev);
	if (!st->info)

would save the 'info' variable and a few lines of code without loosing 
(IMHO) readability.

CJ

>   		return -ENODEV;
>   
> +	st->info = info;
> +
>   	clk = devm_clk_get_enabled(&pdev->dev, NULL);
>   	if (IS_ERR(clk))
>   		return dev_err_probe(&pdev->dev, PTR_ERR(clk),
> @@ -588,12 +826,13 @@ static int axi_dac_probe(struct platform_device *pdev)
>   	if (ret)
>   		return ret;
>   
> -	if (ADI_AXI_PCORE_VER_MAJOR(ver) != ADI_AXI_PCORE_VER_MAJOR(*expected_ver)) {
> +	if (ADI_AXI_PCORE_VER_MAJOR(ver) !=
> +		ADI_AXI_PCORE_VER_MAJOR(st->info->version)) {
>   		dev_err(&pdev->dev,
>   			"Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
> -			ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
> -			ADI_AXI_PCORE_VER_MINOR(*expected_ver),
> -			ADI_AXI_PCORE_VER_PATCH(*expected_ver),
> +			ADI_AXI_PCORE_VER_MAJOR(st->info->version),
> +			ADI_AXI_PCORE_VER_MINOR(st->info->version),
> +			ADI_AXI_PCORE_VER_PATCH(st->info->version),
>   			ADI_AXI_PCORE_VER_MAJOR(ver),
>   			ADI_AXI_PCORE_VER_MINOR(ver),
>   			ADI_AXI_PCORE_VER_PATCH(ver));
> @@ -631,10 +870,18 @@ static int axi_dac_probe(struct platform_device *pdev)
>   	return 0;
>   }

...


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 7/9] iio: dac: ad3552r: extract common code (no changes in behavior intended)
  2024-09-05 15:17 ` [PATCH v2 7/9] iio: dac: ad3552r: extract common code (no changes in behavior intended) Angelo Dureghello
@ 2024-09-08 15:42   ` Jonathan Cameron
  2024-09-08 15:53   ` Christophe JAILLET
  1 sibling, 0 replies; 63+ messages in thread
From: Jonathan Cameron @ 2024-09-08 15:42 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, David Lechner

On Thu, 05 Sep 2024 17:17:37 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:

> 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>

Looks like a few arrays are now duplicated that probably shouldn't be.
Otherwise, just trivial comments inline.

Jonathan


> ---
>  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},

Please add spaces after { and before } given the code
is moving anyway and that's my preferred style (I'm getting fussier
about it over time :)


> +	[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)

return a u16 instead of passing it in as a pointer.
Fits better with how it is used I think.

> +{
> +	*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;

Trivial: Don't mix declarations with assignment and ones with out on same line.
It's slightly trickier to read.  This driver currently does this
a lot but lets not introduce more cases.


> +
> +	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;
If val fits nicely into 31 bits and hence the positive values, I'd
return it as then these all become
			return AD...

> +		else
> +			*val = AD3552R_INTERNAL_VREF_PIN_FLOATING;
> +	} else {
and this else is then unnecessary.

> +		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;
	if (err)
		return err;

	if (*val > 3) {
		dev_err(dev,
			"adi,sdo-drive-strength must be less than 4\n");
		return -EINVAL;
	}
	
	return 0;

is a bit longer but keeps the error handling well separated from the
good path.

> +	}
> +
> +	return err;
> +}
> +

> +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;

Maybe add a comment that this property is optional, so we want to distinguish
this particular reason for failure.  Took me a few mins to figure out why
we needed this check.


> +
> +	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 @@

> -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] = {

This exists now in ad3552-common.c as well as here which seems unlikely to be
what you want.

>  	[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] = {

Isn't this in the new location above?

>  	[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_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);
>  
> -	reg |= FIELD_PREP(AD3552R_MASK_CH_OFFSET_POLARITY, (s32)val < 0);
>  	addr = AD3552R_REG_ADDR_CH_GAIN(ch);
>  	err = ad3552r_write_reg(dac, addr,

Given you now have the calculation of reg nice and compact, I'd move that after
this call.  It's odd to calculate a value first then not use it whilst
doing some other stuff.

> -				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;
With suggestion above,
	err = ad3552_get_ref_voltage(dev);
	if (err)
		return err;

	val = err;

>  
>  	err = ad3552r_update_reg_field(dac,
>  				       AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
...

> 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>

It's all code lifted from elsewhere, so keep the original 
2021 date as well.  2021-2024 would be fine.

> + */
...



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 8/9] iio: dac: ad3552r: add axi platform driver
  2024-09-05 20:40   ` David Lechner
@ 2024-09-08 15:49     ` Jonathan Cameron
  2024-09-09  9:00     ` Nuno Sá
  1 sibling, 0 replies; 63+ messages in thread
From: Jonathan Cameron @ 2024-09-08 15:49 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

On Thu, 5 Sep 2024 15:40:11 -0500
David Lechner <dlechner@baylibre.com> wrote:

> On 9/5/24 10:17 AM, Angelo Dureghello wrote:
> 
> ...
One reply to a comment David made.

Jonathan

> 
> > +		 */
> > +		if (st->single_channel)
> > +			clk_rate = DIV_ROUND_CLOSEST(clk_rate, 4);
> > +		else
> > +			clk_rate = DIV_ROUND_CLOSEST(clk_rate, 8);
> > +  
> 
> Having the sample rate depend on how many channels are enabled in
> the buffer seems a bit odd. Sampling frequency is not strictly
> defined in IIO, so I think it would be fine to always return the
> same value no matter how many channels are enabled.
> 
> We will just need to document that the sampling frequency is the
> rate per sample, not per channel. So if two channels are enabled,
> the effective sampling rate per channel is 1/2 of the sampling
> rate reported by the sysfs attribute. 

There is an oddity around this that we've never cleared up fully.

In my head at least if there is a single sampling_frequency it
applies to 'scans', not individual channel reads (so would change
with the number of channels enabled).  If there
is a per channel attribute we do have documentation:

What:		/sys/bus/iio/devices/iio:deviceX/in_voltageX_sampling_frequency
What:		/sys/bus/iio/devices/iio:deviceX/in_powerY_sampling_frequency
What:		/sys/bus/iio/devices/iio:deviceX/in_currentZ_sampling_frequency
KernelVersion:	5.20
Contact:	linux-iio@vger.kernel.org
Description:
		Some devices have separate controls of sampling frequency for
		individual channels. If multiple channels are enabled in a scan,
		then the sampling_frequency of the scan may be computed from the
		per channel sampling frequencies.

For many devices the sampling frequency isn't down to each sample taking
N microsecs and them running back to back, it is instead a function of
a periodic sampling start for samples that take the same time whatever
the sampling frequency.  Also for simultaneous sampling ADCs it is never
channel dependent.

So I think if you want to avoid the confusion, make your device fall into
the description above and provide a per channel attribute rather
than shared_by_all.

Or keep it as things stand and have it halve when you double the channels.


> 
> > +		*val = clk_rate;
> > +
> > +		return IIO_VAL_INT;
> > +	}

...

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 7/9] iio: dac: ad3552r: extract common code (no changes in behavior intended)
  2024-09-05 15:17 ` [PATCH v2 7/9] iio: dac: ad3552r: extract common code (no changes in behavior intended) Angelo Dureghello
  2024-09-08 15:42   ` Jonathan Cameron
@ 2024-09-08 15:53   ` Christophe JAILLET
  1 sibling, 0 replies; 63+ messages in thread
From: Christophe JAILLET @ 2024-09-08 15:53 UTC (permalink / raw)
  To: adureghello
  Cc: Michael.Hennerich, conor+dt, devicetree, dlechner, jic23, krzk+dt,
	lars, linux-iio, linux-kernel, nuno.sa, olivier.moysan, robh

Le 05/09/2024 à 17:17, Angelo Dureghello a écrit :
> From: Angelo Dureghello <adureghello-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> 
> Extracting common code, to share common code to be used later
> by the AXI driver version (ad3552r-axi.c).

...

> +#include "ad3552r.h"
> +
> +static const s32 ad3552r_ch_ranges[][2] = {
> +	[AD3552R_CH_OUTPUT_RANGE_0__2P5V]	= {0, 2500},

Maybe add some spaces around { }?

> +	[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}
> +};

...

> +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");

Missing \ in the ending \n.

CJ

> +	*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;
> +}

...



^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 8/9] iio: dac: ad3552r: add axi platform driver
  2024-09-05 15:17 ` [PATCH v2 8/9] iio: dac: ad3552r: add axi platform driver Angelo Dureghello
  2024-09-05 20:40   ` David Lechner
@ 2024-09-08 16:07   ` Jonathan Cameron
  2024-09-08 16:28   ` Christophe JAILLET
  2 siblings, 0 replies; 63+ messages in thread
From: Jonathan Cameron @ 2024-09-08 16:07 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, David Lechner

On Thu, 05 Sep 2024 17:17:38 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:

> From: Angelo Dureghello <adureghello@baylibre.com>
> 
> Add support for ad3552r-axi, where ad3552r has to be controlled
> by the custom (fpga-based) ad3552r AXI DAC IP.
> 
> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> Co-developed-by: David Lechner <dlechner@baylibre.com>
> Co-developed-by: Nuno Sá <nuno.sa@analog.com>
Comments inline.

> 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..a9311f29f45d
> --- /dev/null
> +++ b/drivers/iio/dac/ad3552r-axi.c
> @@ -0,0 +1,567 @@

> +
> +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;

If it is another postive value I think you want to return -EINVAL
If it's negative return err as here.

> +
> +		/*
> +		 * 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_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);


	return axi3552r_qspi_update_reg_bits(st->back,
				AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
				AD3552R_MASK_CH_OUTPUT_RANGE,
				FIELD_PREP(AD3552R_MASK_CH0_RANGE, mode) |
				FIELD_PREP(AD3552R_MASK_CH1_RANGE, mode),
				1);

looks fine to me  from readability point of view and it's shorter.


> +}

> +
> +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;
> +	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;
> +
> +	err = iio_backend_bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
> +					AD3552R_SCRATCH_PAD_TEST_VAL1, 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;
> +	}
> +
> +	err = iio_backend_bus_reg_write(st->back,
> +					AD3552R_REG_ADDR_SCRATCH_PAD,
> +					AD3552R_SCRATCH_PAD_TEST_VAL2, 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;
> +	}

This scratch pad test is a separate enough 'thing' maybe pull it out as
another function called from here?


> +
> +	err = iio_backend_bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_L,
> +				       &val, 1);
> +	if (err)
> +		return err;
> +
> +	id = val;
> +
> +	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 != st->model_data->chip_id) {
> +		dev_err(st->dev, "Chip ID mismatch. Expected 0x%x, Read 0x%x\n",
> +			AD3552R_ID, id);
> +	}

no {} needed here.
Also dev_info()  to make it slightly less ominous :)


> +
> +	err = iio_backend_bus_reg_write(st->back,
> +					AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
> +					AD3552R_REF_INIT, 1);

Hmm. This was snuck in during previous patch.  Pull new definitions out of that
and put them in this patch.  I only noticed because I wondered what value it
had and was surprised to find it doesn't exist in current driver.

I'm not sure a define for write it all to 0 is worth while. Maybe just
put a zero here.

> +	if (err)
> +		return err;
> +
> +	err = iio_backend_bus_reg_write(st->back,
> +					AD3552R_REG_ADDR_TRANSFER_REGISTER,
> +					AD3552R_TRANSFER_INIT, 1);
Another define that sneaked in during previous patch.
Given it's not 'general' and only used here. I'd drop that define and
use the various parts that make it up here.

Mind you those defines should be introduced in this patch not the
previous one.


> +	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->model_data->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, &reg);

I'd return regs

> +
> +	offset = abs((s32)goffs);

Hmm. abs(goffs) should use a short I think which will work without the
cast and ultimately rely on sign extension of the result.

> +
> +	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),
> +					reg, 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),
> +					reg, 1);
> +	if (err)
> +		return dev_err_probe(st->dev, err,
> +					"Error writing register\n");
> +
> +	return 0;
> +}

...

> +
> +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),
> +	{}
{ }

Also see discussion in next patch on this. I'm not sure it makes
sense to expose this to userspace but maybe I just don't yet understand
the use case.

> +};
> +
> +#define AD3552R_CHANNEL(ch) { \
> +	.type = IIO_VOLTAGE, \
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> +	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
> +	.output = 1, \
> +	.indexed = 1, \
> +	.channel = (ch), \
> +	.scan_index = (ch), \
> +	.scan_type = { \
> +		.sign = 'u', \
> +		.realbits = 16, \
> +		.storagebits = 16, \
> +		.endianness = IIO_BE, \
> +	}, \
> +	.ext_info = ad3552r_axi_ext_info, \
> +}

> +
> +MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>");
> +MODULE_AUTHOR("Angelo Dureghello <adueghello@baylibre.com>");
> +MODULE_DESCRIPTION("AD3552R Driver - AXI IP version");

Maybe relax that description to include all potential backends.
As long as they keep to the bindings and interfaces, someone else's
completely different backend implementation should work with your
front end driver.  Mind you I can't immediately think of a better
name and module descriptions aren't ABI anyway, so maybe we don't care.


> +MODULE_LICENSE("GPL");
> 


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 8/9] iio: dac: ad3552r: add axi platform driver
  2024-09-05 15:17 ` [PATCH v2 8/9] iio: dac: ad3552r: add axi platform driver Angelo Dureghello
  2024-09-05 20:40   ` David Lechner
  2024-09-08 16:07   ` Jonathan Cameron
@ 2024-09-08 16:28   ` Christophe JAILLET
  2024-09-09 13:35     ` Nuno Sá
  2 siblings, 1 reply; 63+ messages in thread
From: Christophe JAILLET @ 2024-09-08 16:28 UTC (permalink / raw)
  To: adureghello
  Cc: Michael.Hennerich, conor+dt, devicetree, dlechner, jic23, krzk+dt,
	lars, linux-iio, linux-kernel, nuno.sa, olivier.moysan, robh

Le 05/09/2024 à 17:17, Angelo Dureghello a écrit :
> From: Angelo Dureghello <adureghello-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> 
> Add support for ad3552r-axi, where ad3552r has to be controlled
> by the custom (fpga-based) ad3552r AXI DAC IP.

...

> +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;

I don't know if it can be an issue, but iio_backend_ddr_disable() is 
called if iio_backend_ddr_enable() fails.

> +
> +	switch (*indio_dev->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;
> +
> +	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 (ext synch ability) is enabled 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_sync;
> +
> +	err = iio_backend_buffer_enable(st->back);
> +	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;
> +}

...


> +#define AD3552R_CHANNEL(ch) { \
> +	.type = IIO_VOLTAGE, \
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> +	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
> +	.output = 1, \
> +	.indexed = 1, \
> +	.channel = (ch), \
> +	.scan_index = (ch), \
> +	.scan_type = { \
> +		.sign = 'u', \
> +		.realbits = 16, \
> +		.storagebits = 16, \
> +		.endianness = IIO_BE, \
> +	}, \
> +	.ext_info = ad3552r_axi_ext_info, \
> +}
> +
> +static struct iio_chan_spec ad3552r_axi_channels[] = {

I think (but I've not checked :)) that it could be const.

CJ

> +	AD3552R_CHANNEL(0),
> +	AD3552R_CHANNEL(1),
> +};

...

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 4/9] iio: backend adi-axi-dac: add registering of child fdt node
  2024-09-08 12:36       ` Jonathan Cameron
@ 2024-09-09  7:53         ` Nuno Sá
  0 siblings, 0 replies; 63+ messages in thread
From: Nuno Sá @ 2024-09-09  7:53 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

On Sun, 2024-09-08 at 13:36 +0100, Jonathan Cameron wrote:
> On Fri, 06 Sep 2024 09:08:59 +0200
> Nuno Sá <noname.nuno@gmail.com> wrote:
> 
> > On Thu, 2024-09-05 at 14:19 -0500, David Lechner wrote:
> > > On 9/5/24 10:17 AM, Angelo Dureghello wrote:  
> > > > From: Angelo Dureghello <adureghello@baylibre.com>
> > > > 
> > > > Change to obtain the fdt use case as reported in the
> > > > adi,ad3552r.yaml file in this patchset, with the DAC device that
> > > > is actually using the backend set as a child node of the backend.
> > > > 
> > > > To obtain this, registering all the child fdt nodes as platform
> > > > devices.
> > > > 
> > > > Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
> > > > Co-developed-by: David Lechner <dlechner@baylibre.com>
> > > > Co-developed-by: Nuno Sá <nuno.sa@analog.com>
> > > > ---
> > > >  drivers/iio/dac/adi-axi-dac.c | 15 +++++++++++++++
> > > >  1 file changed, 15 insertions(+)
> > > > 
> > > > diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-
> > > > dac.c
> > > > index cc31e1dcd1df..e883cd557b6a 100644
> > > > --- a/drivers/iio/dac/adi-axi-dac.c
> > > > +++ b/drivers/iio/dac/adi-axi-dac.c
> > > > @@ -783,6 +783,7 @@ static int axi_dac_probe(struct platform_device
> > > > *pdev)
> > > >  {
> > > >  	struct axi_dac_state *st;
> > > >  	const struct axi_dac_info *info;
> > > > +	struct platform_device *child_pdev;
> > > >  	void __iomem *base;
> > > >  	unsigned int ver;
> > > >  	struct clk *clk;
> > > > @@ -862,6 +863,20 @@ static int axi_dac_probe(struct platform_device
> > > > *pdev)
> > > >  		return dev_err_probe(&pdev->dev, ret,
> > > >  				     "failed to register iio
> > > > backend\n");
> > > >  
> > > > +	device_for_each_child_node_scoped(&pdev->dev, child) {  
> > > 
> > > This should use fwnode_for_each_available_child_node() so that it skips
> > > nodes with status != "okay".
> 
> Ah. That oddity strikes again...
> 
> > > 
> > > Would be nice to introduce a scoped version of this function too.
> > > 
> > > Also, if we are allowing multiple devices on the bus, the DT bindings
> > > need to have a reg property that is unique for each child.
> > >   
> > > > +		struct platform_device_info pi;
> > > > +
> > > > +		memset(&pi, 0, sizeof(pi));  
> > > 
> > > struct platform_device_info pi = { };
> > > 
> > > avoids the need for memset().
> > >   
> > > > +
> > > > +		pi.name = fwnode_get_name(child);
> > > > +		pi.id = PLATFORM_DEVID_AUTO;
> > > > +		pi.fwnode = child;  
> > > 
> > > Need to have pi.parent = &pdev->dev;
> > > 
> > > It could also make sense to have all of the primary bus functions
> > > (reg read/write, ddr enable/disable, etc.) passed here as platform
> > > data instead of having everything go through the IIO backend.  
> > 
> > Note that ddr enable/disable is something that makes sense to be in the
> > backend
> > anyways as it is something that exists in LVDS/CMOS interfaces that are only
> > running
> > the dataplane. Bus operations like read/write could make sense but that
> > would mean an
> > interface directly between the axi-dac and the child devices (bypassing the
> > backend
> > or any other middle layer - maybe we could create a tiny adi-axi-bus layer
> > on the IIO
> > topdir or any other place in IIO) which I'm not so sure (and is a bit odd).
> > OTOH,
> > this bus stuff goes a bit out of scope of the backend main idea/goal so
> > yeah... Well,
> > let's see what others have to say about it but I don't dislike the idea.
> 
> For the read/write using platform data does seem reasonable to me.
> Agreed that DDR is dataplane (at least sometimes) so backend ops probably
> appropriate.
> 
> > 
> > >   
> > > > +
> > > > +		child_pdev = platform_device_register_full(&pi);
> > > > +		if (IS_ERR(child_pdev))
> > > > +			return PTR_ERR(child_pdev);  
> > > 
> > > These devices need to be unregistered on any error return and when
> > > the parent device is removed.
> > >   
> > 
> > Definitely this needs to be tested by manually unbinding the axi-dac device
> > for
> > example. I'm not really sure how this will look like and if there's any
> > problem in
> > removing twice the same device (likely there is). The thing is that when we
> > connect a
> > frontend with it's backend, a devlink is created (that guarantees that the
> > frontend
> > is removed before the backend). So, I'm fairly confident that if we add a
> > devm action
> > in here to unregister the child devices, by the time we unregister the
> > child, it
> > should be already gone (unless driver core somehow handles this).
> > 
> > All of the above needs careful testing but one way out it (and since in here
> > we have
> > the parent - child relationship), we could add a boolean flag 'skip_devlink'
> > to
> > 'struct iio_backend_info' so that devlinks are skipped on these
> > arrangements. Or we
> > could automatically detect that the frontend is a child of the backend and
> > skip the
> > link (though an explicit flag might be better).
> 
> Agreed it needs testing but I'm not sure why it would already have gone.
> The driver would have unbound, but the platform device /child would still be
> there
> I think at time of removal. Can probably get away with devm to tear
> it down when the backend device then goes away.
> 
> Maybe I'm missing some subtlety though.
> 

Hmm, I guess there was some confusion of me not explaining myself. What I wanted
to say is that we will be unregistering the same device twice. But yeah, maybe
it ends up just being a NOP in the driver core. But yeah, we definitely need to
test this and make sure that the device is only gone by the time the parent
device calls platform_device_unregister() on it.

- Nuno Sá


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 8/9] iio: dac: ad3552r: add axi platform driver
  2024-09-05 20:40   ` David Lechner
  2024-09-08 15:49     ` Jonathan Cameron
@ 2024-09-09  9:00     ` Nuno Sá
  1 sibling, 0 replies; 63+ messages in thread
From: Nuno Sá @ 2024-09-09  9:00 UTC (permalink / raw)
  To: David Lechner, Angelo Dureghello, Lars-Peter Clausen,
	Michael Hennerich, Nuno Sá, Jonathan Cameron, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Olivier Moysan
  Cc: linux-iio, devicetree, linux-kernel

Hi all,

Some comments on top of what David already said...

On Thu, 2024-09-05 at 15:40 -0500, David Lechner wrote:
> On 9/5/24 10:17 AM, Angelo Dureghello wrote:
> 
> ...
> 
> > +
> > +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);
> 
> This seems odd to me. How does the backend know what frequency we want?
> It would make more sense to me if this somehow indicated that we were
> getting the SPI SCLK rate.
> 

Yes, this sampling frequency bit seems very wrong atm. And the thing is, we're
not even getting SCLK. According to [1], the /4 and /8 is for clk_in which is
not the same as SCLK (unless I'm missing something). 

OTOH, if in the backend patch, that clk_get() is somehow getting sclk, that's
wrong because sclk is an output clk of the IP. So we need to get clk_in which
should be (typically) 133MHz.

> > +		if (err != IIO_VAL_INT)
> 
> Would be better to call the variable ret instead of err if it can hold
> something besides an error code.
> 
> > +			return err;
> > +
> > +		/*
> > +		 * Data stream SDR/DDR (clk_in/8 or clk_in/4 update rate).
> > +		 * Samplerate has sense in DDR only.
> 
> We should also mention that this assumes QSPI in addtion to DDR enabled.
> 

I understand the QSPI bit but why the DDR part? I just don't understand the
comment "Samplerate has sense in DDR only.". It needs way more explanation if
that is true...

> > +		 */
> > +		if (st->single_channel)
> > +			clk_rate = DIV_ROUND_CLOSEST(clk_rate, 4);
> > +		else
> > +			clk_rate = DIV_ROUND_CLOSEST(clk_rate, 8);
> > +
> 

This division also looks to be very backend dependent. So it's far from ideal
being in here...

To me, the way we need to get this done is for the backend to effectively report
back SCLK (in a correct way). Then, depending on the number of bits per clk (4
for QSPI), the word size and DDR vs SDR we get the device sample rate. With it,
we then choose one of Jonathan's suggestion (a per channel attr might be less
confusing).

All the above said, I probably need to catch up on the above. It might happen
that David and Angelo already got some more info from the hdl guys while I was
on vacation.

[1]: https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
- Nuno Sá


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-08 12:29   ` Jonathan Cameron
@ 2024-09-09 11:39     ` Angelo Dureghello
  2024-09-09 19:16       ` Jonathan Cameron
  2024-09-09 12:46     ` Conor Dooley
  1 sibling, 1 reply; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-09 11:39 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, David Lechner


On 08/09/24 2:29 PM, Jonathan Cameron wrote:
> On Thu, 05 Sep 2024 17:17:31 +0200
> Angelo Dureghello <adureghello@baylibre.com> wrote:
>
>> 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>
>>   
>>   required:
>>     - compatible
>> -  - reg
>> -  - spi-max-frequency
> Sort of feels like both reg and spi-max-frequency
> are valid things to specify.

This specific backend IP generates a fixed non-configurable clock
frequency, so i don't think the spi-max-frequency is needed.


> Maybe we have an excellent IP and dodgy wiring so want
> to clamp the frequency (long term - don't need to support
> in the driver today).
>
> Maybe we have an axi_dac IP that supports multiple
> front end devices?  So maybe just keep reg?

yes, this is what i am wondering now too, i simplified with just one
frontend node, are multimple frontends (and so reg property) needed ?


>>   
>>   additionalProperties: false
>>   
>> @@ -238,4 +254,26 @@ examples:
>>               };
>>           };
>>       };
>> +
>> +  - |
>> +    backend: axi_dac@44a70000 {
>> +        compatible = "adi,axi-dac-ad3552r";
>> +        reg = <0x44a70000 0x1000>;
>> +        dmas = <&dac_tx_dma 0>;
>> +        dma-names = "tx";
>> +        #io-backend-cells = <0>;
>> +        clocks = <&ref_clk>;
>> +        dac {
>> +            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 = <(-10000000) (10000000)>;
>> +            };
>> +        };
>> +    };
>> +
>>   ...
>>
Regards,
-- 
  ,,,      Angelo Dureghello
:: :.     BayLibre -runtime team- Developer
:`___:
  `____:


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 2/9] iio: backend: extend features
  2024-09-08 12:38   ` Jonathan Cameron
@ 2024-09-09 11:58     ` Angelo Dureghello
  0 siblings, 0 replies; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-09 11:58 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, David Lechner


On 08/09/24 2:38 PM, Jonathan Cameron wrote:
> On Thu, 05 Sep 2024 17:17:32 +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
> The RAMP_16 definition doesn't seem immediately connected to the rest.
> + I'm not sure what it is from the name.

It's a 16bit ramp that the backend is able to generate internally,
can be used for testing.

I changed the name to

IIO_BACKEND_INTERNAL_RAMP_16BIT


>
>> Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
>> ---
>>   drivers/iio/industrialio-backend.c | 157 +++++++++++++++++++++++++++++++++++++
>>   include/linux/iio/backend.h        |  33 ++++++++
>>   2 files changed, 190 insertions(+)
>>
>> diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
>> index 20b3b5212da7..231bef4b560e 100644
>> --- a/drivers/iio/industrialio-backend.c
>> +++ b/drivers/iio/industrialio-backend.c
>> @@ -718,6 +718,163 @@ static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back)
>>   	return 0;
>>   }
>> diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h
>> index 37d56914d485..eb8c5bb74bb5 100644
>> --- a/include/linux/iio/backend.h
>> +++ b/include/linux/iio/backend.h
>>   
>>   enum iio_backend_data_source {
>>   	IIO_BACKEND_INTERNAL_CONTINUOUS_WAVE,
>>   	IIO_BACKEND_EXTERNAL,
>> +	IIO_BACKEND_INTERNAL_RAMP_16,
> Not obvious what this is so maybe this enum needs docs in general.
>
>>   	IIO_BACKEND_DATA_SOURCE_MAX
>>   };

-- 
  ,,,      Angelo Dureghello
:: :.     BayLibre -runtime team- Developer
:`___:
  `____:


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-08 12:29   ` Jonathan Cameron
  2024-09-09 11:39     ` Angelo Dureghello
@ 2024-09-09 12:46     ` Conor Dooley
  2024-09-09 14:03       ` Nuno Sá
  1 sibling, 1 reply; 63+ messages in thread
From: Conor Dooley @ 2024-09-09 12:46 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
	Nuno Sá, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Olivier Moysan, linux-iio, devicetree, linux-kernel,
	David Lechner

[-- Attachment #1: Type: text/plain, Size: 2955 bytes --]

On Sun, Sep 08, 2024 at 01:29:25PM +0100, Jonathan Cameron wrote:
> On Thu, 05 Sep 2024 17:17:31 +0200
> Angelo Dureghello <adureghello@baylibre.com> wrote:
> 
> > 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>
> 
> >  
> >  required:
> >    - compatible
> > -  - reg
> > -  - spi-max-frequency
> Sort of feels like both reg and spi-max-frequency
> are valid things to specify. 
> 
> Maybe we have an excellent IP and dodgy wiring so want
> to clamp the frequency (long term - don't need to support
> in the driver today).
> 
> Maybe we have an axi_dac IP that supports multiple
> front end devices?  So maybe just keep reg?

I'd like to be convinced that this incarnation of the AXI DAC IP is not
a spi controller and that a ref to spi-controller.yaml is not out of
place here. It may not be something that you'd ever use generally, given
the "weird" interface to it, but it does seem to be one regardless.

I'd also really like to know how this fits in with spi-offloads. It
/feels/, and I'd like to reiterate the word feels, like a rather similar
idea just applied to a DAC instead of an ADC. We kinda hit a dead end
with generalising the spi-offload stuff due to lack of similar devices,
but maybe we were looking for other ADCs when instead it should have
been at all other types of IIO device?

> >  
> >  additionalProperties: false
> >  
> > @@ -238,4 +254,26 @@ examples:
> >              };
> >          };
> >      };
> > +
> > +  - |
> > +    backend: axi_dac@44a70000 {

"axi_dac":
- no underscores in node names please
- shouldn't it be "io-backend@" or something like that? Or even
  spi@? axi_dac isn't a class of device, and this device is not, AFAICT
  a DAC at all since the ad3552r is what actually does the conversion.

Cheers,
Conor.

> > +        compatible = "adi,axi-dac-ad3552r";
> > +        reg = <0x44a70000 0x1000>;
> > +        dmas = <&dac_tx_dma 0>;
> > +        dma-names = "tx";
> > +        #io-backend-cells = <0>;
> > +        clocks = <&ref_clk>;
> > +        dac {
> > +            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 = <(-10000000) (10000000)>;
> > +            };
> > +        };
> > +    };
> > +
> >  ...
> > 
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 8/9] iio: dac: ad3552r: add axi platform driver
  2024-09-08 16:28   ` Christophe JAILLET
@ 2024-09-09 13:35     ` Nuno Sá
  0 siblings, 0 replies; 63+ messages in thread
From: Nuno Sá @ 2024-09-09 13:35 UTC (permalink / raw)
  To: Christophe JAILLET, adureghello
  Cc: Michael.Hennerich, conor+dt, devicetree, dlechner, jic23, krzk+dt,
	lars, linux-iio, linux-kernel, nuno.sa, olivier.moysan, robh

On Sun, 2024-09-08 at 18:28 +0200, Christophe JAILLET wrote:
> Le 05/09/2024 à 17:17, Angelo Dureghello a écrit :
> > From: Angelo Dureghello
> > <adureghello-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
> > 
> > Add support for ad3552r-axi, where ad3552r has to be controlled
> > by the custom (fpga-based) ad3552r AXI DAC IP.
> 
> ...
> 
> > +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;
> 
> I don't know if it can be an issue, but iio_backend_ddr_disable() is 
> called if iio_backend_ddr_enable() fails.
> 
> 

I don't think it would be an issue but conceptually it does not really make
sense. Yeah, it should be fixed...

- Nuno Sá

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-09 12:46     ` Conor Dooley
@ 2024-09-09 14:03       ` Nuno Sá
  2024-09-09 16:06         ` Conor Dooley
  2024-09-09 17:19         ` David Lechner
  0 siblings, 2 replies; 63+ messages in thread
From: Nuno Sá @ 2024-09-09 14:03 UTC (permalink / raw)
  To: Conor Dooley, Jonathan Cameron
  Cc: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
	Nuno Sá, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Olivier Moysan, linux-iio, devicetree, linux-kernel,
	David Lechner

On Mon, 2024-09-09 at 13:46 +0100, Conor Dooley wrote:
> On Sun, Sep 08, 2024 at 01:29:25PM +0100, Jonathan Cameron wrote:
> > On Thu, 05 Sep 2024 17:17:31 +0200
> > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > 
> > > 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>
> > 
> > >  
> > >  required:
> > >    - compatible
> > > -  - reg
> > > -  - spi-max-frequency
> > Sort of feels like both reg and spi-max-frequency
> > are valid things to specify. 
> > 
> > Maybe we have an excellent IP and dodgy wiring so want
> > to clamp the frequency (long term - don't need to support
> > in the driver today).
> > 
> > Maybe we have an axi_dac IP that supports multiple
> > front end devices?  So maybe just keep reg?
> 
> I'd like to be convinced that this incarnation of the AXI DAC IP is not
> a spi controller and that a ref to spi-controller.yaml is not out of
> place here. It may not be something that you'd ever use generally, given
> the "weird" interface to it, but it does seem to be one regardless.
> 

Agreed.. As weird as it get's, it's acting as a spi controller.

> I'd also really like to know how this fits in with spi-offloads. It
> /feels/, and I'd like to reiterate the word feels, like a rather similar
> idea just applied to a DAC instead of an ADC.

The offload main principle is to replay a spi transfer periodically given an
input trigger. I'm not so sure we have that same principle in here. In here I
guess we stream data over the qspi interface based on SCLK which can look
similar. The difference is that this IP does not need any trigger for any spi
transfer replay (I think). 

- Nuno Sá

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-09 14:03       ` Nuno Sá
@ 2024-09-09 16:06         ` Conor Dooley
  2024-09-10  8:12           ` Nuno Sá
  2024-09-09 17:19         ` David Lechner
  1 sibling, 1 reply; 63+ messages in thread
From: Conor Dooley @ 2024-09-09 16:06 UTC (permalink / raw)
  To: Nuno Sá
  Cc: Conor Dooley, Jonathan Cameron, Angelo Dureghello,
	Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
	devicetree, linux-kernel, David Lechner

[-- Attachment #1: Type: text/plain, Size: 825 bytes --]

On Mon, Sep 09, 2024 at 04:03:17PM +0200, Nuno Sá wrote:
> On Mon, 2024-09-09 at 13:46 +0100, Conor Dooley wrote:
> > On Sun, Sep 08, 2024 at 01:29:25PM +0100, Jonathan Cameron wrote:

> > I'd also really like to know how this fits in with spi-offloads. It
> > /feels/, and I'd like to reiterate the word feels, like a rather similar
> > idea just applied to a DAC instead of an ADC.
> 
> The offload main principle is to replay a spi transfer periodically given an
> input trigger. I'm not so sure we have that same principle in here. In here I
> guess we stream data over the qspi interface based on SCLK which can look
> similar. The difference is that this IP does not need any trigger for any spi
> transfer replay (I think). 

Right, if the trigger part is what decides it for you then I'm wildin
here.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-09 14:03       ` Nuno Sá
  2024-09-09 16:06         ` Conor Dooley
@ 2024-09-09 17:19         ` David Lechner
  2024-09-09 17:38           ` David Lechner
  2024-09-10  8:16           ` Nuno Sá
  1 sibling, 2 replies; 63+ messages in thread
From: David Lechner @ 2024-09-09 17:19 UTC (permalink / raw)
  To: Nuno Sá, Conor Dooley, Jonathan Cameron
  Cc: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
	Nuno Sá, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Olivier Moysan, linux-iio, devicetree, linux-kernel

On 9/9/24 9:03 AM, Nuno Sá wrote:
> On Mon, 2024-09-09 at 13:46 +0100, Conor Dooley wrote:
>> On Sun, Sep 08, 2024 at 01:29:25PM +0100, Jonathan Cameron wrote:
>>> On Thu, 05 Sep 2024 17:17:31 +0200
>>> Angelo Dureghello <adureghello@baylibre.com> wrote:
>>>
>>>> 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>
>>>
>>>>  
>>>>  required:
>>>>    - compatible
>>>> -  - reg
>>>> -  - spi-max-frequency
>>> Sort of feels like both reg and spi-max-frequency
>>> are valid things to specify. 
>>>
>>> Maybe we have an excellent IP and dodgy wiring so want
>>> to clamp the frequency (long term - don't need to support
>>> in the driver today).
>>>
>>> Maybe we have an axi_dac IP that supports multiple
>>> front end devices?  So maybe just keep reg?
>>
>> I'd like to be convinced that this incarnation of the AXI DAC IP is not
>> a spi controller and that a ref to spi-controller.yaml is not out of
>> place here. It may not be something that you'd ever use generally, given
>> the "weird" interface to it, but it does seem to be one regardless.
>>
> 
> Agreed.. As weird as it get's, it's acting as a spi controller.
> 
>> I'd also really like to know how this fits in with spi-offloads. It
>> /feels/, and I'd like to reiterate the word feels, like a rather similar
>> idea just applied to a DAC instead of an ADC.
> 
> The offload main principle is to replay a spi transfer periodically given an
> input trigger. I'm not so sure we have that same principle in here. In here I
> guess we stream data over the qspi interface based on SCLK which can look
> similar. The difference is that this IP does not need any trigger for any spi
> transfer replay (I think). 
> 

Looking at the AD3552R from a SPI offload perspective of triggered SPI
messages, I think it still works.

The trigger doesn't have to be a clock/PWM. In this case, the trigger would
be whenever the IIO buffer is full and ready to send a burst of data (not
sure if this would be a hardware or software trigger - but it works either
way).

Also, the DAC_CUSTOM_CTRL::ADDRESS register field in the AXI DAC IP core
acts as an offload to record and play back a SPI write transfer.

If we were using the AXI SPI Engine, this would be one SPI message with
two xfers, one for the address write followed by one for the data write.
The size of the data write would be the size of the IIO buffer - or in
the case of a cyclic DMA, the size of the write data would be channel
data size * num channels and the xfer would have a special cyclic offload
flag set.

So I think we could make a single binding that works for the the AXI DAC
backend/offload and the AXI SPI Engine offload. (I don't think it would
be so easy to integrate the AXI DAC into the SPI framework on the driver
side - and hopefully we won't have to, but the DT still could use the
proposed SPI offload bindings.)

    axi_dac: spi@44a70000 {
        compatible = "adi,axi-ad3225r";
        reg = <0x44a70000 0x1000>;
        dmas = <&dac_tx_dma_1 0>;
        dma-names = "tx";
        clocks = <&ref_clk>;
        #spi-offload-cells = <0>;

        #address-cells = <1>;
        #size-cells = <0>;

        dac@0 {
            compatible = "adi,ad3552r";
            reg = <0>;

            spi-max-frequency = <30000000>;
            spi-3-wire;
            spi-tx-bus-width = <4>;
            spi-rx-bus-width = <4>;

            reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
            spi-offloads = <&axi_dac>;

            #address-cells = <1>;
            #size-cells = <0>;

            channel@0 {
                reg = <0>;
                adi,output-range-microvolt = <(-10000000) (10000000)>;
            };
        };
    };

    axi_spi_engine: spi@44a80000 {
        compatible = "adi,axi-spi-engine-1.00.a";
        reg = <0x44a80000 0x1000>;
        dmas = <&dac_tx_dma_2 0>;
        dma-names = "offload0-tx";
        clocks = <&ref_clk>;
        #spi-offload-cells = <1>;

        #address-cells = <1>;
        #size-cells = <0>;

        dac@0 {
            compatible = "adi,ad3552r";
            reg = <0>;

            spi-max-frequency = <30000000>;
            spi-3-wire;
            spi-tx-bus-width = <4>;
            spi-rx-bus-width = <4>;

            reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
            spi-offloads = <&axi_spi_engine 0>;

            #address-cells = <1>;
            #size-cells = <0>;

            channel@0 {
                reg = <0>;
                adi,output-range-microvolt = <(-10000000) (10000000)>;
            };
        };
    };


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-09 17:19         ` David Lechner
@ 2024-09-09 17:38           ` David Lechner
  2024-09-10  8:16           ` Nuno Sá
  1 sibling, 0 replies; 63+ messages in thread
From: David Lechner @ 2024-09-09 17:38 UTC (permalink / raw)
  To: Nuno Sá, Conor Dooley, Jonathan Cameron
  Cc: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
	Nuno Sá, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Olivier Moysan, linux-iio, devicetree, linux-kernel

On 9/9/24 12:19 PM, David Lechner wrote:
> On 9/9/24 9:03 AM, Nuno Sá wrote:
>> On Mon, 2024-09-09 at 13:46 +0100, Conor Dooley wrote:
>>> On Sun, Sep 08, 2024 at 01:29:25PM +0100, Jonathan Cameron wrote:
>>>> On Thu, 05 Sep 2024 17:17:31 +0200
>>>> Angelo Dureghello <adureghello@baylibre.com> wrote:
>>>>
>>>>> 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>
>>>>
>>>>>  
>>>>>  required:
>>>>>    - compatible
>>>>> -  - reg
>>>>> -  - spi-max-frequency
>>>> Sort of feels like both reg and spi-max-frequency
>>>> are valid things to specify. 
>>>>
>>>> Maybe we have an excellent IP and dodgy wiring so want
>>>> to clamp the frequency (long term - don't need to support
>>>> in the driver today).
>>>>
>>>> Maybe we have an axi_dac IP that supports multiple
>>>> front end devices?  So maybe just keep reg?
>>>
>>> I'd like to be convinced that this incarnation of the AXI DAC IP is not
>>> a spi controller and that a ref to spi-controller.yaml is not out of
>>> place here. It may not be something that you'd ever use generally, given
>>> the "weird" interface to it, but it does seem to be one regardless.
>>>
>>
>> Agreed.. As weird as it get's, it's acting as a spi controller.
>>
>>> I'd also really like to know how this fits in with spi-offloads. It
>>> /feels/, and I'd like to reiterate the word feels, like a rather similar
>>> idea just applied to a DAC instead of an ADC.
>>
>> The offload main principle is to replay a spi transfer periodically given an
>> input trigger. I'm not so sure we have that same principle in here. In here I
>> guess we stream data over the qspi interface based on SCLK which can look
>> similar. The difference is that this IP does not need any trigger for any spi
>> transfer replay (I think). 
>>
> 
> Looking at the AD3552R from a SPI offload perspective of triggered SPI
> messages, I think it still works.
> 
> The trigger doesn't have to be a clock/PWM. In this case, the trigger would
> be whenever the IIO buffer is full and ready to send a burst of data (not
> sure if this would be a hardware or software trigger - but it works either
> way).
> 
> Also, the DAC_CUSTOM_CTRL::ADDRESS register field in the AXI DAC IP core
> acts as an offload to record and play back a SPI write transfer.
> 
> If we were using the AXI SPI Engine, this would be one SPI message with
> two xfers, one for the address write followed by one for the data write.
> The size of the data write would be the size of the IIO buffer - or in
> the case of a cyclic DMA, the size of the write data would be channel
> data size * num channels and the xfer would have a special cyclic offload
> flag set.
> 
> So I think we could make a single binding that works for the the AXI DAC
> backend/offload and the AXI SPI Engine offload. (I don't think it would
> be so easy to integrate the AXI DAC into the SPI framework on the driver
> side - and hopefully we won't have to, but the DT still could use the
> proposed SPI offload bindings.)
> 
>     axi_dac: spi@44a70000 {
>         compatible = "adi,axi-ad3225r";
>         reg = <0x44a70000 0x1000>;
>         dmas = <&dac_tx_dma_1 0>;
>         dma-names = "tx";
>         clocks = <&ref_clk>;
>         #spi-offload-cells = <0>;

One thing I forgot...

The AXI AD3552R IP core can be wired up as a loopback to pipe
data directly from some ADC instead of using DMA.

In the case of the ADC loopback, we would also have

	io-channels = <&adc1>, <&adc2>;

here in the controller.

And we would need #spi-offload-cell = <1>; to have a cell to
specify the data source.

> 
>         #address-cells = <1>;
>         #size-cells = <0>;
> 
>         dac@0 {
>             compatible = "adi,ad3552r";
>             reg = <0>;
> 
>             spi-max-frequency = <30000000>;
>             spi-3-wire;
>             spi-tx-bus-width = <4>;
>             spi-rx-bus-width = <4>;
> 
>             reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
>             spi-offloads = <&axi_dac>;

And then here I guess it would be:

	spi-offloads = <&axi_dac 0>, <&axi_dac 1>;
	spi-offload-names = "dma", "adc";

where 0 would select the DMA stream and 1 would select the ADC stream.

Or of the ADC part wasn't wired up, just:

	spi-offloads = <&axi_dac 0>;
	spi-offload-names = "dma";


> 
>             #address-cells = <1>;
>             #size-cells = <0>;
> 
>             channel@0 {
>                 reg = <0>;
>                 adi,output-range-microvolt = <(-10000000) (10000000)>;
>             };
>         };
>     };
> 
>     axi_spi_engine: spi@44a80000 {
>         compatible = "adi,axi-spi-engine-1.00.a";
>         reg = <0x44a80000 0x1000>;
>         dmas = <&dac_tx_dma_2 0>;
>         dma-names = "offload0-tx";
>         clocks = <&ref_clk>;
>         #spi-offload-cells = <1>;
> 
>         #address-cells = <1>;
>         #size-cells = <0>;
> 
>         dac@0 {
>             compatible = "adi,ad3552r";
>             reg = <0>;
> 
>             spi-max-frequency = <30000000>;
>             spi-3-wire;
>             spi-tx-bus-width = <4>;
>             spi-rx-bus-width = <4>;
> 
>             reset-gpios = <&gpio0 92 GPIO_ACTIVE_LOW>;
>             spi-offloads = <&axi_spi_engine 0>;
> 
>             #address-cells = <1>;
>             #size-cells = <0>;
> 
>             channel@0 {
>                 reg = <0>;
>                 adi,output-range-microvolt = <(-10000000) (10000000)>;
>             };
>         };
>     };
> 


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-09 11:39     ` Angelo Dureghello
@ 2024-09-09 19:16       ` Jonathan Cameron
  0 siblings, 0 replies; 63+ messages in thread
From: Jonathan Cameron @ 2024-09-09 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, David Lechner

On Mon, 9 Sep 2024 13:39:26 +0200
Angelo Dureghello <adureghello@baylibre.com> wrote:

> On 08/09/24 2:29 PM, Jonathan Cameron wrote:
> > On Thu, 05 Sep 2024 17:17:31 +0200
> > Angelo Dureghello <adureghello@baylibre.com> wrote:
> >  
> >> 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>
> >>   
> >>   required:
> >>     - compatible
> >> -  - reg
> >> -  - spi-max-frequency  
> > Sort of feels like both reg and spi-max-frequency
> > are valid things to specify.  
> 
> This specific backend IP generates a fixed non-configurable clock
> frequency, so i don't think the spi-max-frequency is needed.
Ah fair enough.
> 
> 
> > Maybe we have an excellent IP and dodgy wiring so want
> > to clamp the frequency (long term - don't need to support
> > in the driver today).
> >
> > Maybe we have an axi_dac IP that supports multiple
> > front end devices?  So maybe just keep reg?  
> 
> yes, this is what i am wondering now too, i simplified with just one
> frontend node, are multimple frontends (and so reg property) needed ?
It does little harm to have one. So I'd say keep it as required.

Detection of what is required should be based on something more
specific than reg being there or not.

Jonathan

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-09 16:06         ` Conor Dooley
@ 2024-09-10  8:12           ` Nuno Sá
  0 siblings, 0 replies; 63+ messages in thread
From: Nuno Sá @ 2024-09-10  8:12 UTC (permalink / raw)
  To: Conor Dooley
  Cc: Conor Dooley, Jonathan Cameron, Angelo Dureghello,
	Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
	devicetree, linux-kernel, David Lechner

On Mon, 2024-09-09 at 17:06 +0100, Conor Dooley wrote:
> On Mon, Sep 09, 2024 at 04:03:17PM +0200, Nuno Sá wrote:
> > On Mon, 2024-09-09 at 13:46 +0100, Conor Dooley wrote:
> > > On Sun, Sep 08, 2024 at 01:29:25PM +0100, Jonathan Cameron wrote:
> 
> > > I'd also really like to know how this fits in with spi-offloads. It
> > > /feels/, and I'd like to reiterate the word feels, like a rather similar
> > > idea just applied to a DAC instead of an ADC.
> > 
> > The offload main principle is to replay a spi transfer periodically given an
> > input trigger. I'm not so sure we have that same principle in here. In here
> > I
> > guess we stream data over the qspi interface based on SCLK which can look
> > similar. The difference is that this IP does not need any trigger for any
> > spi
> > transfer replay (I think). 
> 
> Right, if the trigger part is what decides it for you then I'm wildin
> here.

I mean, not only the trigger. These IPs (axi-dac/adc) are meant to deal with
data while in theory the spi offload principle is about replaying any spi
transfers. But yeah, the above reasoning does not make sense as a data transfer
is still a transfer.

FWIW, these IPs are inherently offload HW as their goal is really to stream data
without any SW intervention (so called HW_BUFFERING in IIO world). Just that
typically you have LVDS/CMOS data interfaces and now we have a qspi interface
and a spi-offload concept already introduced. 

So, yeah, as we want to have spi-offloads documented in the bindings, we can
also document this setup with the same bindings.

- Nuno Sá


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-09 17:19         ` David Lechner
  2024-09-09 17:38           ` David Lechner
@ 2024-09-10  8:16           ` Nuno Sá
  2024-09-11  8:45             ` Angelo Dureghello
  2024-09-11 19:28             ` Conor Dooley
  1 sibling, 2 replies; 63+ messages in thread
From: Nuno Sá @ 2024-09-10  8:16 UTC (permalink / raw)
  To: David Lechner, Conor Dooley, Jonathan Cameron
  Cc: Angelo Dureghello, Lars-Peter Clausen, Michael Hennerich,
	Nuno Sá, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Olivier Moysan, linux-iio, devicetree, linux-kernel

On Mon, 2024-09-09 at 12:19 -0500, David Lechner wrote:
> On 9/9/24 9:03 AM, Nuno Sá wrote:
> > On Mon, 2024-09-09 at 13:46 +0100, Conor Dooley wrote:
> > > On Sun, Sep 08, 2024 at 01:29:25PM +0100, Jonathan Cameron wrote:
> > > > On Thu, 05 Sep 2024 17:17:31 +0200
> > > > Angelo Dureghello <adureghello@baylibre.com> wrote:
> > > > 
> > > > > 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>
> > > > 
> > > > >  
> > > > >  required:
> > > > >    - compatible
> > > > > -  - reg
> > > > > -  - spi-max-frequency
> > > > Sort of feels like both reg and spi-max-frequency
> > > > are valid things to specify. 
> > > > 
> > > > Maybe we have an excellent IP and dodgy wiring so want
> > > > to clamp the frequency (long term - don't need to support
> > > > in the driver today).
> > > > 
> > > > Maybe we have an axi_dac IP that supports multiple
> > > > front end devices?  So maybe just keep reg?
> > > 
> > > I'd like to be convinced that this incarnation of the AXI DAC IP is not
> > > a spi controller and that a ref to spi-controller.yaml is not out of
> > > place here. It may not be something that you'd ever use generally, given
> > > the "weird" interface to it, but it does seem to be one regardless.
> > > 
> > 
> > Agreed.. As weird as it get's, it's acting as a spi controller.
> > 
> > > I'd also really like to know how this fits in with spi-offloads. It
> > > /feels/, and I'd like to reiterate the word feels, like a rather similar
> > > idea just applied to a DAC instead of an ADC.
> > 
> > The offload main principle is to replay a spi transfer periodically given an
> > input trigger. I'm not so sure we have that same principle in here. In here
> > I
> > guess we stream data over the qspi interface based on SCLK which can look
> > similar. The difference is that this IP does not need any trigger for any
> > spi
> > transfer replay (I think). 
> > 
> 
> Looking at the AD3552R from a SPI offload perspective of triggered SPI
> messages, I think it still works.
> 
> The trigger doesn't have to be a clock/PWM. In this case, the trigger would
> be whenever the IIO buffer is full and ready to send a burst of data (not
> sure if this would be a hardware or software trigger - but it works either
> way).
> 

Right... That's what we already have for DACs with HW buffering.

> Also, the DAC_CUSTOM_CTRL::ADDRESS register field in the AXI DAC IP core
> acts as an offload to record and play back a SPI write transfer.
> 
> If we were using the AXI SPI Engine, this would be one SPI message with
> two xfers, one for the address write followed by one for the data write.

Just a nipick comment. At least from the current implementation the address is
only writen once before starting to stream. So I guess we would not want to
replay that xfer for every sample.

> The size of the data write would be the size of the IIO buffer - or in
> the case of a cyclic DMA, the size of the write data would be channel
> data size * num channels and the xfer would have a special cyclic offload
> flag set.
> 
> So I think we could make a single binding that works for the the AXI DAC
> backend/offload and the AXI SPI Engine offload. (I don't think it would
> be so easy to integrate the AXI DAC into the SPI framework on the driver
> side - and hopefully we won't have to, but the DT still could use the
> proposed SPI offload bindings.)
> 

Hopefully not... 


- Nuno Sá

^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-10  8:16           ` Nuno Sá
@ 2024-09-11  8:45             ` Angelo Dureghello
  2024-09-11 19:28             ` Conor Dooley
  1 sibling, 0 replies; 63+ messages in thread
From: Angelo Dureghello @ 2024-09-11  8:45 UTC (permalink / raw)
  To: Nuno Sá, David Lechner, Conor Dooley, Jonathan Cameron
  Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
	devicetree, linux-kernel


On 10/09/24 10:16 AM, Nuno Sá wrote:
> On Mon, 2024-09-09 at 12:19 -0500, David Lechner wrote:
>> On 9/9/24 9:03 AM, Nuno Sá wrote:
>>> On Mon, 2024-09-09 at 13:46 +0100, Conor Dooley wrote:
>>>> On Sun, Sep 08, 2024 at 01:29:25PM +0100, Jonathan Cameron wrote:
>>>>> On Thu, 05 Sep 2024 17:17:31 +0200
>>>>> Angelo Dureghello <adureghello@baylibre.com> wrote:
>>>>>
>>>>>> 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>
>>>>>>   
>>>>>>   required:
>>>>>>     - compatible
>>>>>> -  - reg
>>>>>> -  - spi-max-frequency
>>>>> Sort of feels like both reg and spi-max-frequency
>>>>> are valid things to specify.
>>>>>
>>>>> Maybe we have an excellent IP and dodgy wiring so want
>>>>> to clamp the frequency (long term - don't need to support
>>>>> in the driver today).
>>>>>
>>>>> Maybe we have an axi_dac IP that supports multiple
>>>>> front end devices?  So maybe just keep reg?
>>>> I'd like to be convinced that this incarnation of the AXI DAC IP is not
>>>> a spi controller and that a ref to spi-controller.yaml is not out of
>>>> place here. It may not be something that you'd ever use generally, given
>>>> the "weird" interface to it, but it does seem to be one regardless.
>>>>
>>> Agreed.. As weird as it get's, it's acting as a spi controller.
>>>
>>>> I'd also really like to know how this fits in with spi-offloads. It
>>>> /feels/, and I'd like to reiterate the word feels, like a rather similar
>>>> idea just applied to a DAC instead of an ADC.
>>> The offload main principle is to replay a spi transfer periodically given an
>>> input trigger. I'm not so sure we have that same principle in here. In here
>>> I
>>> guess we stream data over the qspi interface based on SCLK which can look
>>> similar. The difference is that this IP does not need any trigger for any
>>> spi
>>> transfer replay (I think).
>>>
>> Looking at the AD3552R from a SPI offload perspective of triggered SPI
>> messages, I think it still works.
>>
>> The trigger doesn't have to be a clock/PWM. In this case, the trigger would
>> be whenever the IIO buffer is full and ready to send a burst of data (not
>> sure if this would be a hardware or software trigger - but it works either
>> way).
>>
> Right... That's what we already have for DACs with HW buffering.
>
>> Also, the DAC_CUSTOM_CTRL::ADDRESS register field in the AXI DAC IP core
>> acts as an offload to record and play back a SPI write transfer.
>>
>> If we were using the AXI SPI Engine, this would be one SPI message with
>> two xfers, one for the address write followed by one for the data write.
> Just a nipick comment. At least from the current implementation the address is
> only writen once before starting to stream. So I guess we would not want to
> replay that xfer for every sample.
>
>> The size of the data write would be the size of the IIO buffer - or in
>> the case of a cyclic DMA, the size of the write data would be channel
>> data size * num channels and the xfer would have a special cyclic offload
>> flag set.
>>
>> So I think we could make a single binding that works for the the AXI DAC
>> backend/offload and the AXI SPI Engine offload. (I don't think it would
>> be so easy to integrate the AXI DAC into the SPI framework on the driver
>> side - and hopefully we won't have to, but the DT still could use the
>> proposed SPI offload bindings.)
>>
> Hopefully not...

As of now, i am proposing to stay in the simpler node as possible for the
current case, like:


     axi_dac: spi@44a70000 {
         compatible = "adi,axi-ad3552r";
         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 {
             reg = <0>;
             compatible = "adi,ad3552r";
             reset-gpios = <&gpio0 92 GPIO_ACTIVE_HIGH>;
             io-backends = <&axi_dac>;

             #address-cells = <1>;
             #size-cells = <0>;

             channel@0 {
                 reg = <0>;
                 adi,output-range-microvolt = <(-10000000) (10000000)>;
             };
         };
     };


and extend things later on, in case.
SPI lines and other info are all obtained from the compatible.

What do you think ?


>
> - Nuno Sá

-- 
  ,,,      Angelo Dureghello
:: :.     BayLibre -runtime team- Developer
:`___:
  `____:


^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property
  2024-09-10  8:16           ` Nuno Sá
  2024-09-11  8:45             ` Angelo Dureghello
@ 2024-09-11 19:28             ` Conor Dooley
  1 sibling, 0 replies; 63+ messages in thread
From: Conor Dooley @ 2024-09-11 19:28 UTC (permalink / raw)
  To: Nuno Sá
  Cc: David Lechner, Conor Dooley, Jonathan Cameron, Angelo Dureghello,
	Lars-Peter Clausen, Michael Hennerich, Nuno Sá, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Olivier Moysan, linux-iio,
	devicetree, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 986 bytes --]

On Tue, Sep 10, 2024 at 10:16:24AM +0200, Nuno Sá wrote:
> On Mon, 2024-09-09 at 12:19 -0500, David Lechner wrote:

> > So I think we could make a single binding that works for the the AXI DAC
> > backend/offload and the AXI SPI Engine offload. (I don't think it would
> > be so easy to integrate the AXI DAC into the SPI framework on the driver
> > side - and hopefully we won't have to, but the DT still could use the
> > proposed SPI offload bindings.)
> > 
> 
> Hopefully not... 

Yeah, I wasn't really trying to place any expectations on how the driver
would look. My motivation in talking about offloads here was to see if
the data direct switch would help at all in trying to ensure the
spi-offloads stuff was being handled generically.

That said, I do think the current implementation binding wise is
probably capable of supporting both directions with little to no
problems, it'd mostly be the kernel's (proposed) interpretation that'd
not be up to it?


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 63+ messages in thread

end of thread, other threads:[~2024-09-11 19:28 UTC | newest]

Thread overview: 63+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-05 15:17 [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP Angelo Dureghello
2024-09-05 15:17 ` [PATCH v2 1/9] dt-bindings: iio: dac: ad3552r: add io-backend property Angelo Dureghello
2024-09-05 16:28   ` Rob Herring (Arm)
2024-09-05 19:51     ` David Lechner
2024-09-08 12:29   ` Jonathan Cameron
2024-09-09 11:39     ` Angelo Dureghello
2024-09-09 19:16       ` Jonathan Cameron
2024-09-09 12:46     ` Conor Dooley
2024-09-09 14:03       ` Nuno Sá
2024-09-09 16:06         ` Conor Dooley
2024-09-10  8:12           ` Nuno Sá
2024-09-09 17:19         ` David Lechner
2024-09-09 17:38           ` David Lechner
2024-09-10  8:16           ` Nuno Sá
2024-09-11  8:45             ` Angelo Dureghello
2024-09-11 19:28             ` Conor Dooley
2024-09-05 15:17 ` [PATCH v2 2/9] iio: backend: extend features Angelo Dureghello
2024-09-08 12:38   ` Jonathan Cameron
2024-09-09 11:58     ` Angelo Dureghello
2024-09-05 15:17 ` [PATCH v2 3/9] iio: backend adi-axi-dac: " Angelo Dureghello
2024-09-08 15:11   ` Jonathan Cameron
2024-09-08 15:40   ` Christophe JAILLET
2024-09-05 15:17 ` [PATCH v2 4/9] iio: backend adi-axi-dac: add registering of child fdt node Angelo Dureghello
2024-09-05 19:19   ` David Lechner
2024-09-06  5:42     ` Nuno Sá
2024-09-06 13:52       ` David Lechner
2024-09-06  7:08     ` Nuno Sá
2024-09-08 12:36       ` Jonathan Cameron
2024-09-09  7:53         ` Nuno Sá
2024-09-05 15:17 ` [PATCH v2 5/9] dt-bindings: iio: dac: add ad3552r axi-dac compatible Angelo Dureghello
2024-09-05 16:28   ` Rob Herring (Arm)
2024-09-05 21:08   ` David Lechner
2024-09-06  7:22   ` Krzysztof Kozlowski
2024-09-06  9:11     ` Angelo Dureghello
2024-09-06  9:37       ` Krzysztof Kozlowski
2024-09-06 11:53         ` Nuno Sá
2024-09-06 12:13           ` Krzysztof Kozlowski
2024-09-06 13:52             ` Nuno Sá
2024-09-06 14:04               ` David Lechner
2024-09-06 16:36                 ` Krzysztof Kozlowski
2024-09-06 16:42                   ` David Lechner
2024-09-06 16:44                     ` Krzysztof Kozlowski
2024-09-06 16:43               ` Krzysztof Kozlowski
2024-09-05 15:17 ` [PATCH v2 6/9] iio: dac: ad3552r: changes to use FIELD_PREP Angelo Dureghello
2024-09-05 20:59   ` David Lechner
2024-09-08 15:14   ` Jonathan Cameron
2024-09-08 15:15     ` Jonathan Cameron
2024-09-05 15:17 ` [PATCH v2 7/9] iio: dac: ad3552r: extract common code (no changes in behavior intended) Angelo Dureghello
2024-09-08 15:42   ` Jonathan Cameron
2024-09-08 15:53   ` Christophe JAILLET
2024-09-05 15:17 ` [PATCH v2 8/9] iio: dac: ad3552r: add axi platform driver Angelo Dureghello
2024-09-05 20:40   ` David Lechner
2024-09-08 15:49     ` Jonathan Cameron
2024-09-09  9:00     ` Nuno Sá
2024-09-08 16:07   ` Jonathan Cameron
2024-09-08 16:28   ` Christophe JAILLET
2024-09-09 13:35     ` Nuno Sá
2024-09-05 15:17 ` [PATCH v2 9/9] iio: ABI: add DAC sysfs synchronous_mode parameter Angelo Dureghello
2024-09-05 19:14   ` David Lechner
2024-09-08 12:26     ` Jonathan Cameron
2024-09-05 19:46 ` [PATCH v2 0/9] iio: add support for the ad3552r AXI DAC IP David Lechner
2024-09-06  9:07 ` Conor Dooley
2024-09-06  9:44   ` Angelo Dureghello

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).