On Sat, 2020-04-25 at 13:42 +0200, Mateusz Holenko wrote: > From: Pawel Czarnecki <pczarnecki@xxxxxxxxxxxxxxxxxxxxxxxx> > > This commit adds driver for the FPGA-based LiteX SoC > Controller from LiteX SoC builder. Sorry for jumping in late, Joel only just pointed me to this :) > + * The purpose of `litex_set_reg`/`litex_get_reg` is to implement > + * the logic of writing to/reading from the LiteX CSR in a single > + * place that can be then reused by all LiteX drivers. > + */ > +void litex_set_reg(void __iomem *reg, unsigned long reg_size, > + unsigned long val) > +{ > + unsigned long shifted_data, shift, i; > + unsigned long flags; > + > + spin_lock_irqsave(&csr_lock, flags); > + > + for (i = 0; i < reg_size; ++i) { > + shift = ((reg_size - i - 1) * LITEX_SUBREG_SIZE_BIT); > + shifted_data = val >> shift; > + > + __raw_writel(shifted_data, reg + (LITEX_REG_SIZE * i)); > + } > + > + spin_unlock_irqrestore(&csr_lock, flags); > +} > + > +unsigned long litex_get_reg(void __iomem *reg, unsigned long reg_size) > +{ > + unsigned long shifted_data, shift, i; > + unsigned long result = 0; > + unsigned long flags; > + > + spin_lock_irqsave(&csr_lock, flags); > + > + for (i = 0; i < reg_size; ++i) { > + shifted_data = __raw_readl(reg + (LITEX_REG_SIZE * i)); > + > + shift = ((reg_size - i - 1) * LITEX_SUBREG_SIZE_BIT); > + result |= (shifted_data << shift); > + } > + > + spin_unlock_irqrestore(&csr_lock, flags); > + > + return result; > +} I really don't like the fact that the register sizes & sub sizes are #defined. As your comment explains, this makes it harder to support other configurations. This geometry should come from the device-tree instead. Also this while thing is rather gross (and the lock will not help performance). Why can't CSRs be normally memory mapped always instead ? Even when transporting them on a HW bus that's smaller, the HW bus conversion should be able to do the break-down into a multi-breat transfer rather than doing that in SW. Or at least have a fast-path if the register size is no larger than the sub size, so you can use a normal ioread32/iowrite32. Also I wonder ... last I played with LiteX, it would re-generate the register layout (including the bit layout inside registers potentially) rather enthousiastically, making it pretty hard to have a fixed register layout for use by a kernel driver. Was this addressed ? Cheers, Ben.