drivers/iio/dac/stm32-dac.c

Source file repositories/reference/linux-study-clean/drivers/iio/dac/stm32-dac.c

File Facts

System
Linux kernel
Corpus path
drivers/iio/dac/stm32-dac.c
Extension
.c
Size
9991 bytes
Lines
405
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct stm32_dac {
	struct stm32_dac_common *common;
	struct mutex		lock;
};

static int stm32_dac_is_enabled(struct iio_dev *indio_dev, int channel)
{
	struct stm32_dac *dac = iio_priv(indio_dev);
	u32 en, val;
	int ret;

	ret = regmap_read(dac->common->regmap, STM32_DAC_CR, &val);
	if (ret < 0)
		return ret;
	if (STM32_DAC_IS_CHAN_1(channel))
		en = FIELD_GET(STM32_DAC_CR_EN1, val);
	else
		en = FIELD_GET(STM32_DAC_CR_EN2, val);

	return !!en;
}

static int stm32_dac_set_enable_state(struct iio_dev *indio_dev, int ch,
				      bool enable)
{
	struct stm32_dac *dac = iio_priv(indio_dev);
	struct device *dev = indio_dev->dev.parent;
	u32 msk = STM32_DAC_IS_CHAN_1(ch) ? STM32_DAC_CR_EN1 : STM32_DAC_CR_EN2;
	u32 en = enable ? msk : 0;
	int ret;

	/* already enabled / disabled ? */
	mutex_lock(&dac->lock);
	ret = stm32_dac_is_enabled(indio_dev, ch);
	if (ret < 0 || enable == !!ret) {
		mutex_unlock(&dac->lock);
		return ret < 0 ? ret : 0;
	}

	if (enable) {
		ret = pm_runtime_resume_and_get(dev);
		if (ret < 0) {
			mutex_unlock(&dac->lock);
			return ret;
		}
	}

	ret = regmap_update_bits(dac->common->regmap, STM32_DAC_CR, msk, en);
	mutex_unlock(&dac->lock);
	if (ret) {
		dev_err(&indio_dev->dev, "%s failed\n", str_enable_disable(en));
		if (enable)
			pm_runtime_put_autosuspend(dev);
		return ret;
	}

	/*
	 * When HFSEL is set, it is not allowed to write the DHRx register
	 * during 8 clock cycles after the ENx bit is set. It is not allowed
	 * to make software/hardware trigger during this period either.
	 */
	if (en && dac->common->hfsel)
		udelay(1);

	if (!enable)
		pm_runtime_put_autosuspend(dev);

	return 0;
}

static int stm32_dac_get_value(struct stm32_dac *dac, int channel, int *val)
{
	int ret;

	if (STM32_DAC_IS_CHAN_1(channel))
		ret = regmap_read(dac->common->regmap, STM32_DAC_DOR1, val);
	else
		ret = regmap_read(dac->common->regmap, STM32_DAC_DOR2, val);

	return ret ? ret : IIO_VAL_INT;
}

static int stm32_dac_set_value(struct stm32_dac *dac, int channel, int val)
{
	int ret;

	if (STM32_DAC_IS_CHAN_1(channel))
		ret = regmap_write(dac->common->regmap, STM32_DAC_DHR12R1, val);
	else
		ret = regmap_write(dac->common->regmap, STM32_DAC_DHR12R2, val);

Annotation

Implementation Notes