1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * NXP mcf54415 DAC driver 4 * 5 * Copyright 2026 BayLibre - adureghello@baylibre.com 6 */ 7 8 #include <linux/bitfield.h> 9 #include <linux/bits.h> 10 #include <linux/clk.h> 11 #include <linux/delay.h> 12 #include <linux/err.h> 13 #include <linux/mod_devicetable.h> 14 #include <linux/module.h> 15 #include <linux/platform_device.h> 16 #include <linux/regmap.h> 17 #include <linux/types.h> 18 19 #include <linux/iio/iio.h> 20 21 #define MCF54415_DAC_CR 0x00 22 #define MCF54415_DAC_CR_PDN BIT(0) 23 #define MCF54415_DAC_CR_HSLS BIT(6) 24 #define MCF54415_DAC_CR_WMLVL GENMASK(9, 8) 25 #define MCF54415_DAC_CR_FILT BIT(12) 26 27 #define MCF54415_DAC_DATA 0x02 28 29 struct mcf54415_dac { 30 struct regmap *map; 31 struct clk *clk; 32 }; 33 34 static const struct regmap_config mcf54415_dac_regmap_config = { 35 .reg_bits = 16, 36 .reg_stride = 2, 37 .val_bits = 16, 38 .max_register = 0x0c, /* DACX_FILTCNT, R.M. Table 30-2 */ 39 .val_format_endian = REGMAP_ENDIAN_BIG, 40 .reg_format_endian = REGMAP_ENDIAN_BIG, 41 }; 42 43 static int mcf54415_dac_init(struct mcf54415_dac *info) 44 { 45 u16 val = MCF54415_DAC_CR_FILT | FIELD_PREP(MCF54415_DAC_CR_WMLVL, 1); 46 int ret; 47 48 /* Fixed defaults and enable DAC (bit 0 set to 0) */ 49 ret = regmap_write(info->map, MCF54415_DAC_CR, val); 50 if (ret) 51 return ret; 52 53 /* DAC is ready after 12us, from RM table 40-3 */ 54 fsleep(12); 55 56 return 0; 57 } 58 59 static void mcf54415_dac_exit(void *data) 60 { 61 struct mcf54415_dac *info = data; 62 63 regmap_set_bits(info->map, MCF54415_DAC_CR, MCF54415_DAC_CR_PDN); 64 } 65 66 static const struct iio_chan_spec mcf54415_dac_iio_channel = { 67 .type = IIO_VOLTAGE, 68 .output = 1, 69 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 70 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), 71 }; 72 73 static int mcf54415_read_raw(struct iio_dev *indio_dev, 74 struct iio_chan_spec const *chan, 75 int *val, int *val2, long mask) 76 { 77 struct mcf54415_dac *info = iio_priv(indio_dev); 78 unsigned int reg; 79 int ret; 80 81 switch (mask) { 82 case IIO_CHAN_INFO_RAW: 83 ret = regmap_read(info->map, MCF54415_DAC_DATA, ®); 84 if (ret) 85 return ret; 86 *val = reg & GENMASK(11, 0); 87 return IIO_VAL_INT; 88 case IIO_CHAN_INFO_SCALE: 89 /* Reference voltage as per ColdFire datasheet is 3.3V */ 90 *val = 3300 /* mV */; 91 *val2 = 12; 92 return IIO_VAL_FRACTIONAL_LOG2; 93 default: 94 return -EINVAL; 95 } 96 } 97 98 static int mcf54415_write_raw(struct iio_dev *indio_dev, 99 struct iio_chan_spec const *chan, 100 int val, int val2, long mask) 101 { 102 struct mcf54415_dac *info = iio_priv(indio_dev); 103 104 switch (mask) { 105 case IIO_CHAN_INFO_RAW: 106 /* Check based on RM 30.3.2 (DACn_DATA) reg. resolution */ 107 if (val < 0 || val > 4095) 108 return -EINVAL; 109 return regmap_write(info->map, MCF54415_DAC_DATA, val); 110 default: 111 return -EINVAL; 112 } 113 } 114 115 static const struct iio_info mcf54415_dac_iio_info = { 116 .read_raw = &mcf54415_read_raw, 117 .write_raw = &mcf54415_write_raw, 118 }; 119 120 static int mcf54415_dac_probe(struct platform_device *pdev) 121 { 122 struct device *dev = &pdev->dev; 123 struct iio_dev *indio_dev; 124 struct mcf54415_dac *info; 125 void __iomem *regs; 126 int ret; 127 128 indio_dev = devm_iio_device_alloc(dev, sizeof(*info)); 129 if (!indio_dev) 130 return -ENOMEM; 131 132 info = iio_priv(indio_dev); 133 134 regs = devm_platform_ioremap_resource(pdev, 0); 135 if (IS_ERR(regs)) 136 return dev_err_probe(dev, PTR_ERR(regs), "failed to get io regs\n"); 137 138 info->map = devm_regmap_init_mmio(dev, regs, &mcf54415_dac_regmap_config); 139 if (IS_ERR(info->map)) 140 return PTR_ERR(info->map); 141 142 info->clk = devm_clk_get_enabled(dev, "dac"); 143 if (IS_ERR(info->clk)) 144 return dev_err_probe(dev, PTR_ERR(info->clk), "failed getting clock\n"); 145 146 indio_dev->name = "mcf54415"; 147 indio_dev->info = &mcf54415_dac_iio_info; 148 indio_dev->modes = INDIO_DIRECT_MODE; 149 indio_dev->channels = &mcf54415_dac_iio_channel; 150 indio_dev->num_channels = 1; 151 152 ret = mcf54415_dac_init(info); 153 if (ret) 154 return ret; 155 156 ret = devm_add_action_or_reset(dev, mcf54415_dac_exit, info); 157 if (ret) 158 return ret; 159 160 return devm_iio_device_register(dev, indio_dev); 161 } 162 163 static const struct platform_device_id mcf54415_dac_ids[] = { 164 { .name = "mcfdac" }, 165 { } 166 }; 167 MODULE_DEVICE_TABLE(platform, mcf54415_dac_ids); 168 169 static struct platform_driver mcf54415_dac_driver = { 170 .driver = { 171 .name = "mcf54415_dac", 172 }, 173 .probe = mcf54415_dac_probe, 174 .id_table = mcf54415_dac_ids, 175 }; 176 module_platform_driver(mcf54415_dac_driver); 177 178 MODULE_AUTHOR("Angelo Dureghello <angelo@kernel-space.org>"); 179 MODULE_DESCRIPTION("NXP MCF54415 DAC driver"); 180 MODULE_LICENSE("GPL"); 181