brintos

brintos / linux-shallow public Read only

0
0
Text · 16.7 KiB · 0cb00f3 Raw
656 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Analog Devices Generic AXI DAC IP core4 * Link: https://wiki.analog.com/resources/fpga/docs/axi_dac_ip5 *6 * Copyright 2016-2024 Analog Devices Inc.7 */8#include <linux/bitfield.h>9#include <linux/bits.h>10#include <linux/cleanup.h>11#include <linux/clk.h>12#include <linux/device.h>13#include <linux/err.h>14#include <linux/limits.h>15#include <linux/kstrtox.h>16#include <linux/math.h>17#include <linux/math64.h>18#include <linux/module.h>19#include <linux/mod_devicetable.h>20#include <linux/mutex.h>21#include <linux/platform_device.h>22#include <linux/property.h>23#include <linux/regmap.h>24#include <linux/units.h>25 26#include <linux/fpga/adi-axi-common.h>27#include <linux/iio/backend.h>28#include <linux/iio/buffer-dmaengine.h>29#include <linux/iio/buffer.h>30#include <linux/iio/iio.h>31 32/*33 * Register definitions:34 *   https://wiki.analog.com/resources/fpga/docs/axi_dac_ip#register_map35 */36 37/* Base controls */38#define AXI_DAC_REG_CONFIG		0x0c39#define	   AXI_DDS_DISABLE		BIT(6)40 41 /* DAC controls */42#define AXI_DAC_REG_RSTN		0x004043#define   AXI_DAC_RSTN_CE_N		BIT(2)44#define   AXI_DAC_RSTN_MMCM_RSTN	BIT(1)45#define   AXI_DAC_RSTN_RSTN		BIT(0)46#define AXI_DAC_REG_CNTRL_1		0x004447#define   AXI_DAC_SYNC			BIT(0)48#define AXI_DAC_REG_CNTRL_2		0x004849#define	  ADI_DAC_R1_MODE		BIT(4)50#define AXI_DAC_DRP_STATUS		0x007451#define   AXI_DAC_DRP_LOCKED		BIT(17)52/* DAC Channel controls */53#define AXI_DAC_REG_CHAN_CNTRL_1(c)	(0x0400 + (c) * 0x40)54#define AXI_DAC_REG_CHAN_CNTRL_3(c)	(0x0408 + (c) * 0x40)55#define   AXI_DAC_SCALE_SIGN		BIT(15)56#define   AXI_DAC_SCALE_INT		BIT(14)57#define   AXI_DAC_SCALE			GENMASK(14, 0)58#define AXI_DAC_REG_CHAN_CNTRL_2(c)	(0x0404 + (c) * 0x40)59#define AXI_DAC_REG_CHAN_CNTRL_4(c)	(0x040c + (c) * 0x40)60#define   AXI_DAC_PHASE			GENMASK(31, 16)61#define   AXI_DAC_FREQUENCY		GENMASK(15, 0)62#define AXI_DAC_REG_CHAN_CNTRL_7(c)	(0x0418 + (c) * 0x40)63#define   AXI_DAC_DATA_SEL		GENMASK(3, 0)64 65/* 360 degrees in rad */66#define AXI_DAC_2_PI_MEGA		628319067enum {68	AXI_DAC_DATA_INTERNAL_TONE,69	AXI_DAC_DATA_DMA = 2,70};71 72struct axi_dac_state {73	struct regmap *regmap;74	struct device *dev;75	/*76	 * lock to protect multiple accesses to the device registers and global77	 * data/variables.78	 */79	struct mutex lock;80	u64 dac_clk;81	u32 reg_config;82	bool int_tone;83};84 85static int axi_dac_enable(struct iio_backend *back)86{87	struct axi_dac_state *st = iio_backend_get_priv(back);88	unsigned int __val;89	int ret;90 91	guard(mutex)(&st->lock);92	ret = regmap_set_bits(st->regmap, AXI_DAC_REG_RSTN,93			      AXI_DAC_RSTN_MMCM_RSTN);94	if (ret)95		return ret;96	/*97	 * Make sure the DRP (Dynamic Reconfiguration Port) is locked. Not all98	 * designs really use it but if they don't we still get the lock bit99	 * set. So let's do it all the time so the code is generic.100	 */101	ret = regmap_read_poll_timeout(st->regmap, AXI_DAC_DRP_STATUS, __val,102				       __val & AXI_DAC_DRP_LOCKED, 100, 1000);103	if (ret)104		return ret;105 106	return regmap_set_bits(st->regmap, AXI_DAC_REG_RSTN,107			       AXI_DAC_RSTN_RSTN | AXI_DAC_RSTN_MMCM_RSTN);108}109 110static void axi_dac_disable(struct iio_backend *back)111{112	struct axi_dac_state *st = iio_backend_get_priv(back);113 114	guard(mutex)(&st->lock);115	regmap_write(st->regmap, AXI_DAC_REG_RSTN, 0);116}117 118static struct iio_buffer *axi_dac_request_buffer(struct iio_backend *back,119						 struct iio_dev *indio_dev)120{121	struct axi_dac_state *st = iio_backend_get_priv(back);122	const char *dma_name;123 124	if (device_property_read_string(st->dev, "dma-names", &dma_name))125		dma_name = "tx";126 127	return iio_dmaengine_buffer_setup_ext(st->dev, indio_dev, dma_name,128					      IIO_BUFFER_DIRECTION_OUT);129}130 131static void axi_dac_free_buffer(struct iio_backend *back,132				struct iio_buffer *buffer)133{134	iio_dmaengine_buffer_free(buffer);135}136 137enum {138	AXI_DAC_FREQ_TONE_1,139	AXI_DAC_FREQ_TONE_2,140	AXI_DAC_SCALE_TONE_1,141	AXI_DAC_SCALE_TONE_2,142	AXI_DAC_PHASE_TONE_1,143	AXI_DAC_PHASE_TONE_2,144};145 146static int __axi_dac_frequency_get(struct axi_dac_state *st, unsigned int chan,147				   unsigned int tone_2, unsigned int *freq)148{149	u32 reg, raw;150	int ret;151 152	if (!st->dac_clk) {153		dev_err(st->dev, "Sampling rate is 0...\n");154		return -EINVAL;155	}156 157	if (tone_2)158		reg = AXI_DAC_REG_CHAN_CNTRL_4(chan);159	else160		reg = AXI_DAC_REG_CHAN_CNTRL_2(chan);161 162	ret = regmap_read(st->regmap, reg, &raw);163	if (ret)164		return ret;165 166	raw = FIELD_GET(AXI_DAC_FREQUENCY, raw);167	*freq = DIV_ROUND_CLOSEST_ULL(raw * st->dac_clk, BIT(16));168 169	return 0;170}171 172static int axi_dac_frequency_get(struct axi_dac_state *st,173				 const struct iio_chan_spec *chan, char *buf,174				 unsigned int tone_2)175{176	unsigned int freq;177	int ret;178 179	scoped_guard(mutex, &st->lock) {180		ret = __axi_dac_frequency_get(st, chan->channel, tone_2, &freq);181		if (ret)182			return ret;183	}184 185	return sysfs_emit(buf, "%u\n", freq);186}187 188static int axi_dac_scale_get(struct axi_dac_state *st,189			     const struct iio_chan_spec *chan, char *buf,190			     unsigned int tone_2)191{192	unsigned int scale, sign;193	int ret, vals[2];194	u32 reg, raw;195 196	if (tone_2)197		reg = AXI_DAC_REG_CHAN_CNTRL_3(chan->channel);198	else199		reg = AXI_DAC_REG_CHAN_CNTRL_1(chan->channel);200 201	ret = regmap_read(st->regmap, reg, &raw);202	if (ret)203		return ret;204 205	sign = FIELD_GET(AXI_DAC_SCALE_SIGN, raw);206	raw = FIELD_GET(AXI_DAC_SCALE, raw);207	scale = DIV_ROUND_CLOSEST_ULL((u64)raw * MEGA, AXI_DAC_SCALE_INT);208 209	vals[0] = scale / MEGA;210	vals[1] = scale % MEGA;211 212	if (sign) {213		vals[0] *= -1;214		if (!vals[0])215			vals[1] *= -1;216	}217 218	return iio_format_value(buf, IIO_VAL_INT_PLUS_MICRO, ARRAY_SIZE(vals),219				vals);220}221 222static int axi_dac_phase_get(struct axi_dac_state *st,223			     const struct iio_chan_spec *chan, char *buf,224			     unsigned int tone_2)225{226	u32 reg, raw, phase;227	int ret, vals[2];228 229	if (tone_2)230		reg = AXI_DAC_REG_CHAN_CNTRL_4(chan->channel);231	else232		reg = AXI_DAC_REG_CHAN_CNTRL_2(chan->channel);233 234	ret = regmap_read(st->regmap, reg, &raw);235	if (ret)236		return ret;237 238	raw = FIELD_GET(AXI_DAC_PHASE, raw);239	phase = DIV_ROUND_CLOSEST_ULL((u64)raw * AXI_DAC_2_PI_MEGA, U16_MAX);240 241	vals[0] = phase / MEGA;242	vals[1] = phase % MEGA;243 244	return iio_format_value(buf, IIO_VAL_INT_PLUS_MICRO, ARRAY_SIZE(vals),245				vals);246}247 248static int __axi_dac_frequency_set(struct axi_dac_state *st, unsigned int chan,249				   u64 sample_rate, unsigned int freq,250				   unsigned int tone_2)251{252	u32 reg;253	u16 raw;254	int ret;255 256	if (!sample_rate || freq > sample_rate / 2) {257		dev_err(st->dev, "Invalid frequency(%u) dac_clk(%llu)\n",258			freq, sample_rate);259		return -EINVAL;260	}261 262	if (tone_2)263		reg = AXI_DAC_REG_CHAN_CNTRL_4(chan);264	else265		reg = AXI_DAC_REG_CHAN_CNTRL_2(chan);266 267	raw = DIV64_U64_ROUND_CLOSEST((u64)freq * BIT(16), sample_rate);268 269	ret = regmap_update_bits(st->regmap,  reg, AXI_DAC_FREQUENCY, raw);270	if (ret)271		return ret;272 273	/* synchronize channels */274	return regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);275}276 277static int axi_dac_frequency_set(struct axi_dac_state *st,278				 const struct iio_chan_spec *chan,279				 const char *buf, size_t len, unsigned int tone_2)280{281	unsigned int freq;282	int ret;283 284	ret = kstrtou32(buf, 10, &freq);285	if (ret)286		return ret;287 288	guard(mutex)(&st->lock);289	ret = __axi_dac_frequency_set(st, chan->channel, st->dac_clk, freq,290				      tone_2);291	if (ret)292		return ret;293 294	return len;295}296 297static int axi_dac_scale_set(struct axi_dac_state *st,298			     const struct iio_chan_spec *chan,299			     const char *buf, size_t len, unsigned int tone_2)300{301	int integer, frac, scale;302	u32 raw = 0, reg;303	int ret;304 305	ret = iio_str_to_fixpoint(buf, 100000, &integer, &frac);306	if (ret)307		return ret;308 309	scale = integer * MEGA + frac;310	if (scale <= -2 * (int)MEGA || scale >= 2 * (int)MEGA)311		return -EINVAL;312 313	/*  format is 1.1.14 (sign, integer and fractional bits) */314	if (scale < 0) {315		raw = FIELD_PREP(AXI_DAC_SCALE_SIGN, 1);316		scale *= -1;317	}318 319	raw |= div_u64((u64)scale * AXI_DAC_SCALE_INT, MEGA);320 321	if (tone_2)322		reg = AXI_DAC_REG_CHAN_CNTRL_3(chan->channel);323	else324		reg = AXI_DAC_REG_CHAN_CNTRL_1(chan->channel);325 326	guard(mutex)(&st->lock);327	ret = regmap_write(st->regmap, reg, raw);328	if (ret)329		return ret;330 331	/* synchronize channels */332	ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);333	if (ret)334		return ret;335 336	return len;337}338 339static int axi_dac_phase_set(struct axi_dac_state *st,340			     const struct iio_chan_spec *chan,341			     const char *buf, size_t len, unsigned int tone_2)342{343	int integer, frac, phase;344	u32 raw, reg;345	int ret;346 347	ret = iio_str_to_fixpoint(buf, 100000, &integer, &frac);348	if (ret)349		return ret;350 351	phase = integer * MEGA + frac;352	if (phase < 0 || phase > AXI_DAC_2_PI_MEGA)353		return -EINVAL;354 355	raw = DIV_ROUND_CLOSEST_ULL((u64)phase * U16_MAX, AXI_DAC_2_PI_MEGA);356 357	if (tone_2)358		reg = AXI_DAC_REG_CHAN_CNTRL_4(chan->channel);359	else360		reg = AXI_DAC_REG_CHAN_CNTRL_2(chan->channel);361 362	guard(mutex)(&st->lock);363	ret = regmap_update_bits(st->regmap, reg, AXI_DAC_PHASE,364				 FIELD_PREP(AXI_DAC_PHASE, raw));365	if (ret)366		return ret;367 368	/* synchronize channels */369	ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);370	if (ret)371		return ret;372 373	return len;374}375 376static int axi_dac_ext_info_set(struct iio_backend *back, uintptr_t private,377				const struct iio_chan_spec *chan,378				const char *buf, size_t len)379{380	struct axi_dac_state *st = iio_backend_get_priv(back);381 382	switch (private) {383	case AXI_DAC_FREQ_TONE_1:384	case AXI_DAC_FREQ_TONE_2:385		return axi_dac_frequency_set(st, chan, buf, len,386					     private == AXI_DAC_FREQ_TONE_2);387	case AXI_DAC_SCALE_TONE_1:388	case AXI_DAC_SCALE_TONE_2:389		return axi_dac_scale_set(st, chan, buf, len,390					 private == AXI_DAC_SCALE_TONE_2);391	case AXI_DAC_PHASE_TONE_1:392	case AXI_DAC_PHASE_TONE_2:393		return axi_dac_phase_set(st, chan, buf, len,394					 private == AXI_DAC_PHASE_TONE_2);395	default:396		return -EOPNOTSUPP;397	}398}399 400static int axi_dac_ext_info_get(struct iio_backend *back, uintptr_t private,401				const struct iio_chan_spec *chan, char *buf)402{403	struct axi_dac_state *st = iio_backend_get_priv(back);404 405	switch (private) {406	case AXI_DAC_FREQ_TONE_1:407	case AXI_DAC_FREQ_TONE_2:408		return axi_dac_frequency_get(st, chan, buf,409					     private - AXI_DAC_FREQ_TONE_1);410	case AXI_DAC_SCALE_TONE_1:411	case AXI_DAC_SCALE_TONE_2:412		return axi_dac_scale_get(st, chan, buf,413					 private - AXI_DAC_SCALE_TONE_1);414	case AXI_DAC_PHASE_TONE_1:415	case AXI_DAC_PHASE_TONE_2:416		return axi_dac_phase_get(st, chan, buf,417					 private - AXI_DAC_PHASE_TONE_1);418	default:419		return -EOPNOTSUPP;420	}421}422 423static const struct iio_chan_spec_ext_info axi_dac_ext_info[] = {424	IIO_BACKEND_EX_INFO("frequency0", IIO_SEPARATE, AXI_DAC_FREQ_TONE_1),425	IIO_BACKEND_EX_INFO("frequency1", IIO_SEPARATE, AXI_DAC_FREQ_TONE_2),426	IIO_BACKEND_EX_INFO("scale0", IIO_SEPARATE, AXI_DAC_SCALE_TONE_1),427	IIO_BACKEND_EX_INFO("scale1", IIO_SEPARATE, AXI_DAC_SCALE_TONE_2),428	IIO_BACKEND_EX_INFO("phase0", IIO_SEPARATE, AXI_DAC_PHASE_TONE_1),429	IIO_BACKEND_EX_INFO("phase1", IIO_SEPARATE, AXI_DAC_PHASE_TONE_2),430	{}431};432 433static int axi_dac_extend_chan(struct iio_backend *back,434			       struct iio_chan_spec *chan)435{436	struct axi_dac_state *st = iio_backend_get_priv(back);437 438	if (chan->type != IIO_ALTVOLTAGE)439		return -EINVAL;440	if (st->reg_config & AXI_DDS_DISABLE)441		/* nothing to extend */442		return 0;443 444	chan->ext_info = axi_dac_ext_info;445 446	return 0;447}448 449static int axi_dac_data_source_set(struct iio_backend *back, unsigned int chan,450				   enum iio_backend_data_source data)451{452	struct axi_dac_state *st = iio_backend_get_priv(back);453 454	switch (data) {455	case IIO_BACKEND_INTERNAL_CONTINUOUS_WAVE:456		return regmap_update_bits(st->regmap,457					  AXI_DAC_REG_CHAN_CNTRL_7(chan),458					  AXI_DAC_DATA_SEL,459					  AXI_DAC_DATA_INTERNAL_TONE);460	case IIO_BACKEND_EXTERNAL:461		return regmap_update_bits(st->regmap,462					  AXI_DAC_REG_CHAN_CNTRL_7(chan),463					  AXI_DAC_DATA_SEL, AXI_DAC_DATA_DMA);464	default:465		return -EINVAL;466	}467}468 469static int axi_dac_set_sample_rate(struct iio_backend *back, unsigned int chan,470				   u64 sample_rate)471{472	struct axi_dac_state *st = iio_backend_get_priv(back);473	unsigned int freq;474	int ret, tone;475 476	if (!sample_rate)477		return -EINVAL;478	if (st->reg_config & AXI_DDS_DISABLE)479		/* sample_rate has no meaning if DDS is disabled */480		return 0;481 482	guard(mutex)(&st->lock);483	/*484	 * If dac_clk is 0 then this must be the first time we're being notified485	 * about the interface sample rate. Hence, just update our internal486	 * variable and bail... If it's not 0, then we get the current DDS487	 * frequency (for the old rate) and update the registers for the new488	 * sample rate.489	 */490	if (!st->dac_clk) {491		st->dac_clk = sample_rate;492		return 0;493	}494 495	for (tone = 0; tone <= AXI_DAC_FREQ_TONE_2; tone++) {496		ret = __axi_dac_frequency_get(st, chan, tone, &freq);497		if (ret)498			return ret;499 500		ret = __axi_dac_frequency_set(st, chan, sample_rate, tone, freq);501		if (ret)502			return ret;503	}504 505	st->dac_clk = sample_rate;506 507	return 0;508}509 510static int axi_dac_reg_access(struct iio_backend *back, unsigned int reg,511			      unsigned int writeval, unsigned int *readval)512{513	struct axi_dac_state *st = iio_backend_get_priv(back);514 515	if (readval)516		return regmap_read(st->regmap, reg, readval);517 518	return regmap_write(st->regmap, reg, writeval);519}520 521static const struct iio_backend_ops axi_dac_generic_ops = {522	.enable = axi_dac_enable,523	.disable = axi_dac_disable,524	.request_buffer = axi_dac_request_buffer,525	.free_buffer = axi_dac_free_buffer,526	.extend_chan_spec = axi_dac_extend_chan,527	.ext_info_set = axi_dac_ext_info_set,528	.ext_info_get = axi_dac_ext_info_get,529	.data_source_set = axi_dac_data_source_set,530	.set_sample_rate = axi_dac_set_sample_rate,531	.debugfs_reg_access = iio_backend_debugfs_ptr(axi_dac_reg_access),532};533 534static const struct iio_backend_info axi_dac_generic = {535	.name = "axi-dac",536	.ops = &axi_dac_generic_ops,537};538 539static const struct regmap_config axi_dac_regmap_config = {540	.val_bits = 32,541	.reg_bits = 32,542	.reg_stride = 4,543	.max_register = 0x0800,544};545 546static int axi_dac_probe(struct platform_device *pdev)547{548	const unsigned int *expected_ver;549	struct axi_dac_state *st;550	void __iomem *base;551	unsigned int ver;552	struct clk *clk;553	int ret;554 555	st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL);556	if (!st)557		return -ENOMEM;558 559	expected_ver = device_get_match_data(&pdev->dev);560	if (!expected_ver)561		return -ENODEV;562 563	clk = devm_clk_get_enabled(&pdev->dev, NULL);564	if (IS_ERR(clk))565		return dev_err_probe(&pdev->dev, PTR_ERR(clk),566				     "failed to get clock\n");567 568	base = devm_platform_ioremap_resource(pdev, 0);569	if (IS_ERR(base))570		return PTR_ERR(base);571 572	st->dev = &pdev->dev;573	st->regmap = devm_regmap_init_mmio(&pdev->dev, base,574					   &axi_dac_regmap_config);575	if (IS_ERR(st->regmap))576		return dev_err_probe(&pdev->dev, PTR_ERR(st->regmap),577				     "failed to init register map\n");578 579	/*580	 * Force disable the core. Up to the frontend to enable us. And we can581	 * still read/write registers...582	 */583	ret = regmap_write(st->regmap, AXI_DAC_REG_RSTN, 0);584	if (ret)585		return ret;586 587	ret = regmap_read(st->regmap, ADI_AXI_REG_VERSION, &ver);588	if (ret)589		return ret;590 591	if (ADI_AXI_PCORE_VER_MAJOR(ver) != ADI_AXI_PCORE_VER_MAJOR(*expected_ver)) {592		dev_err(&pdev->dev,593			"Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",594			ADI_AXI_PCORE_VER_MAJOR(*expected_ver),595			ADI_AXI_PCORE_VER_MINOR(*expected_ver),596			ADI_AXI_PCORE_VER_PATCH(*expected_ver),597			ADI_AXI_PCORE_VER_MAJOR(ver),598			ADI_AXI_PCORE_VER_MINOR(ver),599			ADI_AXI_PCORE_VER_PATCH(ver));600		return -ENODEV;601	}602 603	/* Let's get the core read only configuration */604	ret = regmap_read(st->regmap, AXI_DAC_REG_CONFIG, &st->reg_config);605	if (ret)606		return ret;607 608	/*609	 * In some designs, setting the R1_MODE bit to 0 (which is the default610	 * value) causes all channels of the frontend to be routed to the same611	 * DMA (so they are sampled together). This is for things like612	 * Multiple-Input and Multiple-Output (MIMO). As most of the times we613	 * want independent channels let's override the core's default value and614	 * set the R1_MODE bit.615	 */616	ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_2, ADI_DAC_R1_MODE);617	if (ret)618		return ret;619 620	mutex_init(&st->lock);621	ret = devm_iio_backend_register(&pdev->dev, &axi_dac_generic, st);622	if (ret)623		return dev_err_probe(&pdev->dev, ret,624				     "failed to register iio backend\n");625 626	dev_info(&pdev->dev, "AXI DAC IP core (%d.%.2d.%c) probed\n",627		 ADI_AXI_PCORE_VER_MAJOR(ver),628		 ADI_AXI_PCORE_VER_MINOR(ver),629		 ADI_AXI_PCORE_VER_PATCH(ver));630 631	return 0;632}633 634static unsigned int axi_dac_9_1_b_info = ADI_AXI_PCORE_VER(9, 1, 'b');635 636static const struct of_device_id axi_dac_of_match[] = {637	{ .compatible = "adi,axi-dac-9.1.b", .data = &axi_dac_9_1_b_info },638	{}639};640MODULE_DEVICE_TABLE(of, axi_dac_of_match);641 642static struct platform_driver axi_dac_driver = {643	.driver = {644		.name = "adi-axi-dac",645		.of_match_table = axi_dac_of_match,646	},647	.probe = axi_dac_probe,648};649module_platform_driver(axi_dac_driver);650 651MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");652MODULE_DESCRIPTION("Analog Devices Generic AXI DAC IP core driver");653MODULE_LICENSE("GPL");654MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER);655MODULE_IMPORT_NS(IIO_BACKEND);656