From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 85347CD6E5F for ; Sun, 31 May 2026 15:26:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Cc:To:In-Reply-To:References :Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=vbLPyTAr/7pOES4+QYKflXQW79LkqiEBBw61edcaLvY=; b=qlxerkOVUHO/VaDf1ThxhdOGvx ATEc35pAELFK7m4b1mVdL4XuHOEpYoCSJ3kNWdu7V5URInG4MtN56wIlHvDmSjNNBYCJYlD6kooHM G+u79PeD7Dj5RLJv4idWvYghZ1Vaz3WOO4OtnzDuxob4iWW8E443NquVQPfEdrbFBUjmmurC8F2kf cPOZbn1xyCQIOH+pSaeI87V/yZd56GSFcXQX2mh5yB9MjWbF/BOZl/d6oX1yyel5dfr16WvqlJX3o BVZbMioGAZ1VUKgQaGy/S23H5sjnL38t1TdhFRbrQzI+uGDLw25auCEbdXdzkA23LVJ8zeIx7nSSj RGElchug==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wTi3q-00000009h72-38GR; Sun, 31 May 2026 15:26:46 +0000 Received: from mail-wr1-x433.google.com ([2a00:1450:4864:20::433]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wTi3H-00000009ghk-2Q1o for linux-arm-kernel@lists.infradead.org; Sun, 31 May 2026 15:26:13 +0000 Received: by mail-wr1-x433.google.com with SMTP id ffacd0b85a97d-45eeba68948so2453826f8f.1 for ; Sun, 31 May 2026 08:26:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre.com; s=google; t=1780241170; x=1780845970; darn=lists.infradead.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=vbLPyTAr/7pOES4+QYKflXQW79LkqiEBBw61edcaLvY=; b=TioreP8o+ZbNm7kxCRIbb0pcnJ6EPT6R78vpzkvmaE8JEYVCaabJ8Q6eV/ZjlB0+9g PeYUisYt8y+8+dy64KaT31fFKcucgp7HEJcf9yh/KfDvGhHy/P6cEQEJToLr4n4/uPgm bw/wwWVhTSUWKaW5aKsGR3ZjWBbzOLMPuWem26eZ7ElIPrYwVkkfVfmGngWZBfcAUoOV koNSQTLFVusCkbKducZOTFsug0NFt824TDTgX8Xsk428P1UTrMCsVtkR0RuZMQKci9I6 23ZTqp8L+lg5haTtLa6efnuJD26yldJpHEzy/8Qnao4BWH4Q0MjBSJlEX0ehiFqgt7+M J7Wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780241170; x=1780845970; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=vbLPyTAr/7pOES4+QYKflXQW79LkqiEBBw61edcaLvY=; b=U2DExTAKrm8jGgiix1MEAHjcLgE6TpKadA/2iFpucUcgRLb9Eg2tLOmRyUT7l+SyYN 45FYrehmYVWtxtKh23C1ZQYWJLpKXsfl8W5+nd9KbRMXwfca9dfPkgLtcyxFoEYiB4Tb TDfCY6fxowX6jrxCK6m3Reqm2eqYqZHWuZDO0vpw24RPrKof+f1B0ukZkjMinBGIXM5J KRoVU5rWz0dNiW3YcuxOqVlPHC2qf7wgeN7hcxrwedi2l1yTqEg1As+r8+tjaMVDm4Wg jQAWyBoR1tlCeJUVDwVTT06DAPsGhje34xqJ3R2FDLVx76nRZqtZGSUoNDLmMnlEN06i erEg== X-Forwarded-Encrypted: i=1; AFNElJ8aWA6qy05U82lbSRKpNsqu9lhY73T01CnUWSB+RziIXdC2OW5gNHu2042mrXqOU2A2Tgzwnk1CNLl0K1yQEpuU@lists.infradead.org X-Gm-Message-State: AOJu0Yy1wu1wQKSQnmTMPrLQCdRBV/w+bdjbH1Z6+ZEJlfL+MMk1xmme 97M51+BahdZRJdd6HlM9o2AAiXWUYDG9yiFywAbley0cgmsojQi/vInsWCkMe2o0F4w= X-Gm-Gg: Acq92OGe0P487aF4tUlsdkQBeQAVZqJs5KZxhS0D5SC4tMKhg0Lm6fj9J3UvjAKFLgP sq1Bm6dyj+iC/pTa42aEovaq+Uts8LJKO+xP9iFRx7cXL3HRdMRbvjHPBtE7s4Hg4mTOi49X3lq 5J8tkRivItZRcwEg8j6wLc4FvXbBFhq81DJkwrWYb8Q5eunRpl27+BU2g99UHXDhPyMMprsMKmh VqEq5BPVVmwhJPpufKQoNaM5T4tys4AKMTWkb3M36c1gSSv9CTz+BnH5opnIU2xNaAaEMYw95PD BCjdQhUA3B09z91x3esqfLfPNzXrvt43yxBXLtFy7mZIkcbYVPm+mbHXnwexciaFK7Q7GVEXLIu e1/DJ12UTVMHX/rnn9bvU/iKX/54NVQ1I6Ho0B2VbFNA3it1zuuU2IPJZtSUzFiqXgo977WqlFR FA3GYHsok8udHU0R6SR9kVyeXjyTzDG8JkMiyDF56CDQ== X-Received: by 2002:a05:6000:e11:b0:45e:73b3:8118 with SMTP id ffacd0b85a97d-45ef6b79fa7mr8922789f8f.29.1780241169883; Sun, 31 May 2026 08:26:09 -0700 (PDT) Received: from [192.168.0.2] ([2a07:7e81:7daa:0:202:c9ff:fe53:eda4]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-45ef354cf0dsm18526622f8f.17.2026.05.31.08.26.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 31 May 2026 08:26:09 -0700 (PDT) From: Angelo Dureghello X-Google-Original-From: Angelo Dureghello Date: Sun, 31 May 2026 17:26:04 +0200 Subject: [PATCH v4 11/11] iio: dac: add mcf54415 DAC MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260531-wip-stmark2-dac-v4-11-7e65ab4215dd@baylibre.com> References: <20260531-wip-stmark2-dac-v4-0-7e65ab4215dd@baylibre.com> In-Reply-To: <20260531-wip-stmark2-dac-v4-0-7e65ab4215dd@baylibre.com> To: Greg Ungerer , Geert Uytterhoeven , Steven King , Arnd Bergmann , Maxime Coquelin , Alexandre Torgue , Jonathan Cameron , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: Greg Ungerer , linux-m68k@lists.linux-m68k.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, linux-iio@vger.kernel.org, Angelo Dureghello X-Mailer: b4 0.15.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260531_082611_687415_B30C4939 X-CRM114-Status: GOOD ( 27.65 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Angelo Dureghello Add basic version of mcf54415 DAC driver. DAC is embedded in the cpu and DAC configuration registers are mapped in the internal IO address space. The DAC accepts a 12-bit digital signal and creates a monotonic 12-bit analog output varying from DAC_VREFL to DAC_VREFH. The DAC module consists of a conversion unit, an output amplifier, and the associated digital control blocks. Default register values for DAC_VREFL and DAC_VREFH are respectively 0 and 0xfff, left untouched in this initial version. This initial version of the driver is minimalistic, "output raw" only, to be extended in the future. DMA and external sync are disabled, default mode is high speed, default format is right-justified 12bit on 16bit word. Signed-off-by: Angelo Dureghello --- Changes in v2: - remove tests from commit message, moved to patch 0 - remove additional blank lines - remove dead code and unused definitions - use regmap - add limit check on raw write - non functional style fixes - add COMPILE_TEST to Kconfig Changes in v3: - add comments where needed - code style changes - remove unneeded variables - use regmap_set_bits where possible - remove macro not needed to define a single channel - set up regmap to big_endian accesses for next patches that will come, that will adjust ColdFire readx/writex as standard LE (links in 0/x). - add return value check on regmap calls - sashiko: remove unneeded .io_port from regmap init. - sashiko: add select REGMAP_MMIO in Kconfig Changes in v4: - remove unused includes - sashiko: return "ret" as regmap_read ret value in case of error - sashiko: using u32 as regmap_read value - use local variable in mcf54415_dac_init() for better readability - sashiko: check mcf54415_dac_init return value also in resume() --- drivers/iio/dac/Kconfig | 11 +++ drivers/iio/dac/Makefile | 1 + drivers/iio/dac/mcf54415_dac.c | 211 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+) diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index cd4870b65415..b1a578076188 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -516,6 +516,17 @@ config MAX5821 Say yes here to build support for Maxim MAX5821 10 bits DAC. +config MCF54415_DAC + tristate "NXP MCF54415 DAC driver" + depends on M5441x || COMPILE_TEST + select REGMAP_MMIO + help + Say yes here to build support for NXP MCF54415 + 12bit DAC. + + To compile this driver as a module, choose M here: the module + will be called mcf54415_dac. + config MCP4725 tristate "MCP4725/6 DAC driver" depends on I2C diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 2a80bbf4e80a..1cb93e83d0eb 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_MAX517) += max517.o obj-$(CONFIG_MAX22007) += max22007.o obj-$(CONFIG_MAX5522) += max5522.o obj-$(CONFIG_MAX5821) += max5821.o +obj-$(CONFIG_MCF54415_DAC) += mcf54415_dac.o obj-$(CONFIG_MCP4725) += mcp4725.o obj-$(CONFIG_MCP4728) += mcp4728.o obj-$(CONFIG_MCP47FEB02) += mcp47feb02.o diff --git a/drivers/iio/dac/mcf54415_dac.c b/drivers/iio/dac/mcf54415_dac.c new file mode 100644 index 000000000000..474a2c327fcd --- /dev/null +++ b/drivers/iio/dac/mcf54415_dac.c @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * NXP mcf54415 DAC driver + * + * Copyright 2026 BayLibre - adureghello@baylibre.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MCF54415_DAC_CR 0x00 +#define MCF54415_DAC_CR_PDN BIT(0) +#define MCF54415_DAC_CR_HSLS BIT(6) +#define MCF54415_DAC_CR_WMLVL GENMASK(9, 8) +#define MCF54415_DAC_CR_FILT BIT(12) + +#define MCF54415_DAC_DATA 0x02 + +struct mcf54415_dac { + struct regmap *map; + struct clk *clk; +}; + +static const struct regmap_config mcf54415_dac_regmap_config = { + .reg_bits = 16, + .reg_stride = 2, + .val_bits = 16, + .max_register = 0x0c, /* DACX_FILTCNT, R.M. Table 30-2 */ + .val_format_endian = REGMAP_ENDIAN_BIG, + .reg_format_endian = REGMAP_ENDIAN_BIG, +}; + +static int mcf54415_dac_init(struct mcf54415_dac *info) +{ + int ret; + u16 val = MCF54415_DAC_CR_FILT | FIELD_PREP(MCF54415_DAC_CR_WMLVL, 1); + + /* Fixed defaults and enable DAC (bit 0 set to 0) */ + ret = regmap_write(info->map, MCF54415_DAC_CR, val); + if (ret) + return ret; + + /* DAC is ready after 12us, from RM table 40-3 */ + fsleep(12); + + return 0; +} + +static void mcf54415_dac_exit(void *data) +{ + struct mcf54415_dac *info = data; + + regmap_set_bits(info->map, MCF54415_DAC_CR, MCF54415_DAC_CR_PDN); +} + +static const struct iio_chan_spec mcf54415_dac_iio_channel = { + .type = IIO_VOLTAGE, + .output = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), +}; + +static int mcf54415_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct mcf54415_dac *info = iio_priv(indio_dev); + int ret; + u32 reg; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = regmap_read(info->map, MCF54415_DAC_DATA, ®); + if (ret) + return ret; + *val = (int)reg & 0xfff; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + /* Reference voltage as per ColdFire datasheet is 3.3V */ + *val = 3300 /* mV */; + *val2 = 12; + return IIO_VAL_FRACTIONAL_LOG2; + default: + return -EINVAL; + } +} + +static int mcf54415_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct mcf54415_dac *info = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + /* Check based on RM 30.3.2 (DACn_DATA) reg. resolution */ + if (val < 0 || val > 4095) + return -EINVAL; + return regmap_write(info->map, MCF54415_DAC_DATA, val); + default: + return -EINVAL; + } +} + +static const struct iio_info mcf54415_dac_iio_info = { + .read_raw = &mcf54415_read_raw, + .write_raw = &mcf54415_write_raw, +}; + +static int mcf54415_dac_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct iio_dev *indio_dev; + struct mcf54415_dac *info; + void __iomem *regs; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*info)); + if (!indio_dev) + return -ENOMEM; + + info = iio_priv(indio_dev); + + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return dev_err_probe(dev, PTR_ERR(regs), + "failed to get io regs\n"); + + info->map = devm_regmap_init_mmio(dev, regs, + &mcf54415_dac_regmap_config); + if (IS_ERR(info->map)) + return PTR_ERR(info->map); + + info->clk = devm_clk_get_enabled(dev, "dac"); + if (IS_ERR(info->clk)) + return dev_err_probe(dev, PTR_ERR(info->clk), + "failed getting clock\n"); + + platform_set_drvdata(pdev, indio_dev); + + indio_dev->name = "mcf54415"; + indio_dev->info = &mcf54415_dac_iio_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = &mcf54415_dac_iio_channel; + indio_dev->num_channels = 1; + + ret = mcf54415_dac_init(info); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, mcf54415_dac_exit, info); + if (ret) + return ret; + + return devm_iio_device_register(dev, indio_dev); +} + +static int mcf54415_dac_suspend(struct device *dev) +{ + struct mcf54415_dac *info = iio_priv(dev_get_drvdata(dev)); + + mcf54415_dac_exit(info); + clk_disable_unprepare(info->clk); + + return 0; +} + +static int mcf54415_dac_resume(struct device *dev) +{ + struct mcf54415_dac *info = iio_priv(dev_get_drvdata(dev)); + int ret; + + ret = clk_prepare_enable(info->clk); + if (ret) + return ret; + + ret = mcf54415_dac_init(info); + if (ret) { + dev_err(dev, "could not resume device\n"); + return ret; + } + + return 0; + +} + +static DEFINE_SIMPLE_DEV_PM_OPS(mcf54415_dac_pm_ops, + mcf54415_dac_suspend, mcf54415_dac_resume); + +static struct platform_driver mcf54415_dac_driver = { + .probe = mcf54415_dac_probe, + .driver = { + .name = "mcf54415_dac", + .pm = pm_sleep_ptr(&mcf54415_dac_pm_ops), + }, +}; +module_platform_driver(mcf54415_dac_driver); + +MODULE_AUTHOR("Angelo Dureghello "); +MODULE_DESCRIPTION("NXP MCF54415 DAC driver"); +MODULE_LICENSE("GPL"); -- 2.54.0