drivers/iio/dac/ad3552r.c
Source file repositories/reference/linux-study-clean/drivers/iio/dac/ad3552r.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/iio/dac/ad3552r.c- Extension
.c- Size
- 16932 bytes
- Lines
- 701
- Domain
- Driver Families
- Bucket
- drivers/iio
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/unaligned.hlinux/bitfield.hlinux/device.hlinux/iio/triggered_buffer.hlinux/iio/trigger_consumer.hlinux/iopoll.hlinux/kernel.hlinux/spi/spi.had3552r.h
Detected Declarations
struct ad3552r_descstruct reg_addr_poolfunction _ad3552r_reg_lenfunction ad3552r_transferfunction ad3552r_write_regfunction ad3552r_read_regfunction ad3552r_update_reg_fieldfunction BITfunction ad3552r_write_rawfunction ad3552r_trigger_hw_ldacfunction ad3552r_write_all_channelsfunction ad3552r_write_codesfunction ad3552r_trigger_handlerfunction ad3552r_check_scratch_padfunction ad3552r_read_reg_wrapperfunction ad3552r_resetfunction ad3552r_configure_custom_gainfunction ad3552r_configure_devicefunction device_for_each_child_node_scopedfunction ad3552r_initfunction ad3552r_probe
Annotated Snippet
struct ad3552r_desc {
const struct ad3552r_model_data *model_data;
/* Used to look the spi bus for atomic operations where needed */
struct mutex lock;
struct gpio_desc *gpio_reset;
struct gpio_desc *gpio_ldac;
struct spi_device *spi;
struct ad3552r_ch_data ch_data[AD3552R_MAX_CH];
struct iio_chan_spec channels[AD3552R_MAX_CH + 1];
unsigned long enabled_ch;
unsigned int num_ch;
};
static u8 _ad3552r_reg_len(u8 addr)
{
switch (addr) {
case AD3552R_REG_ADDR_HW_LDAC_16B:
case AD3552R_REG_ADDR_CH_SELECT_16B:
case AD3552R_REG_ADDR_SW_LDAC_16B:
case AD3552R_REG_ADDR_HW_LDAC_24B:
case AD3552R_REG_ADDR_CH_SELECT_24B:
case AD3552R_REG_ADDR_SW_LDAC_24B:
return 1;
default:
break;
}
if (addr > AD3552R_REG_ADDR_HW_LDAC_24B)
return 3;
if (addr > AD3552R_REG_ADDR_HW_LDAC_16B)
return 2;
return 1;
}
/* SPI transfer to device */
static int ad3552r_transfer(struct ad3552r_desc *dac, u8 addr, u32 len,
u8 *data, bool is_read)
{
/* Maximum transfer: Addr (1B) + 2 * (Data Reg (3B)) + SW LDAC(1B) */
u8 buf[8];
buf[0] = addr & AD3552R_ADDR_MASK;
buf[0] |= is_read ? AD3552R_READ_BIT : 0;
if (is_read)
return spi_write_then_read(dac->spi, buf, 1, data, len);
memcpy(buf + 1, data, len);
return spi_write_then_read(dac->spi, buf, len + 1, NULL, 0);
}
static int ad3552r_write_reg(struct ad3552r_desc *dac, u8 addr, u16 val)
{
u8 reg_len;
u8 buf[AD3552R_MAX_REG_SIZE] = { 0 };
reg_len = _ad3552r_reg_len(addr);
if (reg_len == 2)
/* Only DAC register are 2 bytes wide */
val &= AD3552R_MASK_DAC_12B;
if (reg_len == 1)
buf[0] = val & 0xFF;
else
/* reg_len can be 2 or 3, but 3rd bytes needs to be set to 0 */
put_unaligned_be16(val, buf);
return ad3552r_transfer(dac, addr, reg_len, buf, false);
}
static int ad3552r_read_reg(struct ad3552r_desc *dac, u8 addr, u16 *val)
{
int err;
u8 reg_len, buf[AD3552R_MAX_REG_SIZE] = { 0 };
reg_len = _ad3552r_reg_len(addr);
err = ad3552r_transfer(dac, addr, reg_len, buf, true);
if (err)
return err;
if (reg_len == 1)
*val = buf[0];
else
/* reg_len can be 2 or 3, but only first 2 bytes are relevant */
*val = get_unaligned_be16(buf);
return 0;
}
/* Update field of a register, shift val if needed */
static int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask,
Annotation
- Immediate include surface: `linux/unaligned.h`, `linux/bitfield.h`, `linux/device.h`, `linux/iio/triggered_buffer.h`, `linux/iio/trigger_consumer.h`, `linux/iopoll.h`, `linux/kernel.h`, `linux/spi/spi.h`.
- Detected declarations: `struct ad3552r_desc`, `struct reg_addr_pool`, `function _ad3552r_reg_len`, `function ad3552r_transfer`, `function ad3552r_write_reg`, `function ad3552r_read_reg`, `function ad3552r_update_reg_field`, `function BIT`, `function ad3552r_write_raw`, `function ad3552r_trigger_hw_ldac`.
- Atlas domain: Driver Families / drivers/iio.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.