On Thu, 2024-09-05 at 13:58 +0200, Angelo Dureghello wrote: > Hi, > > On 05/09/24 12:49 PM, Nuno Sá wrote: > > On Tue, 2024-09-03 at 20:16 +0100, Jonathan Cameron wrote: > > > On Mon, 2 Sep 2024 18:04:51 +0200 > > > Angelo Dureghello <adureghello@xxxxxxxxxxxx> wrote: > > > > > > > On 31/08/24 1:34 PM, Jonathan Cameron wrote: > > > > > On Thu, 29 Aug 2024 14:32:01 +0200 > > > > > Angelo Dureghello <adureghello@xxxxxxxxxxxx> wrote: > > > > > > > > > > > From: Angelo Dureghello <adureghello@xxxxxxxxxxxx> > > > > > > > > > > > > Extend DAC backend with new features required for the AXI driver > > > > > > version for the a3552r DAC. > > > > > > > > > > > > Signed-off-by: Angelo Dureghello <adureghello@xxxxxxxxxxxx> > > > > > Hi Angelo > > > > > Minor comments inline. > > > > > > > > > > > > static int axi_dac_enable(struct iio_backend *back) > > > > > > @@ -460,7 +493,13 @@ static int axi_dac_data_source_set(struct > > > > > > iio_backend *back, unsigned int chan, > > > > > > case IIO_BACKEND_EXTERNAL: > > > > > > return regmap_update_bits(st->regmap, > > > > > > > > > > > > AXI_DAC_REG_CHAN_CNTRL_7(chan), > > > > > > - AXI_DAC_DATA_SEL, > > > > > > AXI_DAC_DATA_DMA); > > > > > > + AXI_DAC_DATA_SEL, > > > > > > + AXI_DAC_DATA_DMA); > > > > > Unrelated change. If you want to change this, separate patch. > > > > Thanks, fixed. > > > > > > > > > > > + case IIO_BACKEND_INTERNAL_RAMP_16: > > > > > > + return regmap_update_bits(st->regmap, > > > > > > + > > > > > > AXI_DAC_REG_CHAN_CNTRL_7(chan), > > > > > > + AXI_DAC_DATA_SEL, > > > > > > + > > > > > > AXI_DAC_DATA_INTERNAL_RAMP_16); > > > > > > default: > > > > > > return -EINVAL; > > > > > > } > > > > > > @@ -518,9 +557,204 @@ static int axi_dac_reg_access(struct iio_backend > > > > > > *back, unsigned int reg, > > > > > > return regmap_write(st->regmap, reg, writeval); > > > > > > } > > > > > > > > > > > > + > > > > > > +static int axi_dac_bus_reg_write(struct iio_backend *back, > > > > > > + u32 reg, void *val, size_t size) > > > > > Maybe just pass an unsigned int for val? > > > > > So follow what regmap does? You will still need the size, but it > > > > > will just be configuration related rather than affecting the type > > > > > of val. > > > > > > > > > void * was used since data size in the future may vary depending > > > > on the bus physical interface. > > > > > > > I doubt it will get bigger than u64. Passing void * is always > > > nasty if we can do something else and this is a register writing > > > operation. I'm yet to meet an ADC or similar with > 64 bit registers > > > (or even one with 64 bit ones!) > > I think the original thinking was to support thinks like appending crc to the > > register read/write. But even in that case, u32 for val might be enough. Not > > sure. Anyways, as you often say with the backend stuff, this is all in the > > kernel so I guess we can change it to unsigned int and change it in the future > > if we need to. > > > > Since you mentioned regmap, I also want to bring something that was discussed > > before the RFC. Basically we talked about having the backend registering it's > > own regmap_bus. Then we would either: > > > > 1) Have a specific get_regmap_bus() callback for the frontend to initialize a > > regmap on; > > 2) Pass this bus into the core and have a new frontend API like > > devm_iio_backend_regmap_init(). > > > > Then, on top of the API already provided by regmap (like _update_bit()), the > > frontend could just use regmap independent of having a backend or not. > > > > The current API is likely more generic but tbh (and David and Angelo are aware > > of it) my preferred approach it to use the regmap_bus stuff. I just don't feel > > that strong about it :) > > > > > > Actually, a reg bus write involves several AXI regmap operations. > > > > > > > > > > > +{ > > > > > > + struct axi_dac_state *st = iio_backend_get_priv(back); > > > > > > + > > > > > > + if (!st->bus_type) > > > > > > + return -EOPNOTSUPP; > > > > > > + > > > > > > + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) { > > > > > As below, I'd use a switch and factor out this block as a separate > > > > > bus specific function. > > > > Ok, changed. > > > > > > > > > > > + int ret; > > > > > > + u32 ival; > > > > > > + > > > > > > + if (size != 1 && size != 2) > > > > > > + return -EINVAL; > > > > > > + > > > > > > + switch (size) { > > > > > > + case 1: > > > > > > + ival = FIELD_PREP(AXI_DAC_DATA_WR_8, *(u8 > > > > > > *)val); > > > > > > + break; > > > > > > + case 2: > > > > > > + ival = FIELD_PREP(AXI_DAC_DATA_WR_16, *(u16 > > > > > > *)val); > > > > > > + break; > > > > > > + default: > > > > > > + return -EINVAL; > > > > > Hopefully compiler won't need this and the above. I'd drop the size != 1.. > > > > > check in favour of just doing it in this switch. > > > > > > > > > sure, done. > > > > > > > > > > > > > > + } > > > > > > + > > > > > > + ret = regmap_write(st->regmap, AXI_DAC_CNTRL_DATA_WR, > > > > > > ival); > > > > > > + if (ret) > > > > > > + return ret; > > > > > > + > > > > > > + /* > > > > > > + * Both REG_CNTRL_2 and AXI_DAC_CNTRL_DATA_WR need to > > > > > > know > > > > > > + * the data size. So keeping data size control here > > > > > > only, > > > > > > + * since data size is mandatory for to the current > > > > > > transfer. > > > > > > + * DDR state handled separately by specific backend > > > > > > calls, > > > > > > + * generally all raw register writes are SDR. > > > > > > + */ > > > > > > + if (size == 1) > > > > > > + ret = regmap_set_bits(st->regmap, > > > > > > AXI_DAC_REG_CNTRL_2, > > > > > > + AXI_DAC_SYMB_8B); > > > > > > + else > > > > > > + ret = regmap_clear_bits(st->regmap, > > > > > > AXI_DAC_REG_CNTRL_2, > > > > > > + AXI_DAC_SYMB_8B); > > > > > > + if (ret) > > > > > > + return ret; > > > > > > + > > > > > > + ret = regmap_update_bits(st->regmap, > > > > > > AXI_DAC_REG_CUSTOM_CTRL, > > > > > > + AXI_DAC_ADDRESS, > > > > > > + FIELD_PREP(AXI_DAC_ADDRESS, > > > > > > reg)); > > > > > > + if (ret) > > > > > > + return ret; > > > > > > + > > > > > > + ret = regmap_update_bits(st->regmap, > > > > > > AXI_DAC_REG_CUSTOM_CTRL, > > > > > > + AXI_DAC_TRANSFER_DATA, > > > > > > + AXI_DAC_TRANSFER_DATA); > > > > > > + if (ret) > > > > > > + return ret; > > > > > > + > > > > > > + ret = regmap_read_poll_timeout(st->regmap, > > > > > > + AXI_DAC_REG_CUSTOM_CTRL, > > > > > > ival, > > > > > > + ival & > > > > > > AXI_DAC_TRANSFER_DATA, > > > > > > + 10, 100 * KILO); > > > > > > + if (ret) > > > > > > + return ret; > > > > > > + > > > > > > + return regmap_clear_bits(st->regmap, > > > > > > AXI_DAC_REG_CUSTOM_CTRL, > > > > > > + AXI_DAC_TRANSFER_DATA); > > > > > > + } > > > > > > + > > > > > > + return -EINVAL; > > > > > > +} > > > > > > + > > > > > > +static int axi_dac_bus_reg_read(struct iio_backend *back, > > > > > > + u32 reg, void *val, size_t size) > > > > > As for write, I'd just use an unsigned int * for val like > > > > > regmap does. > > > > Ok, so initial choice was unsigned int, further thinking of > > > > possible future busses drive the choice to void *. > > > > > > > > Let me know, i can switch to unsigned int in case. > > > I would just go with unsigned int or at a push u64 * > > > > > > > > > > > > > > > > > > +{ > > > > > > + struct axi_dac_state *st = iio_backend_get_priv(back); > > > > > > + > > > > > > + if (!st->bus_type) > > > > > > + return -EOPNOTSUPP; > > > > > > + > > > > > > + if (st->bus_type == AXI_DAC_BUS_TYPE_QSPI) { > > > > > It got mentioned in binding review but if this isn't QSPI, even > > > > > if similar don't call it that. > > > > It's a bit difficult to find a different name, physically, > > > > it is a QSPI, 4 lanes + clock + cs, and datasheet is naming it Quad SPI. > > > > But looking the data protocol, it's a bit different. > > > is QSPI actually defined anywhere? I assumed it would be like > > > SPI for which everything is so flexible you can build whatever you like. > > > > > > > QSPI has instruction, address and data. > > > > Here we have just ADDR and DATA. > > > > > > I'm not sure the instruction is really relevant for this. From a quick look, it > > feels like something used for accessing external flash memory like spi-nors. So, > > I would not be surprised if things are just like Jonathan said and this is just > > flexible as spi (being that extra instruction field a protocol defined for flash > > memory - where one typically sees this interface) > > Ok, so QSPI is the hardware, and the protocol on it may vary for the target > chip/application. > > Looks like DDR makes the 33MUPS rate reachable, and not all the controllers > have DDR mode. Also some controllers are supposed to work with a QSPI flash > (so with instructions), and likely this reason driven the need to use a > custom IP. > I do understand the custom IP, I just don't understand why not using the spi_engine IP. Indeed maybe because of DDR (as that is already supported on axi-dac). - Nuno Sá