| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Analog Devices AD4062 I3C ADC driver
- *
- * Copyright 2025 Analog Devices Inc.
- */
- #include <linux/array_size.h>
- #include <linux/bitfield.h>
- #include <linux/bitops.h>
- #include <linux/completion.h>
- #include <linux/delay.h>
- #include <linux/devm-helpers.h>
- #include <linux/err.h>
- #include <linux/gpio/driver.h>
- #include <linux/i3c/device.h>
- #include <linux/i3c/master.h>
- #include <linux/iio/buffer.h>
- #include <linux/iio/events.h>
- #include <linux/iio/iio.h>
- #include <linux/iio/sysfs.h>
- #include <linux/iio/trigger.h>
- #include <linux/iio/trigger_consumer.h>
- #include <linux/iio/triggered_buffer.h>
- #include <linux/interrupt.h>
- #include <linux/jiffies.h>
- #include <linux/math.h>
- #include <linux/minmax.h>
- #include <linux/pm_runtime.h>
- #include <linux/property.h>
- #include <linux/regmap.h>
- #include <linux/regulator/consumer.h>
- #include <linux/string.h>
- #include <linux/types.h>
- #include <linux/units.h>
- #include <linux/unaligned.h>
- #include <linux/util_macros.h>
- #define AD4062_REG_INTERFACE_CONFIG_A 0x00
- #define AD4062_REG_DEVICE_CONFIG 0x02
- #define AD4062_REG_DEVICE_CONFIG_POWER_MODE_MSK GENMASK(1, 0)
- #define AD4062_REG_DEVICE_CONFIG_LOW_POWER_MODE 3
- #define AD4062_REG_PROD_ID_1 0x05
- #define AD4062_REG_DEVICE_GRADE 0x06
- #define AD4062_REG_SCRATCH_PAD 0x0A
- #define AD4062_REG_VENDOR_H 0x0D
- #define AD4062_REG_STREAM_MODE 0x0E
- #define AD4062_REG_INTERFACE_STATUS 0x11
- #define AD4062_REG_MODE_SET 0x20
- #define AD4062_REG_MODE_SET_ENTER_ADC BIT(0)
- #define AD4062_REG_ADC_MODES 0x21
- #define AD4062_REG_ADC_MODES_MODE_MSK GENMASK(1, 0)
- #define AD4062_REG_ADC_CONFIG 0x22
- #define AD4062_REG_ADC_CONFIG_REF_EN_MSK BIT(5)
- #define AD4062_REG_ADC_CONFIG_SCALE_EN_MSK BIT(4)
- #define AD4062_REG_AVG_CONFIG 0x23
- #define AD4062_REG_GP_CONF 0x24
- #define AD4062_REG_GP_CONF_MODE_MSK_0 GENMASK(2, 0)
- #define AD4062_REG_GP_CONF_MODE_MSK_1 GENMASK(6, 4)
- #define AD4062_REG_INTR_CONF 0x25
- #define AD4062_REG_INTR_CONF_EN_MSK_0 GENMASK(1, 0)
- #define AD4062_REG_INTR_CONF_EN_MSK_1 GENMASK(5, 4)
- #define AD4062_REG_TIMER_CONFIG 0x27
- #define AD4062_REG_TIMER_CONFIG_FS_MASK GENMASK(7, 4)
- #define AD4062_REG_MAX_LIMIT 0x29
- #define AD4062_REG_MIN_LIMIT 0x2B
- #define AD4062_REG_MAX_HYST 0x2C
- #define AD4062_REG_MIN_HYST 0x2D
- #define AD4062_REG_MON_VAL 0x2F
- #define AD4062_REG_ADC_IBI_EN 0x31
- #define AD4062_REG_ADC_IBI_EN_CONV_TRIGGER BIT(2)
- #define AD4062_REG_ADC_IBI_EN_MAX BIT(1)
- #define AD4062_REG_ADC_IBI_EN_MIN BIT(0)
- #define AD4062_REG_FUSE_CRC 0x40
- #define AD4062_REG_DEVICE_STATUS 0x41
- #define AD4062_REG_DEVICE_STATUS_DEVICE_RESET BIT(6)
- #define AD4062_REG_IBI_STATUS 0x48
- #define AD4062_REG_CONV_READ_LSB 0x50
- #define AD4062_REG_CONV_READ_16BITS 0x51
- #define AD4062_REG_CONV_READ_32BITS 0x53
- #define AD4062_REG_CONV_TRIGGER_16BITS 0x57
- #define AD4062_REG_CONV_TRIGGER_32BITS 0x59
- #define AD4062_REG_CONV_AUTO 0x61
- #define AD4062_MAX_REG AD4062_REG_CONV_AUTO
- #define AD4062_MON_VAL_MIDDLE_POINT 0x8000
- #define AD4062_I3C_VENDOR 0x0177
- #define AD4062_SOFT_RESET 0x81
- #define AD4060_PROD_ID 0x7A
- #define AD4062_PROD_ID 0x7C
- #define AD4062_GP_DISABLED 0x0
- #define AD4062_GP_INTR 0x1
- #define AD4062_GP_DRDY 0x2
- #define AD4062_GP_STATIC_LOW 0x5
- #define AD4062_GP_STATIC_HIGH 0x6
- #define AD4062_LIMIT_BITS 12
- #define AD4062_INTR_EN_NEITHER 0x0
- #define AD4062_INTR_EN_EITHER 0x3
- #define AD4062_TCONV_NS 270
- enum ad4062_operation_mode {
- AD4062_SAMPLE_MODE = 0x0,
- AD4062_BURST_AVERAGING_MODE = 0x1,
- AD4062_MONITOR_MODE = 0x3,
- };
- struct ad4062_chip_info {
- const struct iio_chan_spec channels[1];
- const char *name;
- u16 prod_id;
- u16 avg_max;
- };
- enum {
- AD4062_SCAN_TYPE_SAMPLE,
- AD4062_SCAN_TYPE_BURST_AVG,
- };
- static const struct iio_scan_type ad4062_scan_type_12_s[] = {
- [AD4062_SCAN_TYPE_SAMPLE] = {
- .sign = 's',
- .realbits = 12,
- .storagebits = 16,
- .endianness = IIO_BE,
- },
- [AD4062_SCAN_TYPE_BURST_AVG] = {
- .sign = 's',
- .realbits = 14,
- .storagebits = 16,
- .endianness = IIO_BE,
- },
- };
- static const struct iio_scan_type ad4062_scan_type_16_s[] = {
- [AD4062_SCAN_TYPE_SAMPLE] = {
- .sign = 's',
- .realbits = 16,
- .storagebits = 16,
- .endianness = IIO_BE,
- },
- [AD4062_SCAN_TYPE_BURST_AVG] = {
- .sign = 's',
- .realbits = 20,
- .storagebits = 32,
- .endianness = IIO_BE,
- },
- };
- static const unsigned int ad4062_conversion_freqs[] = {
- 2000000, 1000000, 300000, 100000, /* 0 - 3 */
- 33300, 10000, 3000, 500, /* 4 - 7 */
- 333, 250, 200, 166, /* 8 - 11 */
- 140, 124, 111, /* 12 - 15 */
- };
- struct ad4062_state {
- const struct ad4062_chip_info *chip;
- const struct ad4062_bus_ops *ops;
- enum ad4062_operation_mode mode;
- struct work_struct trig_conv;
- struct completion completion;
- struct iio_trigger *trigger;
- struct iio_dev *indio_dev;
- struct i3c_device *i3cdev;
- struct regmap *regmap;
- bool wait_event;
- int vref_uV;
- unsigned int samp_freqs[ARRAY_SIZE(ad4062_conversion_freqs)];
- bool gpo_irq[2];
- u16 sampling_frequency;
- u16 events_frequency;
- u8 oversamp_ratio;
- u8 conv_sizeof;
- u8 conv_addr;
- union {
- __be32 be32;
- __be16 be16;
- } buf __aligned(IIO_DMA_MINALIGN);
- };
- static const struct regmap_range ad4062_regmap_rd_ranges[] = {
- regmap_reg_range(AD4062_REG_INTERFACE_CONFIG_A, AD4062_REG_DEVICE_GRADE),
- regmap_reg_range(AD4062_REG_SCRATCH_PAD, AD4062_REG_INTERFACE_STATUS),
- regmap_reg_range(AD4062_REG_MODE_SET, AD4062_REG_ADC_IBI_EN),
- regmap_reg_range(AD4062_REG_FUSE_CRC, AD4062_REG_IBI_STATUS),
- regmap_reg_range(AD4062_REG_CONV_READ_LSB, AD4062_REG_CONV_AUTO),
- };
- static const struct regmap_access_table ad4062_regmap_rd_table = {
- .yes_ranges = ad4062_regmap_rd_ranges,
- .n_yes_ranges = ARRAY_SIZE(ad4062_regmap_rd_ranges),
- };
- static const struct regmap_range ad4062_regmap_wr_ranges[] = {
- regmap_reg_range(AD4062_REG_INTERFACE_CONFIG_A, AD4062_REG_DEVICE_CONFIG),
- regmap_reg_range(AD4062_REG_SCRATCH_PAD, AD4062_REG_SCRATCH_PAD),
- regmap_reg_range(AD4062_REG_STREAM_MODE, AD4062_REG_INTERFACE_STATUS),
- regmap_reg_range(AD4062_REG_MODE_SET, AD4062_REG_ADC_IBI_EN),
- regmap_reg_range(AD4062_REG_FUSE_CRC, AD4062_REG_DEVICE_STATUS),
- };
- static const struct regmap_access_table ad4062_regmap_wr_table = {
- .yes_ranges = ad4062_regmap_wr_ranges,
- .n_yes_ranges = ARRAY_SIZE(ad4062_regmap_wr_ranges),
- };
- static const struct iio_event_spec ad4062_events[] = {
- {
- .type = IIO_EV_TYPE_THRESH,
- .dir = IIO_EV_DIR_EITHER,
- .mask_shared_by_all = BIT(IIO_EV_INFO_ENABLE),
- },
- {
- .type = IIO_EV_TYPE_THRESH,
- .dir = IIO_EV_DIR_RISING,
- .mask_shared_by_all = BIT(IIO_EV_INFO_VALUE) |
- BIT(IIO_EV_INFO_HYSTERESIS),
- },
- {
- .type = IIO_EV_TYPE_THRESH,
- .dir = IIO_EV_DIR_FALLING,
- .mask_shared_by_all = BIT(IIO_EV_INFO_VALUE) |
- BIT(IIO_EV_INFO_HYSTERESIS),
- },
- };
- #define AD4062_CHAN(bits) { \
- .type = IIO_VOLTAGE, \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_RAW) | \
- BIT(IIO_CHAN_INFO_SCALE) | \
- BIT(IIO_CHAN_INFO_CALIBSCALE) | \
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
- .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
- .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
- .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
- .indexed = 1, \
- .channel = 0, \
- .event_spec = ad4062_events, \
- .num_event_specs = ARRAY_SIZE(ad4062_events), \
- .has_ext_scan_type = 1, \
- .ext_scan_type = ad4062_scan_type_##bits##_s, \
- .num_ext_scan_type = ARRAY_SIZE(ad4062_scan_type_##bits##_s), \
- }
- static const struct ad4062_chip_info ad4060_chip_info = {
- .name = "ad4060",
- .channels = { AD4062_CHAN(12) },
- .prod_id = AD4060_PROD_ID,
- .avg_max = 256,
- };
- static const struct ad4062_chip_info ad4062_chip_info = {
- .name = "ad4062",
- .channels = { AD4062_CHAN(16) },
- .prod_id = AD4062_PROD_ID,
- .avg_max = 4096,
- };
- static ssize_t sampling_frequency_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct ad4062_state *st = iio_priv(dev_to_iio_dev(dev));
- return sysfs_emit(buf, "%d\n", ad4062_conversion_freqs[st->events_frequency]);
- }
- static int sampling_frequency_store_dispatch(struct iio_dev *indio_dev,
- const char *buf)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- int val, ret;
- if (st->wait_event)
- return -EBUSY;
- ret = kstrtoint(buf, 10, &val);
- if (ret)
- return ret;
- st->events_frequency = find_closest_descending(val, ad4062_conversion_freqs,
- ARRAY_SIZE(ad4062_conversion_freqs));
- return 0;
- }
- static ssize_t sampling_frequency_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
- {
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- int ret;
- if (!iio_device_claim_direct(indio_dev))
- return -EBUSY;
- ret = sampling_frequency_store_dispatch(indio_dev, buf);
- iio_device_release_direct(indio_dev);
- return ret ?: len;
- }
- static IIO_DEVICE_ATTR_RW(sampling_frequency, 0);
- static ssize_t sampling_frequency_available_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
- {
- int ret = 0;
- for (u8 i = 0; i < ARRAY_SIZE(ad4062_conversion_freqs); i++)
- ret += sysfs_emit_at(buf, ret, "%d%s", ad4062_conversion_freqs[i],
- i != (ARRAY_SIZE(ad4062_conversion_freqs) - 1) ? " " : "\n");
- return ret;
- }
- static IIO_DEVICE_ATTR_RO(sampling_frequency_available, 0);
- static struct attribute *ad4062_event_attributes[] = {
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
- &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
- NULL
- };
- static const struct attribute_group ad4062_event_attribute_group = {
- .attrs = ad4062_event_attributes,
- };
- static int ad4062_set_oversampling_ratio(struct ad4062_state *st, int val, int val2)
- {
- const u32 _max = st->chip->avg_max;
- const u32 _min = 1;
- int ret;
- if (!in_range(val, _min, _max) || val2 != 0)
- return -EINVAL;
- /* 1 disables oversampling */
- val = ilog2(val);
- if (val == 0) {
- st->mode = AD4062_SAMPLE_MODE;
- } else {
- st->mode = AD4062_BURST_AVERAGING_MODE;
- ret = regmap_write(st->regmap, AD4062_REG_AVG_CONFIG, val - 1);
- if (ret)
- return ret;
- }
- st->oversamp_ratio = val;
- return 0;
- }
- static int ad4062_get_oversampling_ratio(struct ad4062_state *st, int *val)
- {
- int ret, buf;
- if (st->mode == AD4062_SAMPLE_MODE) {
- *val = 1;
- return 0;
- }
- ret = regmap_read(st->regmap, AD4062_REG_AVG_CONFIG, &buf);
- if (ret)
- return ret;
- *val = BIT(buf + 1);
- return 0;
- }
- static int ad4062_calc_sampling_frequency(unsigned int fosc, unsigned int oversamp_ratio)
- {
- /* From datasheet p.31: (n_avg - 1)/fosc + tconv */
- u32 n_avg = BIT(oversamp_ratio) - 1;
- u32 period_ns = NSEC_PER_SEC / fosc;
- /* Result is less than 1 Hz */
- if (n_avg >= fosc)
- return 1;
- return NSEC_PER_SEC / (n_avg * period_ns + AD4062_TCONV_NS);
- }
- static int ad4062_populate_sampling_frequency(struct ad4062_state *st)
- {
- for (u8 i = 0; i < ARRAY_SIZE(ad4062_conversion_freqs); i++)
- st->samp_freqs[i] =
- ad4062_calc_sampling_frequency(ad4062_conversion_freqs[i],
- st->oversamp_ratio);
- return 0;
- }
- static int ad4062_get_sampling_frequency(struct ad4062_state *st, int *val)
- {
- int freq = ad4062_conversion_freqs[st->sampling_frequency];
- *val = ad4062_calc_sampling_frequency(freq, st->oversamp_ratio);
- return IIO_VAL_INT;
- }
- static int ad4062_set_sampling_frequency(struct ad4062_state *st, int val, int val2)
- {
- int ret;
- if (val2 != 0)
- return -EINVAL;
- ret = ad4062_populate_sampling_frequency(st);
- if (ret)
- return ret;
- st->sampling_frequency =
- find_closest_descending(val, st->samp_freqs,
- ARRAY_SIZE(ad4062_conversion_freqs));
- return 0;
- }
- static int ad4062_check_ids(struct ad4062_state *st)
- {
- struct device *dev = &st->i3cdev->dev;
- int ret;
- u16 val;
- ret = regmap_bulk_read(st->regmap, AD4062_REG_PROD_ID_1,
- &st->buf.be16, sizeof(st->buf.be16));
- if (ret)
- return ret;
- val = be16_to_cpu(st->buf.be16);
- if (val != st->chip->prod_id)
- dev_warn(dev, "Production ID x%x does not match known values", val);
- ret = regmap_bulk_read(st->regmap, AD4062_REG_VENDOR_H,
- &st->buf.be16, sizeof(st->buf.be16));
- if (ret)
- return ret;
- val = be16_to_cpu(st->buf.be16);
- if (val != AD4062_I3C_VENDOR) {
- dev_err(dev, "Vendor ID x%x does not match expected value\n", val);
- return -ENODEV;
- }
- return 0;
- }
- static int ad4062_conversion_frequency_set(struct ad4062_state *st, u8 val)
- {
- return regmap_write(st->regmap, AD4062_REG_TIMER_CONFIG,
- FIELD_PREP(AD4062_REG_TIMER_CONFIG_FS_MASK, val));
- }
- static int ad4062_set_operation_mode(struct ad4062_state *st,
- enum ad4062_operation_mode mode)
- {
- const unsigned int samp_freq = mode == AD4062_MONITOR_MODE ?
- st->events_frequency : st->sampling_frequency;
- int ret;
- ret = ad4062_conversion_frequency_set(st, samp_freq);
- if (ret)
- return ret;
- ret = regmap_update_bits(st->regmap, AD4062_REG_ADC_MODES,
- AD4062_REG_ADC_MODES_MODE_MSK, mode);
- if (ret)
- return ret;
- if (mode == AD4062_MONITOR_MODE) {
- /* Change address pointer to enter monitor mode */
- struct i3c_xfer xfer_trigger = {
- .data.out = &st->conv_addr,
- .len = sizeof(st->conv_addr),
- .rnw = false,
- };
- st->conv_addr = AD4062_REG_CONV_TRIGGER_32BITS;
- return i3c_device_do_xfers(st->i3cdev, &xfer_trigger, 1, I3C_SDR);
- }
- return regmap_write(st->regmap, AD4062_REG_MODE_SET,
- AD4062_REG_MODE_SET_ENTER_ADC);
- }
- static int ad4062_soft_reset(struct ad4062_state *st)
- {
- u8 val = AD4062_SOFT_RESET;
- int ret;
- ret = regmap_write(st->regmap, AD4062_REG_INTERFACE_CONFIG_A, val);
- if (ret)
- return ret;
- /* Wait AD4062 treset time, datasheet p8 */
- ndelay(60);
- return 0;
- }
- static int ad4062_setup(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
- const bool *ref_sel)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- const struct iio_scan_type *scan_type;
- int ret;
- scan_type = iio_get_current_scan_type(indio_dev, chan);
- if (IS_ERR(scan_type))
- return PTR_ERR(scan_type);
- ret = regmap_update_bits(st->regmap, AD4062_REG_GP_CONF,
- AD4062_REG_GP_CONF_MODE_MSK_0,
- FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_0,
- AD4062_GP_INTR));
- if (ret)
- return ret;
- ret = regmap_update_bits(st->regmap, AD4062_REG_GP_CONF,
- AD4062_REG_GP_CONF_MODE_MSK_1,
- FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_1,
- AD4062_GP_DRDY));
- if (ret)
- return ret;
- ret = regmap_update_bits(st->regmap, AD4062_REG_ADC_CONFIG,
- AD4062_REG_ADC_CONFIG_REF_EN_MSK,
- FIELD_PREP(AD4062_REG_ADC_CONFIG_REF_EN_MSK,
- *ref_sel));
- if (ret)
- return ret;
- ret = regmap_write(st->regmap, AD4062_REG_DEVICE_STATUS,
- AD4062_REG_DEVICE_STATUS_DEVICE_RESET);
- if (ret)
- return ret;
- ret = regmap_update_bits(st->regmap, AD4062_REG_INTR_CONF,
- AD4062_REG_INTR_CONF_EN_MSK_0,
- FIELD_PREP(AD4062_REG_INTR_CONF_EN_MSK_0,
- AD4062_INTR_EN_EITHER));
- if (ret)
- return ret;
- ret = regmap_update_bits(st->regmap, AD4062_REG_INTR_CONF,
- AD4062_REG_INTR_CONF_EN_MSK_1,
- FIELD_PREP(AD4062_REG_INTR_CONF_EN_MSK_1,
- AD4062_INTR_EN_NEITHER));
- if (ret)
- return ret;
- st->buf.be16 = cpu_to_be16(AD4062_MON_VAL_MIDDLE_POINT);
- return regmap_bulk_write(st->regmap, AD4062_REG_MON_VAL,
- &st->buf.be16, sizeof(st->buf.be16));
- }
- static irqreturn_t ad4062_irq_handler_thresh(int irq, void *private)
- {
- struct iio_dev *indio_dev = private;
- iio_push_event(indio_dev,
- IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_EITHER),
- iio_get_time_ns(indio_dev));
- return IRQ_HANDLED;
- }
- static irqreturn_t ad4062_irq_handler_drdy(int irq, void *private)
- {
- struct iio_dev *indio_dev = private;
- struct ad4062_state *st = iio_priv(indio_dev);
- if (iio_buffer_enabled(indio_dev) && iio_trigger_using_own(indio_dev))
- iio_trigger_poll(st->trigger);
- else
- complete(&st->completion);
- return IRQ_HANDLED;
- }
- static void ad4062_ibi_handler(struct i3c_device *i3cdev,
- const struct i3c_ibi_payload *payload)
- {
- struct ad4062_state *st = i3cdev_get_drvdata(i3cdev);
- if (st->wait_event) {
- iio_push_event(st->indio_dev,
- IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
- IIO_EV_TYPE_THRESH,
- IIO_EV_DIR_EITHER),
- iio_get_time_ns(st->indio_dev));
- return;
- }
- if (iio_buffer_enabled(st->indio_dev))
- iio_trigger_poll_nested(st->trigger);
- else
- complete(&st->completion);
- }
- static void ad4062_trigger_work(struct work_struct *work)
- {
- struct ad4062_state *st =
- container_of(work, struct ad4062_state, trig_conv);
- int ret;
- /*
- * Read current conversion, if at reg CONV_READ, stop bit triggers
- * next sample and does not need writing the address.
- */
- struct i3c_xfer xfer_sample = {
- .data.in = &st->buf.be32,
- .len = st->conv_sizeof,
- .rnw = true,
- };
- struct i3c_xfer xfer_trigger = {
- .data.out = &st->conv_addr,
- .len = sizeof(st->conv_addr),
- .rnw = false,
- };
- ret = i3c_device_do_xfers(st->i3cdev, &xfer_sample, 1, I3C_SDR);
- if (ret)
- return;
- iio_push_to_buffers_with_ts(st->indio_dev, &st->buf.be32, st->conv_sizeof,
- iio_get_time_ns(st->indio_dev));
- if (st->gpo_irq[1])
- return;
- i3c_device_do_xfers(st->i3cdev, &xfer_trigger, 1, I3C_SDR);
- }
- static irqreturn_t ad4062_poll_handler(int irq, void *p)
- {
- struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->indio_dev;
- struct ad4062_state *st = iio_priv(indio_dev);
- iio_trigger_notify_done(indio_dev->trig);
- schedule_work(&st->trig_conv);
- return IRQ_HANDLED;
- }
- static void ad4062_disable_ibi(void *data)
- {
- struct i3c_device *i3cdev = data;
- i3c_device_disable_ibi(i3cdev);
- }
- static void ad4062_free_ibi(void *data)
- {
- struct i3c_device *i3cdev = data;
- i3c_device_free_ibi(i3cdev);
- }
- static int ad4062_request_ibi(struct i3c_device *i3cdev)
- {
- const struct i3c_ibi_setup ibireq = {
- .max_payload_len = 1,
- .num_slots = 1,
- .handler = ad4062_ibi_handler,
- };
- int ret;
- ret = i3c_device_request_ibi(i3cdev, &ibireq);
- if (ret)
- return ret;
- ret = devm_add_action_or_reset(&i3cdev->dev, ad4062_free_ibi, i3cdev);
- if (ret)
- return ret;
- ret = i3c_device_enable_ibi(i3cdev);
- if (ret)
- return ret;
- return devm_add_action_or_reset(&i3cdev->dev, ad4062_disable_ibi, i3cdev);
- }
- static int ad4062_request_irq(struct iio_dev *indio_dev)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- struct device *dev = &st->i3cdev->dev;
- int ret;
- ret = fwnode_irq_get_byname(dev_fwnode(&st->i3cdev->dev), "gp0");
- if (ret == -EPROBE_DEFER)
- return ret;
- if (ret < 0) {
- st->gpo_irq[0] = false;
- ret = regmap_update_bits(st->regmap, AD4062_REG_ADC_IBI_EN,
- AD4062_REG_ADC_IBI_EN_MAX | AD4062_REG_ADC_IBI_EN_MIN,
- AD4062_REG_ADC_IBI_EN_MAX | AD4062_REG_ADC_IBI_EN_MIN);
- if (ret)
- return ret;
- } else {
- st->gpo_irq[0] = true;
- ret = devm_request_threaded_irq(dev, ret, NULL,
- ad4062_irq_handler_thresh,
- IRQF_ONESHOT, indio_dev->name,
- indio_dev);
- if (ret)
- return ret;
- }
- ret = fwnode_irq_get_byname(dev_fwnode(&st->i3cdev->dev), "gp1");
- if (ret == -EPROBE_DEFER)
- return ret;
- if (ret < 0) {
- st->gpo_irq[1] = false;
- return regmap_update_bits(st->regmap, AD4062_REG_ADC_IBI_EN,
- AD4062_REG_ADC_IBI_EN_CONV_TRIGGER,
- AD4062_REG_ADC_IBI_EN_CONV_TRIGGER);
- }
- st->gpo_irq[1] = true;
- return devm_request_irq(dev, ret, ad4062_irq_handler_drdy,
- IRQF_NO_THREAD, indio_dev->name, indio_dev);
- }
- static const struct iio_trigger_ops ad4062_trigger_ops = {
- .validate_device = &iio_trigger_validate_own_device,
- };
- static int ad4062_request_trigger(struct iio_dev *indio_dev)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- struct device *dev = &st->i3cdev->dev;
- int ret;
- st->trigger = devm_iio_trigger_alloc(dev, "%s-dev%d",
- indio_dev->name,
- iio_device_id(indio_dev));
- if (!st->trigger)
- return -ENOMEM;
- st->trigger->ops = &ad4062_trigger_ops;
- iio_trigger_set_drvdata(st->trigger, indio_dev);
- ret = devm_iio_trigger_register(dev, st->trigger);
- if (ret)
- return ret;
- indio_dev->trig = iio_trigger_get(st->trigger);
- return 0;
- }
- static const int ad4062_oversampling_avail[] = {
- 1, 2, 4, 8, 16, 32, 64, 128, /* 0 - 7 */
- 256, 512, 1024, 2048, 4096, /* 8 - 12 */
- };
- static int ad4062_read_avail(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan, const int **vals,
- int *type, int *len, long mask)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- int ret;
- switch (mask) {
- case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- *vals = ad4062_oversampling_avail;
- *len = ARRAY_SIZE(ad4062_oversampling_avail);
- *len -= st->chip->avg_max == 256 ? 4 : 0;
- *type = IIO_VAL_INT;
- return IIO_AVAIL_LIST;
- case IIO_CHAN_INFO_SAMP_FREQ:
- ret = ad4062_populate_sampling_frequency(st);
- if (ret)
- return ret;
- *vals = st->samp_freqs;
- *len = st->oversamp_ratio ? ARRAY_SIZE(ad4062_conversion_freqs) : 1;
- *type = IIO_VAL_INT;
- return IIO_AVAIL_LIST;
- default:
- return -EINVAL;
- }
- }
- static int ad4062_get_chan_scale(struct iio_dev *indio_dev, int *val, int *val2)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- const struct iio_scan_type *scan_type;
- /*
- * In burst averaging mode the averaging filter accumulates resulting
- * in a sample with increased precision.
- */
- scan_type = iio_get_current_scan_type(indio_dev, st->chip->channels);
- if (IS_ERR(scan_type))
- return PTR_ERR(scan_type);
- *val = (st->vref_uV * 2) / (MICRO / MILLI); /* signed */
- *val2 = scan_type->realbits - 1;
- return IIO_VAL_FRACTIONAL_LOG2;
- }
- static int ad4062_get_chan_calibscale(struct ad4062_state *st, int *val, int *val2)
- {
- int ret;
- ret = regmap_bulk_read(st->regmap, AD4062_REG_MON_VAL,
- &st->buf.be16, sizeof(st->buf.be16));
- if (ret)
- return ret;
- /* From datasheet: code out = code in × mon_val/0x8000 */
- *val = be16_to_cpu(st->buf.be16) * 2;
- *val2 = 16;
- return IIO_VAL_FRACTIONAL_LOG2;
- }
- static int ad4062_set_chan_calibscale(struct ad4062_state *st, int gain_int,
- int gain_frac)
- {
- /* Divide numerator and denumerator by known great common divider */
- const u32 mon_val = AD4062_MON_VAL_MIDDLE_POINT / 64;
- const u32 micro = MICRO / 64;
- const u32 gain_fp = gain_int * MICRO + gain_frac;
- const u32 reg_val = DIV_ROUND_CLOSEST(gain_fp * mon_val, micro);
- int ret;
- /* Checks if the gain is in range and the value fits the field */
- if (gain_int < 0 || gain_int > 1 || reg_val > BIT(16) - 1)
- return -EINVAL;
- st->buf.be16 = cpu_to_be16(reg_val);
- ret = regmap_bulk_write(st->regmap, AD4062_REG_MON_VAL,
- &st->buf.be16, sizeof(st->buf.be16));
- if (ret)
- return ret;
- /* Enable scale if gain is not equal to one */
- return regmap_update_bits(st->regmap, AD4062_REG_ADC_CONFIG,
- AD4062_REG_ADC_CONFIG_SCALE_EN_MSK,
- FIELD_PREP(AD4062_REG_ADC_CONFIG_SCALE_EN_MSK,
- !(gain_int == 1 && gain_frac == 0)));
- }
- static int ad4062_read_chan_raw(struct ad4062_state *st, int *val)
- {
- struct i3c_device *i3cdev = st->i3cdev;
- struct i3c_xfer xfer_trigger = {
- .data.out = &st->conv_addr,
- .len = sizeof(st->conv_addr),
- .rnw = false,
- };
- struct i3c_xfer xfer_sample = {
- .data.in = &st->buf.be32,
- .len = sizeof(st->buf.be32),
- .rnw = true,
- };
- int ret;
- PM_RUNTIME_ACQUIRE(&st->i3cdev->dev, pm);
- ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
- if (ret)
- return ret;
- ret = ad4062_set_operation_mode(st, st->mode);
- if (ret)
- return ret;
- reinit_completion(&st->completion);
- /* Change address pointer to trigger conversion */
- st->conv_addr = AD4062_REG_CONV_TRIGGER_32BITS;
- ret = i3c_device_do_xfers(i3cdev, &xfer_trigger, 1, I3C_SDR);
- if (ret)
- return ret;
- /*
- * Single sample read should be used only for oversampling and
- * sampling frequency pairs that take less than 1 sec.
- */
- ret = wait_for_completion_timeout(&st->completion,
- msecs_to_jiffies(1000));
- if (!ret)
- return -ETIMEDOUT;
- ret = i3c_device_do_xfers(i3cdev, &xfer_sample, 1, I3C_SDR);
- if (ret)
- return ret;
- *val = be32_to_cpu(st->buf.be32);
- return 0;
- }
- static int ad4062_read_raw_dispatch(struct ad4062_state *st,
- int *val, int *val2, long info)
- {
- if (st->wait_event)
- return -EBUSY;
- switch (info) {
- case IIO_CHAN_INFO_RAW:
- return ad4062_read_chan_raw(st, val);
- case IIO_CHAN_INFO_CALIBSCALE:
- return ad4062_get_chan_calibscale(st, val, val2);
- case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- return ad4062_get_oversampling_ratio(st, val);
- default:
- return -EINVAL;
- }
- }
- static int ad4062_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val, int *val2, long info)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- int ret;
- switch (info) {
- case IIO_CHAN_INFO_SCALE:
- return ad4062_get_chan_scale(indio_dev, val, val2);
- case IIO_CHAN_INFO_SAMP_FREQ:
- return ad4062_get_sampling_frequency(st, val);
- }
- if (!iio_device_claim_direct(indio_dev))
- return -EBUSY;
- ret = ad4062_read_raw_dispatch(st, val, val2, info);
- iio_device_release_direct(indio_dev);
- return ret ?: IIO_VAL_INT;
- }
- static int ad4062_write_raw_dispatch(struct ad4062_state *st, int val, int val2,
- long info)
- {
- if (st->wait_event)
- return -EBUSY;
- switch (info) {
- case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- return ad4062_set_oversampling_ratio(st, val, val2);
- case IIO_CHAN_INFO_CALIBSCALE:
- return ad4062_set_chan_calibscale(st, val, val2);
- default:
- return -EINVAL;
- }
- }
- static int ad4062_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan, int val,
- int val2, long info)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- int ret;
- switch (info) {
- case IIO_CHAN_INFO_SAMP_FREQ:
- return ad4062_set_sampling_frequency(st, val, val2);
- }
- if (!iio_device_claim_direct(indio_dev))
- return -EBUSY;
- ret = ad4062_write_raw_dispatch(st, val, val2, info);
- iio_device_release_direct(indio_dev);
- return ret;
- }
- static int pm_ad4062_monitor_mode_enable(struct ad4062_state *st)
- {
- int ret;
- PM_RUNTIME_ACQUIRE(&st->i3cdev->dev, pm);
- ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
- if (ret)
- return ret;
- return ad4062_set_operation_mode(st, AD4062_MONITOR_MODE);
- }
- static int ad4062_monitor_mode_enable(struct ad4062_state *st)
- {
- int ret;
- ret = pm_ad4062_monitor_mode_enable(st);
- if (ret)
- return ret;
- pm_runtime_get_noresume(&st->i3cdev->dev);
- return 0;
- }
- static int ad4062_monitor_mode_disable(struct ad4062_state *st)
- {
- pm_runtime_put_autosuspend(&st->i3cdev->dev);
- return 0;
- }
- static int ad4062_read_event_config(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- return st->wait_event;
- }
- static int ad4062_write_event_config_dispatch(struct iio_dev *indio_dev,
- bool state)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- int ret;
- if (st->wait_event == state)
- ret = 0;
- else if (state)
- ret = ad4062_monitor_mode_enable(st);
- else
- ret = ad4062_monitor_mode_disable(st);
- if (ret)
- return ret;
- st->wait_event = state;
- return 0;
- }
- static int ad4062_write_event_config(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir,
- bool state)
- {
- int ret;
- if (!iio_device_claim_direct(indio_dev))
- return -EBUSY;
- ret = ad4062_write_event_config_dispatch(indio_dev, state);
- iio_device_release_direct(indio_dev);
- return ret;
- }
- static int __ad4062_read_event_info_value(struct ad4062_state *st,
- enum iio_event_direction dir, int *val)
- {
- int ret;
- u8 reg;
- if (dir == IIO_EV_DIR_RISING)
- reg = AD4062_REG_MAX_LIMIT;
- else
- reg = AD4062_REG_MIN_LIMIT;
- ret = regmap_bulk_read(st->regmap, reg, &st->buf.be16,
- sizeof(st->buf.be16));
- if (ret)
- return ret;
- *val = sign_extend32(be16_to_cpu(st->buf.be16), AD4062_LIMIT_BITS - 1);
- return 0;
- }
- static int __ad4062_read_event_info_hysteresis(struct ad4062_state *st,
- enum iio_event_direction dir, int *val)
- {
- u8 reg;
- if (dir == IIO_EV_DIR_RISING)
- reg = AD4062_REG_MAX_HYST;
- else
- reg = AD4062_REG_MIN_HYST;
- return regmap_read(st->regmap, reg, val);
- }
- static int ad4062_read_event_config_dispatch(struct iio_dev *indio_dev,
- enum iio_event_direction dir,
- enum iio_event_info info, int *val)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- if (st->wait_event)
- return -EBUSY;
- switch (info) {
- case IIO_EV_INFO_VALUE:
- return __ad4062_read_event_info_value(st, dir, val);
- case IIO_EV_INFO_HYSTERESIS:
- return __ad4062_read_event_info_hysteresis(st, dir, val);
- default:
- return -EINVAL;
- }
- }
- static int ad4062_read_event_value(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir,
- enum iio_event_info info, int *val,
- int *val2)
- {
- int ret;
- if (!iio_device_claim_direct(indio_dev))
- return -EBUSY;
- ret = ad4062_read_event_config_dispatch(indio_dev, dir, info, val);
- iio_device_release_direct(indio_dev);
- return ret ?: IIO_VAL_INT;
- }
- static int __ad4062_write_event_info_value(struct ad4062_state *st,
- enum iio_event_direction dir, int val)
- {
- u8 reg;
- if (val != sign_extend32(val, AD4062_LIMIT_BITS - 1))
- return -EINVAL;
- if (dir == IIO_EV_DIR_RISING)
- reg = AD4062_REG_MAX_LIMIT;
- else
- reg = AD4062_REG_MIN_LIMIT;
- st->buf.be16 = cpu_to_be16(val);
- return regmap_bulk_write(st->regmap, reg, &st->buf.be16,
- sizeof(st->buf.be16));
- }
- static int __ad4062_write_event_info_hysteresis(struct ad4062_state *st,
- enum iio_event_direction dir, int val)
- {
- u8 reg;
- if (val > BIT(7) - 1)
- return -EINVAL;
- if (dir == IIO_EV_DIR_RISING)
- reg = AD4062_REG_MAX_HYST;
- else
- reg = AD4062_REG_MIN_HYST;
- return regmap_write(st->regmap, reg, val);
- }
- static int ad4062_write_event_value_dispatch(struct iio_dev *indio_dev,
- enum iio_event_type type,
- enum iio_event_direction dir,
- enum iio_event_info info, int val)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- if (st->wait_event)
- return -EBUSY;
- switch (type) {
- case IIO_EV_TYPE_THRESH:
- switch (info) {
- case IIO_EV_INFO_VALUE:
- return __ad4062_write_event_info_value(st, dir, val);
- case IIO_EV_INFO_HYSTERESIS:
- return __ad4062_write_event_info_hysteresis(st, dir, val);
- default:
- return -EINVAL;
- }
- default:
- return -EINVAL;
- }
- }
- static int ad4062_write_event_value(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir,
- enum iio_event_info info, int val,
- int val2)
- {
- int ret;
- if (!iio_device_claim_direct(indio_dev))
- return -EBUSY;
- ret = ad4062_write_event_value_dispatch(indio_dev, type, dir, info, val);
- iio_device_release_direct(indio_dev);
- return ret;
- }
- /*
- * The AD4062 in burst averaging mode increases realbits from 16-bits to
- * 20-bits, increasing the storagebits from 16-bits to 32-bits.
- */
- static inline size_t ad4062_sizeof_storagebits(struct ad4062_state *st)
- {
- const struct iio_scan_type *scan_type =
- iio_get_current_scan_type(st->indio_dev, st->chip->channels);
- return BITS_TO_BYTES(scan_type->storagebits);
- }
- /* Read registers only with realbits (no sign extension bytes) */
- static inline size_t ad4062_get_conv_addr(struct ad4062_state *st, size_t _sizeof)
- {
- if (st->gpo_irq[1])
- return _sizeof == sizeof(u32) ? AD4062_REG_CONV_READ_32BITS :
- AD4062_REG_CONV_READ_16BITS;
- return _sizeof == sizeof(u32) ? AD4062_REG_CONV_TRIGGER_32BITS :
- AD4062_REG_CONV_TRIGGER_16BITS;
- }
- static int pm_ad4062_triggered_buffer_postenable(struct ad4062_state *st)
- {
- int ret;
- PM_RUNTIME_ACQUIRE(&st->i3cdev->dev, pm);
- ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
- if (ret)
- return ret;
- if (st->wait_event)
- return -EBUSY;
- ret = ad4062_set_operation_mode(st, st->mode);
- if (ret)
- return ret;
- st->conv_sizeof = ad4062_sizeof_storagebits(st);
- st->conv_addr = ad4062_get_conv_addr(st, st->conv_sizeof);
- /* CONV_READ requires read to trigger first sample. */
- struct i3c_xfer xfer_sample[2] = {
- {
- .data.out = &st->conv_addr,
- .len = sizeof(st->conv_addr),
- .rnw = false,
- },
- {
- .data.in = &st->buf.be32,
- .len = sizeof(st->buf.be32),
- .rnw = true,
- }
- };
- return i3c_device_do_xfers(st->i3cdev, xfer_sample,
- st->gpo_irq[1] ? 2 : 1, I3C_SDR);
- }
- static int ad4062_triggered_buffer_postenable(struct iio_dev *indio_dev)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- int ret;
- ret = pm_ad4062_triggered_buffer_postenable(st);
- if (ret)
- return ret;
- pm_runtime_get_noresume(&st->i3cdev->dev);
- return 0;
- }
- static int ad4062_triggered_buffer_predisable(struct iio_dev *indio_dev)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- pm_runtime_put_autosuspend(&st->i3cdev->dev);
- return 0;
- }
- static const struct iio_buffer_setup_ops ad4062_triggered_buffer_setup_ops = {
- .postenable = &ad4062_triggered_buffer_postenable,
- .predisable = &ad4062_triggered_buffer_predisable,
- };
- static int ad4062_debugfs_reg_access(struct iio_dev *indio_dev, unsigned int reg,
- unsigned int writeval, unsigned int *readval)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- if (readval)
- return regmap_read(st->regmap, reg, readval);
- else
- return regmap_write(st->regmap, reg, writeval);
- }
- static int ad4062_get_current_scan_type(const struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan)
- {
- struct ad4062_state *st = iio_priv(indio_dev);
- return st->mode == AD4062_BURST_AVERAGING_MODE ?
- AD4062_SCAN_TYPE_BURST_AVG :
- AD4062_SCAN_TYPE_SAMPLE;
- }
- static const struct iio_info ad4062_info = {
- .read_raw = ad4062_read_raw,
- .write_raw = ad4062_write_raw,
- .read_avail = ad4062_read_avail,
- .read_event_config = ad4062_read_event_config,
- .write_event_config = ad4062_write_event_config,
- .read_event_value = ad4062_read_event_value,
- .write_event_value = ad4062_write_event_value,
- .event_attrs = &ad4062_event_attribute_group,
- .get_current_scan_type = ad4062_get_current_scan_type,
- .debugfs_reg_access = ad4062_debugfs_reg_access,
- };
- static const struct regmap_config ad4062_regmap_config = {
- .name = "ad4062",
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = AD4062_MAX_REG,
- .rd_table = &ad4062_regmap_rd_table,
- .wr_table = &ad4062_regmap_wr_table,
- .can_sleep = true,
- };
- static int ad4062_regulators_get(struct ad4062_state *st, bool *ref_sel)
- {
- struct device *dev = &st->i3cdev->dev;
- int ret;
- ret = devm_regulator_get_enable(dev, "vio");
- if (ret)
- return dev_err_probe(dev, ret, "Failed to enable vio voltage\n");
- st->vref_uV = devm_regulator_get_enable_read_voltage(dev, "ref");
- *ref_sel = st->vref_uV == -ENODEV;
- if (st->vref_uV < 0 && !*ref_sel)
- return dev_err_probe(dev, st->vref_uV,
- "Failed to enable and read ref voltage\n");
- if (*ref_sel) {
- st->vref_uV = devm_regulator_get_enable_read_voltage(dev, "vdd");
- if (st->vref_uV < 0)
- return dev_err_probe(dev, st->vref_uV,
- "Failed to enable and read vdd voltage\n");
- } else {
- ret = devm_regulator_get_enable(dev, "vdd");
- if (ret)
- return dev_err_probe(dev, ret,
- "Failed to enable vdd regulator\n");
- }
- return 0;
- }
- static int ad4062_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
- {
- return GPIO_LINE_DIRECTION_OUT;
- }
- static int ad4062_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
- {
- struct ad4062_state *st = gpiochip_get_data(gc);
- unsigned int reg_val = value ? AD4062_GP_STATIC_HIGH : AD4062_GP_STATIC_LOW;
- if (offset)
- return regmap_update_bits(st->regmap, AD4062_REG_GP_CONF,
- AD4062_REG_GP_CONF_MODE_MSK_1,
- FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_1, reg_val));
- else
- return regmap_update_bits(st->regmap, AD4062_REG_GP_CONF,
- AD4062_REG_GP_CONF_MODE_MSK_0,
- FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_0, reg_val));
- }
- static int ad4062_gpio_get(struct gpio_chip *gc, unsigned int offset)
- {
- struct ad4062_state *st = gpiochip_get_data(gc);
- unsigned int reg_val;
- int ret;
- ret = regmap_read(st->regmap, AD4062_REG_GP_CONF, ®_val);
- if (ret)
- return ret;
- if (offset)
- reg_val = FIELD_GET(AD4062_REG_GP_CONF_MODE_MSK_1, reg_val);
- else
- reg_val = FIELD_GET(AD4062_REG_GP_CONF_MODE_MSK_0, reg_val);
- return reg_val == AD4062_GP_STATIC_HIGH;
- }
- static void ad4062_gpio_disable(void *data)
- {
- struct ad4062_state *st = data;
- u8 val = FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_0, AD4062_GP_DISABLED) |
- FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_1, AD4062_GP_DISABLED);
- regmap_update_bits(st->regmap, AD4062_REG_GP_CONF,
- AD4062_REG_GP_CONF_MODE_MSK_1 | AD4062_REG_GP_CONF_MODE_MSK_0,
- val);
- }
- static int ad4062_gpio_init_valid_mask(struct gpio_chip *gc,
- unsigned long *valid_mask,
- unsigned int ngpios)
- {
- struct ad4062_state *st = gpiochip_get_data(gc);
- bitmap_zero(valid_mask, ngpios);
- for (unsigned int i = 0; i < ARRAY_SIZE(st->gpo_irq); i++)
- __assign_bit(i, valid_mask, !st->gpo_irq[i]);
- return 0;
- }
- static int ad4062_gpio_init(struct ad4062_state *st)
- {
- struct device *dev = &st->i3cdev->dev;
- struct gpio_chip *gc;
- u8 val, mask;
- int ret;
- if (!device_property_read_bool(dev, "gpio-controller"))
- return 0;
- gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
- if (!gc)
- return -ENOMEM;
- val = 0;
- mask = 0;
- if (!st->gpo_irq[0]) {
- mask |= AD4062_REG_GP_CONF_MODE_MSK_0;
- val |= FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_0, AD4062_GP_STATIC_LOW);
- }
- if (!st->gpo_irq[1]) {
- mask |= AD4062_REG_GP_CONF_MODE_MSK_1;
- val |= FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_1, AD4062_GP_STATIC_LOW);
- }
- ret = regmap_update_bits(st->regmap, AD4062_REG_GP_CONF,
- mask, val);
- if (ret)
- return ret;
- ret = devm_add_action_or_reset(dev, ad4062_gpio_disable, st);
- if (ret)
- return ret;
- gc->parent = dev;
- gc->label = st->chip->name;
- gc->owner = THIS_MODULE;
- gc->base = -1;
- gc->ngpio = 2;
- gc->init_valid_mask = ad4062_gpio_init_valid_mask;
- gc->get_direction = ad4062_gpio_get_direction;
- gc->set = ad4062_gpio_set;
- gc->get = ad4062_gpio_get;
- gc->can_sleep = true;
- ret = devm_gpiochip_add_data(dev, gc, st);
- if (ret)
- return dev_err_probe(dev, ret, "Unable to register GPIO chip\n");
- return 0;
- }
- static const struct i3c_device_id ad4062_id_table[] = {
- I3C_DEVICE(AD4062_I3C_VENDOR, AD4060_PROD_ID, &ad4060_chip_info),
- I3C_DEVICE(AD4062_I3C_VENDOR, AD4062_PROD_ID, &ad4062_chip_info),
- { }
- };
- MODULE_DEVICE_TABLE(i3c, ad4062_id_table);
- static int ad4062_probe(struct i3c_device *i3cdev)
- {
- const struct i3c_device_id *id = i3c_device_match_id(i3cdev, ad4062_id_table);
- const struct ad4062_chip_info *chip = id->data;
- struct device *dev = &i3cdev->dev;
- struct iio_dev *indio_dev;
- struct ad4062_state *st;
- bool ref_sel;
- int ret;
- indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
- if (!indio_dev)
- return -ENOMEM;
- st = iio_priv(indio_dev);
- st->i3cdev = i3cdev;
- i3cdev_set_drvdata(i3cdev, st);
- init_completion(&st->completion);
- ret = ad4062_regulators_get(st, &ref_sel);
- if (ret)
- return ret;
- st->regmap = devm_regmap_init_i3c(i3cdev, &ad4062_regmap_config);
- if (IS_ERR(st->regmap))
- return dev_err_probe(dev, PTR_ERR(st->regmap),
- "Failed to initialize regmap\n");
- st->mode = AD4062_SAMPLE_MODE;
- st->wait_event = false;
- st->chip = chip;
- st->sampling_frequency = 0;
- st->events_frequency = 0;
- st->oversamp_ratio = 0;
- st->indio_dev = indio_dev;
- indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->num_channels = 1;
- indio_dev->info = &ad4062_info;
- indio_dev->name = chip->name;
- indio_dev->channels = chip->channels;
- ret = ad4062_soft_reset(st);
- if (ret)
- return dev_err_probe(dev, ret, "AD4062 failed to soft reset\n");
- ret = ad4062_check_ids(st);
- if (ret)
- return ret;
- ret = ad4062_setup(indio_dev, indio_dev->channels, &ref_sel);
- if (ret)
- return ret;
- ret = ad4062_request_irq(indio_dev);
- if (ret)
- return ret;
- ret = ad4062_request_trigger(indio_dev);
- if (ret)
- return ret;
- ret = devm_iio_triggered_buffer_setup(&i3cdev->dev, indio_dev,
- iio_pollfunc_store_time,
- ad4062_poll_handler,
- &ad4062_triggered_buffer_setup_ops);
- if (ret)
- return ret;
- pm_runtime_set_active(dev);
- ret = devm_pm_runtime_enable(dev);
- if (ret)
- return dev_err_probe(dev, ret, "Failed to enable pm_runtime\n");
- pm_runtime_set_autosuspend_delay(dev, 1000);
- pm_runtime_use_autosuspend(dev);
- ret = ad4062_request_ibi(i3cdev);
- if (ret)
- return dev_err_probe(dev, ret, "Failed to request i3c ibi\n");
- ret = ad4062_gpio_init(st);
- if (ret)
- return ret;
- ret = devm_work_autocancel(dev, &st->trig_conv, ad4062_trigger_work);
- if (ret)
- return ret;
- return devm_iio_device_register(dev, indio_dev);
- }
- static int ad4062_runtime_suspend(struct device *dev)
- {
- struct ad4062_state *st = dev_get_drvdata(dev);
- return regmap_write(st->regmap, AD4062_REG_DEVICE_CONFIG,
- FIELD_PREP(AD4062_REG_DEVICE_CONFIG_POWER_MODE_MSK,
- AD4062_REG_DEVICE_CONFIG_LOW_POWER_MODE));
- }
- static int ad4062_runtime_resume(struct device *dev)
- {
- struct ad4062_state *st = dev_get_drvdata(dev);
- int ret;
- ret = regmap_clear_bits(st->regmap, AD4062_REG_DEVICE_CONFIG,
- AD4062_REG_DEVICE_CONFIG_POWER_MODE_MSK);
- if (ret)
- return ret;
- /* Wait device functional blocks to power up */
- fsleep(3 * USEC_PER_MSEC);
- return 0;
- }
- static DEFINE_RUNTIME_DEV_PM_OPS(ad4062_pm_ops,
- ad4062_runtime_suspend, ad4062_runtime_resume, NULL);
- static struct i3c_driver ad4062_driver = {
- .driver = {
- .name = "ad4062",
- .pm = pm_ptr(&ad4062_pm_ops),
- },
- .probe = ad4062_probe,
- .id_table = ad4062_id_table,
- };
- module_i3c_driver(ad4062_driver);
- MODULE_AUTHOR("Jorge Marques <jorge.marques@analog.com>");
- MODULE_DESCRIPTION("Analog Devices AD4062");
- MODULE_LICENSE("GPL");
|