162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Renesas R-Car GyroADC driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2016 Marek Vasut <marek.vasut@gmail.com> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/module.h> 962306a36Sopenharmony_ci#include <linux/platform_device.h> 1062306a36Sopenharmony_ci#include <linux/delay.h> 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/slab.h> 1362306a36Sopenharmony_ci#include <linux/io.h> 1462306a36Sopenharmony_ci#include <linux/clk.h> 1562306a36Sopenharmony_ci#include <linux/of.h> 1662306a36Sopenharmony_ci#include <linux/of_irq.h> 1762306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1862306a36Sopenharmony_ci#include <linux/of_platform.h> 1962306a36Sopenharmony_ci#include <linux/err.h> 2062306a36Sopenharmony_ci#include <linux/pm_runtime.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <linux/iio/iio.h> 2362306a36Sopenharmony_ci#include <linux/iio/sysfs.h> 2462306a36Sopenharmony_ci#include <linux/iio/trigger.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define DRIVER_NAME "rcar-gyroadc" 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/* GyroADC registers. */ 2962306a36Sopenharmony_ci#define RCAR_GYROADC_MODE_SELECT 0x00 3062306a36Sopenharmony_ci#define RCAR_GYROADC_MODE_SELECT_1_MB88101A 0x0 3162306a36Sopenharmony_ci#define RCAR_GYROADC_MODE_SELECT_2_ADCS7476 0x1 3262306a36Sopenharmony_ci#define RCAR_GYROADC_MODE_SELECT_3_MAX1162 0x3 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define RCAR_GYROADC_START_STOP 0x04 3562306a36Sopenharmony_ci#define RCAR_GYROADC_START_STOP_START BIT(0) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define RCAR_GYROADC_CLOCK_LENGTH 0x08 3862306a36Sopenharmony_ci#define RCAR_GYROADC_1_25MS_LENGTH 0x0c 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define RCAR_GYROADC_REALTIME_DATA(ch) (0x10 + ((ch) * 4)) 4162306a36Sopenharmony_ci#define RCAR_GYROADC_100MS_ADDED_DATA(ch) (0x30 + ((ch) * 4)) 4262306a36Sopenharmony_ci#define RCAR_GYROADC_10MS_AVG_DATA(ch) (0x50 + ((ch) * 4)) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define RCAR_GYROADC_FIFO_STATUS 0x70 4562306a36Sopenharmony_ci#define RCAR_GYROADC_FIFO_STATUS_EMPTY(ch) BIT(0 + (4 * (ch))) 4662306a36Sopenharmony_ci#define RCAR_GYROADC_FIFO_STATUS_FULL(ch) BIT(1 + (4 * (ch))) 4762306a36Sopenharmony_ci#define RCAR_GYROADC_FIFO_STATUS_ERROR(ch) BIT(2 + (4 * (ch))) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define RCAR_GYROADC_INTR 0x74 5062306a36Sopenharmony_ci#define RCAR_GYROADC_INTR_INT BIT(0) 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#define RCAR_GYROADC_INTENR 0x78 5362306a36Sopenharmony_ci#define RCAR_GYROADC_INTENR_INTEN BIT(0) 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define RCAR_GYROADC_SAMPLE_RATE 800 /* Hz */ 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define RCAR_GYROADC_RUNTIME_PM_DELAY_MS 2000 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cienum rcar_gyroadc_model { 6062306a36Sopenharmony_ci RCAR_GYROADC_MODEL_DEFAULT, 6162306a36Sopenharmony_ci RCAR_GYROADC_MODEL_R8A7792, 6262306a36Sopenharmony_ci}; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistruct rcar_gyroadc { 6562306a36Sopenharmony_ci struct device *dev; 6662306a36Sopenharmony_ci void __iomem *regs; 6762306a36Sopenharmony_ci struct clk *clk; 6862306a36Sopenharmony_ci struct regulator *vref[8]; 6962306a36Sopenharmony_ci unsigned int num_channels; 7062306a36Sopenharmony_ci enum rcar_gyroadc_model model; 7162306a36Sopenharmony_ci unsigned int mode; 7262306a36Sopenharmony_ci unsigned int sample_width; 7362306a36Sopenharmony_ci}; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistatic void rcar_gyroadc_hw_init(struct rcar_gyroadc *priv) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci const unsigned long clk_mhz = clk_get_rate(priv->clk) / 1000000; 7862306a36Sopenharmony_ci const unsigned long clk_mul = 7962306a36Sopenharmony_ci (priv->mode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) ? 10 : 5; 8062306a36Sopenharmony_ci unsigned long clk_len = clk_mhz * clk_mul; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* 8362306a36Sopenharmony_ci * According to the R-Car Gen2 datasheet Rev. 1.01, Sept 08 2014, 8462306a36Sopenharmony_ci * page 77-7, clock length must be even number. If it's odd number, 8562306a36Sopenharmony_ci * add one. 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ci if (clk_len & 1) 8862306a36Sopenharmony_ci clk_len++; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci /* Stop the GyroADC. */ 9162306a36Sopenharmony_ci writel(0, priv->regs + RCAR_GYROADC_START_STOP); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci /* Disable IRQ on V2H. */ 9462306a36Sopenharmony_ci if (priv->model == RCAR_GYROADC_MODEL_R8A7792) 9562306a36Sopenharmony_ci writel(0, priv->regs + RCAR_GYROADC_INTENR); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* Set mode and timing. */ 9862306a36Sopenharmony_ci writel(priv->mode, priv->regs + RCAR_GYROADC_MODE_SELECT); 9962306a36Sopenharmony_ci writel(clk_len, priv->regs + RCAR_GYROADC_CLOCK_LENGTH); 10062306a36Sopenharmony_ci writel(clk_mhz * 1250, priv->regs + RCAR_GYROADC_1_25MS_LENGTH); 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic void rcar_gyroadc_hw_start(struct rcar_gyroadc *priv) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci /* Start sampling. */ 10662306a36Sopenharmony_ci writel(RCAR_GYROADC_START_STOP_START, 10762306a36Sopenharmony_ci priv->regs + RCAR_GYROADC_START_STOP); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci /* 11062306a36Sopenharmony_ci * Wait for the first conversion to complete. This is longer than 11162306a36Sopenharmony_ci * the 1.25 mS in the datasheet because 1.25 mS is not enough for 11262306a36Sopenharmony_ci * the hardware to deliver the first sample and the hardware does 11362306a36Sopenharmony_ci * then return zeroes instead of valid data. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_ci mdelay(3); 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistatic void rcar_gyroadc_hw_stop(struct rcar_gyroadc *priv) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci /* Stop the GyroADC. */ 12162306a36Sopenharmony_ci writel(0, priv->regs + RCAR_GYROADC_START_STOP); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#define RCAR_GYROADC_CHAN(_idx) { \ 12562306a36Sopenharmony_ci .type = IIO_VOLTAGE, \ 12662306a36Sopenharmony_ci .indexed = 1, \ 12762306a36Sopenharmony_ci .channel = (_idx), \ 12862306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 12962306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_SCALE), \ 13062306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic const struct iio_chan_spec rcar_gyroadc_iio_channels_1[] = { 13462306a36Sopenharmony_ci RCAR_GYROADC_CHAN(0), 13562306a36Sopenharmony_ci RCAR_GYROADC_CHAN(1), 13662306a36Sopenharmony_ci RCAR_GYROADC_CHAN(2), 13762306a36Sopenharmony_ci RCAR_GYROADC_CHAN(3), 13862306a36Sopenharmony_ci}; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic const struct iio_chan_spec rcar_gyroadc_iio_channels_2[] = { 14162306a36Sopenharmony_ci RCAR_GYROADC_CHAN(0), 14262306a36Sopenharmony_ci RCAR_GYROADC_CHAN(1), 14362306a36Sopenharmony_ci RCAR_GYROADC_CHAN(2), 14462306a36Sopenharmony_ci RCAR_GYROADC_CHAN(3), 14562306a36Sopenharmony_ci RCAR_GYROADC_CHAN(4), 14662306a36Sopenharmony_ci RCAR_GYROADC_CHAN(5), 14762306a36Sopenharmony_ci RCAR_GYROADC_CHAN(6), 14862306a36Sopenharmony_ci RCAR_GYROADC_CHAN(7), 14962306a36Sopenharmony_ci}; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic const struct iio_chan_spec rcar_gyroadc_iio_channels_3[] = { 15262306a36Sopenharmony_ci RCAR_GYROADC_CHAN(0), 15362306a36Sopenharmony_ci RCAR_GYROADC_CHAN(1), 15462306a36Sopenharmony_ci RCAR_GYROADC_CHAN(2), 15562306a36Sopenharmony_ci RCAR_GYROADC_CHAN(3), 15662306a36Sopenharmony_ci RCAR_GYROADC_CHAN(4), 15762306a36Sopenharmony_ci RCAR_GYROADC_CHAN(5), 15862306a36Sopenharmony_ci RCAR_GYROADC_CHAN(6), 15962306a36Sopenharmony_ci RCAR_GYROADC_CHAN(7), 16062306a36Sopenharmony_ci}; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic int rcar_gyroadc_set_power(struct rcar_gyroadc *priv, bool on) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci struct device *dev = priv->dev; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci if (on) { 16762306a36Sopenharmony_ci return pm_runtime_resume_and_get(dev); 16862306a36Sopenharmony_ci } else { 16962306a36Sopenharmony_ci pm_runtime_mark_last_busy(dev); 17062306a36Sopenharmony_ci return pm_runtime_put_autosuspend(dev); 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic int rcar_gyroadc_read_raw(struct iio_dev *indio_dev, 17562306a36Sopenharmony_ci struct iio_chan_spec const *chan, 17662306a36Sopenharmony_ci int *val, int *val2, long mask) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci struct rcar_gyroadc *priv = iio_priv(indio_dev); 17962306a36Sopenharmony_ci struct regulator *consumer; 18062306a36Sopenharmony_ci unsigned int datareg = RCAR_GYROADC_REALTIME_DATA(chan->channel); 18162306a36Sopenharmony_ci unsigned int vref; 18262306a36Sopenharmony_ci int ret; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci /* 18562306a36Sopenharmony_ci * MB88101 is special in that it has only single regulator for 18662306a36Sopenharmony_ci * all four channels. 18762306a36Sopenharmony_ci */ 18862306a36Sopenharmony_ci if (priv->mode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) 18962306a36Sopenharmony_ci consumer = priv->vref[0]; 19062306a36Sopenharmony_ci else 19162306a36Sopenharmony_ci consumer = priv->vref[chan->channel]; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci switch (mask) { 19462306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 19562306a36Sopenharmony_ci if (chan->type != IIO_VOLTAGE) 19662306a36Sopenharmony_ci return -EINVAL; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci /* Channel not connected. */ 19962306a36Sopenharmony_ci if (!consumer) 20062306a36Sopenharmony_ci return -EINVAL; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci ret = iio_device_claim_direct_mode(indio_dev); 20362306a36Sopenharmony_ci if (ret) 20462306a36Sopenharmony_ci return ret; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci ret = rcar_gyroadc_set_power(priv, true); 20762306a36Sopenharmony_ci if (ret < 0) { 20862306a36Sopenharmony_ci iio_device_release_direct_mode(indio_dev); 20962306a36Sopenharmony_ci return ret; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci *val = readl(priv->regs + datareg); 21362306a36Sopenharmony_ci *val &= BIT(priv->sample_width) - 1; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci ret = rcar_gyroadc_set_power(priv, false); 21662306a36Sopenharmony_ci iio_device_release_direct_mode(indio_dev); 21762306a36Sopenharmony_ci if (ret < 0) 21862306a36Sopenharmony_ci return ret; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci return IIO_VAL_INT; 22162306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 22262306a36Sopenharmony_ci /* Channel not connected. */ 22362306a36Sopenharmony_ci if (!consumer) 22462306a36Sopenharmony_ci return -EINVAL; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci vref = regulator_get_voltage(consumer); 22762306a36Sopenharmony_ci *val = vref / 1000; 22862306a36Sopenharmony_ci *val2 = 1 << priv->sample_width; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL; 23162306a36Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 23262306a36Sopenharmony_ci *val = RCAR_GYROADC_SAMPLE_RATE; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci return IIO_VAL_INT; 23562306a36Sopenharmony_ci default: 23662306a36Sopenharmony_ci return -EINVAL; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_cistatic int rcar_gyroadc_reg_access(struct iio_dev *indio_dev, 24162306a36Sopenharmony_ci unsigned int reg, unsigned int writeval, 24262306a36Sopenharmony_ci unsigned int *readval) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci struct rcar_gyroadc *priv = iio_priv(indio_dev); 24562306a36Sopenharmony_ci unsigned int maxreg = RCAR_GYROADC_FIFO_STATUS; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci if (readval == NULL) 24862306a36Sopenharmony_ci return -EINVAL; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci if (reg % 4) 25162306a36Sopenharmony_ci return -EINVAL; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci /* Handle the V2H case with extra interrupt block. */ 25462306a36Sopenharmony_ci if (priv->model == RCAR_GYROADC_MODEL_R8A7792) 25562306a36Sopenharmony_ci maxreg = RCAR_GYROADC_INTENR; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci if (reg > maxreg) 25862306a36Sopenharmony_ci return -EINVAL; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci *readval = readl(priv->regs + reg); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci return 0; 26362306a36Sopenharmony_ci} 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_cistatic const struct iio_info rcar_gyroadc_iio_info = { 26662306a36Sopenharmony_ci .read_raw = rcar_gyroadc_read_raw, 26762306a36Sopenharmony_ci .debugfs_reg_access = rcar_gyroadc_reg_access, 26862306a36Sopenharmony_ci}; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic const struct of_device_id rcar_gyroadc_match[] = { 27162306a36Sopenharmony_ci { 27262306a36Sopenharmony_ci /* R-Car compatible GyroADC */ 27362306a36Sopenharmony_ci .compatible = "renesas,rcar-gyroadc", 27462306a36Sopenharmony_ci .data = (void *)RCAR_GYROADC_MODEL_DEFAULT, 27562306a36Sopenharmony_ci }, { 27662306a36Sopenharmony_ci /* R-Car V2H specialty with interrupt registers. */ 27762306a36Sopenharmony_ci .compatible = "renesas,r8a7792-gyroadc", 27862306a36Sopenharmony_ci .data = (void *)RCAR_GYROADC_MODEL_R8A7792, 27962306a36Sopenharmony_ci }, { 28062306a36Sopenharmony_ci /* sentinel */ 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci}; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, rcar_gyroadc_match); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_cistatic const struct of_device_id rcar_gyroadc_child_match[] __maybe_unused = { 28762306a36Sopenharmony_ci /* Mode 1 ADCs */ 28862306a36Sopenharmony_ci { 28962306a36Sopenharmony_ci .compatible = "fujitsu,mb88101a", 29062306a36Sopenharmony_ci .data = (void *)RCAR_GYROADC_MODE_SELECT_1_MB88101A, 29162306a36Sopenharmony_ci }, 29262306a36Sopenharmony_ci /* Mode 2 ADCs */ 29362306a36Sopenharmony_ci { 29462306a36Sopenharmony_ci .compatible = "ti,adcs7476", 29562306a36Sopenharmony_ci .data = (void *)RCAR_GYROADC_MODE_SELECT_2_ADCS7476, 29662306a36Sopenharmony_ci }, { 29762306a36Sopenharmony_ci .compatible = "ti,adc121", 29862306a36Sopenharmony_ci .data = (void *)RCAR_GYROADC_MODE_SELECT_2_ADCS7476, 29962306a36Sopenharmony_ci }, { 30062306a36Sopenharmony_ci .compatible = "adi,ad7476", 30162306a36Sopenharmony_ci .data = (void *)RCAR_GYROADC_MODE_SELECT_2_ADCS7476, 30262306a36Sopenharmony_ci }, 30362306a36Sopenharmony_ci /* Mode 3 ADCs */ 30462306a36Sopenharmony_ci { 30562306a36Sopenharmony_ci .compatible = "maxim,max1162", 30662306a36Sopenharmony_ci .data = (void *)RCAR_GYROADC_MODE_SELECT_3_MAX1162, 30762306a36Sopenharmony_ci }, { 30862306a36Sopenharmony_ci .compatible = "maxim,max11100", 30962306a36Sopenharmony_ci .data = (void *)RCAR_GYROADC_MODE_SELECT_3_MAX1162, 31062306a36Sopenharmony_ci }, 31162306a36Sopenharmony_ci { /* sentinel */ } 31262306a36Sopenharmony_ci}; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev) 31562306a36Sopenharmony_ci{ 31662306a36Sopenharmony_ci const struct of_device_id *of_id; 31762306a36Sopenharmony_ci const struct iio_chan_spec *channels; 31862306a36Sopenharmony_ci struct rcar_gyroadc *priv = iio_priv(indio_dev); 31962306a36Sopenharmony_ci struct device *dev = priv->dev; 32062306a36Sopenharmony_ci struct device_node *np = dev->of_node; 32162306a36Sopenharmony_ci struct device_node *child; 32262306a36Sopenharmony_ci struct regulator *vref; 32362306a36Sopenharmony_ci unsigned int reg; 32462306a36Sopenharmony_ci unsigned int adcmode = -1, childmode; 32562306a36Sopenharmony_ci unsigned int sample_width; 32662306a36Sopenharmony_ci unsigned int num_channels; 32762306a36Sopenharmony_ci int ret, first = 1; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci for_each_child_of_node(np, child) { 33062306a36Sopenharmony_ci of_id = of_match_node(rcar_gyroadc_child_match, child); 33162306a36Sopenharmony_ci if (!of_id) { 33262306a36Sopenharmony_ci dev_err(dev, "Ignoring unsupported ADC \"%pOFn\".", 33362306a36Sopenharmony_ci child); 33462306a36Sopenharmony_ci continue; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci childmode = (uintptr_t)of_id->data; 33862306a36Sopenharmony_ci switch (childmode) { 33962306a36Sopenharmony_ci case RCAR_GYROADC_MODE_SELECT_1_MB88101A: 34062306a36Sopenharmony_ci sample_width = 12; 34162306a36Sopenharmony_ci channels = rcar_gyroadc_iio_channels_1; 34262306a36Sopenharmony_ci num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_1); 34362306a36Sopenharmony_ci break; 34462306a36Sopenharmony_ci case RCAR_GYROADC_MODE_SELECT_2_ADCS7476: 34562306a36Sopenharmony_ci sample_width = 15; 34662306a36Sopenharmony_ci channels = rcar_gyroadc_iio_channels_2; 34762306a36Sopenharmony_ci num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_2); 34862306a36Sopenharmony_ci break; 34962306a36Sopenharmony_ci case RCAR_GYROADC_MODE_SELECT_3_MAX1162: 35062306a36Sopenharmony_ci sample_width = 16; 35162306a36Sopenharmony_ci channels = rcar_gyroadc_iio_channels_3; 35262306a36Sopenharmony_ci num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_3); 35362306a36Sopenharmony_ci break; 35462306a36Sopenharmony_ci default: 35562306a36Sopenharmony_ci goto err_e_inval; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci /* 35962306a36Sopenharmony_ci * MB88101 is special in that it's only a single chip taking 36062306a36Sopenharmony_ci * up all the CHS lines. Thus, the DT binding is also special 36162306a36Sopenharmony_ci * and has no reg property. If we run into such ADC, handle 36262306a36Sopenharmony_ci * it here. 36362306a36Sopenharmony_ci */ 36462306a36Sopenharmony_ci if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) { 36562306a36Sopenharmony_ci reg = 0; 36662306a36Sopenharmony_ci } else { 36762306a36Sopenharmony_ci ret = of_property_read_u32(child, "reg", ®); 36862306a36Sopenharmony_ci if (ret) { 36962306a36Sopenharmony_ci dev_err(dev, 37062306a36Sopenharmony_ci "Failed to get child reg property of ADC \"%pOFn\".\n", 37162306a36Sopenharmony_ci child); 37262306a36Sopenharmony_ci goto err_of_node_put; 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci /* Channel number is too high. */ 37662306a36Sopenharmony_ci if (reg >= num_channels) { 37762306a36Sopenharmony_ci dev_err(dev, 37862306a36Sopenharmony_ci "Only %i channels supported with %pOFn, but reg = <%i>.\n", 37962306a36Sopenharmony_ci num_channels, child, reg); 38062306a36Sopenharmony_ci goto err_e_inval; 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci /* Child node selected different mode than the rest. */ 38562306a36Sopenharmony_ci if (!first && (adcmode != childmode)) { 38662306a36Sopenharmony_ci dev_err(dev, 38762306a36Sopenharmony_ci "Channel %i uses different ADC mode than the rest.\n", 38862306a36Sopenharmony_ci reg); 38962306a36Sopenharmony_ci goto err_e_inval; 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci /* Channel is valid, grab the regulator. */ 39362306a36Sopenharmony_ci dev->of_node = child; 39462306a36Sopenharmony_ci vref = devm_regulator_get(dev, "vref"); 39562306a36Sopenharmony_ci dev->of_node = np; 39662306a36Sopenharmony_ci if (IS_ERR(vref)) { 39762306a36Sopenharmony_ci dev_dbg(dev, "Channel %i 'vref' supply not connected.\n", 39862306a36Sopenharmony_ci reg); 39962306a36Sopenharmony_ci ret = PTR_ERR(vref); 40062306a36Sopenharmony_ci goto err_of_node_put; 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci priv->vref[reg] = vref; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if (!first) 40662306a36Sopenharmony_ci continue; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci /* First child node which passed sanity tests. */ 40962306a36Sopenharmony_ci adcmode = childmode; 41062306a36Sopenharmony_ci first = 0; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci priv->num_channels = num_channels; 41362306a36Sopenharmony_ci priv->mode = childmode; 41462306a36Sopenharmony_ci priv->sample_width = sample_width; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci indio_dev->channels = channels; 41762306a36Sopenharmony_ci indio_dev->num_channels = num_channels; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci /* 42062306a36Sopenharmony_ci * MB88101 is special and we only have one such device 42162306a36Sopenharmony_ci * attached to the GyroADC at a time, so if we found it, 42262306a36Sopenharmony_ci * we can stop parsing here. 42362306a36Sopenharmony_ci */ 42462306a36Sopenharmony_ci if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) { 42562306a36Sopenharmony_ci of_node_put(child); 42662306a36Sopenharmony_ci break; 42762306a36Sopenharmony_ci } 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci if (first) { 43162306a36Sopenharmony_ci dev_err(dev, "No valid ADC channels found, aborting.\n"); 43262306a36Sopenharmony_ci return -EINVAL; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci return 0; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cierr_e_inval: 43862306a36Sopenharmony_ci ret = -EINVAL; 43962306a36Sopenharmony_cierr_of_node_put: 44062306a36Sopenharmony_ci of_node_put(child); 44162306a36Sopenharmony_ci return ret; 44262306a36Sopenharmony_ci} 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic void rcar_gyroadc_deinit_supplies(struct iio_dev *indio_dev) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci struct rcar_gyroadc *priv = iio_priv(indio_dev); 44762306a36Sopenharmony_ci unsigned int i; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci for (i = 0; i < priv->num_channels; i++) { 45062306a36Sopenharmony_ci if (!priv->vref[i]) 45162306a36Sopenharmony_ci continue; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci regulator_disable(priv->vref[i]); 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci} 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_cistatic int rcar_gyroadc_init_supplies(struct iio_dev *indio_dev) 45862306a36Sopenharmony_ci{ 45962306a36Sopenharmony_ci struct rcar_gyroadc *priv = iio_priv(indio_dev); 46062306a36Sopenharmony_ci struct device *dev = priv->dev; 46162306a36Sopenharmony_ci unsigned int i; 46262306a36Sopenharmony_ci int ret; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci for (i = 0; i < priv->num_channels; i++) { 46562306a36Sopenharmony_ci if (!priv->vref[i]) 46662306a36Sopenharmony_ci continue; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci ret = regulator_enable(priv->vref[i]); 46962306a36Sopenharmony_ci if (ret) { 47062306a36Sopenharmony_ci dev_err(dev, "Failed to enable regulator %i (ret=%i)\n", 47162306a36Sopenharmony_ci i, ret); 47262306a36Sopenharmony_ci goto err; 47362306a36Sopenharmony_ci } 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci return 0; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_cierr: 47962306a36Sopenharmony_ci rcar_gyroadc_deinit_supplies(indio_dev); 48062306a36Sopenharmony_ci return ret; 48162306a36Sopenharmony_ci} 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_cistatic int rcar_gyroadc_probe(struct platform_device *pdev) 48462306a36Sopenharmony_ci{ 48562306a36Sopenharmony_ci struct device *dev = &pdev->dev; 48662306a36Sopenharmony_ci struct rcar_gyroadc *priv; 48762306a36Sopenharmony_ci struct iio_dev *indio_dev; 48862306a36Sopenharmony_ci int ret; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); 49162306a36Sopenharmony_ci if (!indio_dev) 49262306a36Sopenharmony_ci return -ENOMEM; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci priv = iio_priv(indio_dev); 49562306a36Sopenharmony_ci priv->dev = dev; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci priv->regs = devm_platform_ioremap_resource(pdev, 0); 49862306a36Sopenharmony_ci if (IS_ERR(priv->regs)) 49962306a36Sopenharmony_ci return PTR_ERR(priv->regs); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci priv->clk = devm_clk_get(dev, "fck"); 50262306a36Sopenharmony_ci if (IS_ERR(priv->clk)) 50362306a36Sopenharmony_ci return dev_err_probe(dev, PTR_ERR(priv->clk), 50462306a36Sopenharmony_ci "Failed to get IF clock\n"); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci ret = rcar_gyroadc_parse_subdevs(indio_dev); 50762306a36Sopenharmony_ci if (ret) 50862306a36Sopenharmony_ci return ret; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci ret = rcar_gyroadc_init_supplies(indio_dev); 51162306a36Sopenharmony_ci if (ret) 51262306a36Sopenharmony_ci return ret; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci priv->model = (uintptr_t)of_device_get_match_data(&pdev->dev); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci platform_set_drvdata(pdev, indio_dev); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci indio_dev->name = DRIVER_NAME; 51962306a36Sopenharmony_ci indio_dev->info = &rcar_gyroadc_iio_info; 52062306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci ret = clk_prepare_enable(priv->clk); 52362306a36Sopenharmony_ci if (ret) { 52462306a36Sopenharmony_ci dev_err(dev, "Could not prepare or enable the IF clock.\n"); 52562306a36Sopenharmony_ci goto err_clk_if_enable; 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci pm_runtime_set_autosuspend_delay(dev, RCAR_GYROADC_RUNTIME_PM_DELAY_MS); 52962306a36Sopenharmony_ci pm_runtime_use_autosuspend(dev); 53062306a36Sopenharmony_ci pm_runtime_enable(dev); 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(dev); 53362306a36Sopenharmony_ci if (ret) 53462306a36Sopenharmony_ci goto err_power_up; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci rcar_gyroadc_hw_init(priv); 53762306a36Sopenharmony_ci rcar_gyroadc_hw_start(priv); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci ret = iio_device_register(indio_dev); 54062306a36Sopenharmony_ci if (ret) { 54162306a36Sopenharmony_ci dev_err(dev, "Couldn't register IIO device.\n"); 54262306a36Sopenharmony_ci goto err_iio_device_register; 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci pm_runtime_put_sync(dev); 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci return 0; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_cierr_iio_device_register: 55062306a36Sopenharmony_ci rcar_gyroadc_hw_stop(priv); 55162306a36Sopenharmony_ci pm_runtime_put_sync(dev); 55262306a36Sopenharmony_cierr_power_up: 55362306a36Sopenharmony_ci pm_runtime_disable(dev); 55462306a36Sopenharmony_ci pm_runtime_set_suspended(dev); 55562306a36Sopenharmony_ci clk_disable_unprepare(priv->clk); 55662306a36Sopenharmony_cierr_clk_if_enable: 55762306a36Sopenharmony_ci rcar_gyroadc_deinit_supplies(indio_dev); 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci return ret; 56062306a36Sopenharmony_ci} 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cistatic int rcar_gyroadc_remove(struct platform_device *pdev) 56362306a36Sopenharmony_ci{ 56462306a36Sopenharmony_ci struct iio_dev *indio_dev = platform_get_drvdata(pdev); 56562306a36Sopenharmony_ci struct rcar_gyroadc *priv = iio_priv(indio_dev); 56662306a36Sopenharmony_ci struct device *dev = priv->dev; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci iio_device_unregister(indio_dev); 56962306a36Sopenharmony_ci pm_runtime_get_sync(dev); 57062306a36Sopenharmony_ci rcar_gyroadc_hw_stop(priv); 57162306a36Sopenharmony_ci pm_runtime_put_sync(dev); 57262306a36Sopenharmony_ci pm_runtime_disable(dev); 57362306a36Sopenharmony_ci pm_runtime_set_suspended(dev); 57462306a36Sopenharmony_ci clk_disable_unprepare(priv->clk); 57562306a36Sopenharmony_ci rcar_gyroadc_deinit_supplies(indio_dev); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci return 0; 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_cistatic int rcar_gyroadc_suspend(struct device *dev) 58162306a36Sopenharmony_ci{ 58262306a36Sopenharmony_ci struct iio_dev *indio_dev = dev_get_drvdata(dev); 58362306a36Sopenharmony_ci struct rcar_gyroadc *priv = iio_priv(indio_dev); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci rcar_gyroadc_hw_stop(priv); 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci return 0; 58862306a36Sopenharmony_ci} 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_cistatic int rcar_gyroadc_resume(struct device *dev) 59162306a36Sopenharmony_ci{ 59262306a36Sopenharmony_ci struct iio_dev *indio_dev = dev_get_drvdata(dev); 59362306a36Sopenharmony_ci struct rcar_gyroadc *priv = iio_priv(indio_dev); 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci rcar_gyroadc_hw_start(priv); 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci return 0; 59862306a36Sopenharmony_ci} 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_cistatic const struct dev_pm_ops rcar_gyroadc_pm_ops = { 60162306a36Sopenharmony_ci RUNTIME_PM_OPS(rcar_gyroadc_suspend, rcar_gyroadc_resume, NULL) 60262306a36Sopenharmony_ci}; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_cistatic struct platform_driver rcar_gyroadc_driver = { 60562306a36Sopenharmony_ci .probe = rcar_gyroadc_probe, 60662306a36Sopenharmony_ci .remove = rcar_gyroadc_remove, 60762306a36Sopenharmony_ci .driver = { 60862306a36Sopenharmony_ci .name = DRIVER_NAME, 60962306a36Sopenharmony_ci .of_match_table = rcar_gyroadc_match, 61062306a36Sopenharmony_ci .pm = pm_ptr(&rcar_gyroadc_pm_ops), 61162306a36Sopenharmony_ci }, 61262306a36Sopenharmony_ci}; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_cimodule_platform_driver(rcar_gyroadc_driver); 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ciMODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); 61762306a36Sopenharmony_ciMODULE_DESCRIPTION("Renesas R-Car GyroADC driver"); 61862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 619