summaryrefslogtreecommitdiff
path: root/drivers/iio/adc/meson_saradc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/adc/meson_saradc.c')
-rw-r--r--drivers/iio/adc/meson_saradc.c656
1 files changed, 411 insertions, 245 deletions
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index 66dc452d643a..47cd350498a0 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -12,11 +12,11 @@
#include <linux/io.h>
#include <linux/iio/iio.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/nvmem-consumer.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/of_irq.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -71,7 +71,7 @@
#define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18)
#define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16)
#define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10
- #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5
+ #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 6
#define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8)
#define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0)
@@ -155,6 +155,15 @@
*/
#define MESON_SAR_ADC_REG11 0x2c
#define MESON_SAR_ADC_REG11_BANDGAP_EN BIT(13)
+ #define MESON_SAR_ADC_REG11_CMV_SEL BIT(6)
+ #define MESON_SAR_ADC_REG11_VREF_VOLTAGE BIT(5)
+ #define MESON_SAR_ADC_REG11_EOC BIT(1)
+ #define MESON_SAR_ADC_REG11_VREF_SEL BIT(0)
+
+#define MESON_SAR_ADC_REG12 0x30
+ #define MESON_SAR_ADC_REG12_MPLL0_UNKNOWN BIT(0)
+ #define MESON_SAR_ADC_REG12_MPLL1_UNKNOWN BIT(1)
+ #define MESON_SAR_ADC_REG12_MPLL2_UNKNOWN BIT(2)
#define MESON_SAR_ADC_REG13 0x34
#define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8)
@@ -162,6 +171,7 @@
#define MESON_SAR_ADC_MAX_FIFO_SIZE 32
#define MESON_SAR_ADC_TIMEOUT 100 /* ms */
#define MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL 6
+#define MESON_SAR_ADC_VOLTAGE_AND_MUX_CHANNEL 7
#define MESON_SAR_ADC_TEMP_OFFSET 27
/* temperature sensor calibration information in eFuse */
@@ -201,29 +211,22 @@
.datasheet_name = "TEMP_SENSOR", \
}
-static const struct iio_chan_spec meson_sar_adc_iio_channels[] = {
- MESON_SAR_ADC_CHAN(0),
- MESON_SAR_ADC_CHAN(1),
- MESON_SAR_ADC_CHAN(2),
- MESON_SAR_ADC_CHAN(3),
- MESON_SAR_ADC_CHAN(4),
- MESON_SAR_ADC_CHAN(5),
- MESON_SAR_ADC_CHAN(6),
- MESON_SAR_ADC_CHAN(7),
- IIO_CHAN_SOFT_TIMESTAMP(8),
-};
+#define MESON_SAR_ADC_MUX(_chan, _sel) { \
+ .type = IIO_VOLTAGE, \
+ .channel = _chan, \
+ .indexed = 1, \
+ .address = MESON_SAR_ADC_VOLTAGE_AND_MUX_CHANNEL, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) | \
+ BIT(IIO_CHAN_INFO_CALIBSCALE), \
+ .datasheet_name = "SAR_ADC_MUX_"#_sel, \
+}
-static const struct iio_chan_spec meson_sar_adc_and_temp_iio_channels[] = {
- MESON_SAR_ADC_CHAN(0),
- MESON_SAR_ADC_CHAN(1),
- MESON_SAR_ADC_CHAN(2),
- MESON_SAR_ADC_CHAN(3),
- MESON_SAR_ADC_CHAN(4),
- MESON_SAR_ADC_CHAN(5),
- MESON_SAR_ADC_CHAN(6),
- MESON_SAR_ADC_CHAN(7),
- MESON_SAR_ADC_TEMP_CHAN(8),
- IIO_CHAN_SOFT_TIMESTAMP(9),
+enum meson_sar_adc_vref_sel {
+ VREF_CALIBATION_VOLTAGE = 0,
+ VREF_VDDA = 1,
};
enum meson_sar_adc_avg_mode {
@@ -248,15 +251,87 @@ enum meson_sar_adc_chan7_mux_sel {
CHAN7_MUX_CH7_INPUT = 0x7,
};
+enum meson_sar_adc_channel_index {
+ NUM_CHAN_0,
+ NUM_CHAN_1,
+ NUM_CHAN_2,
+ NUM_CHAN_3,
+ NUM_CHAN_4,
+ NUM_CHAN_5,
+ NUM_CHAN_6,
+ NUM_CHAN_7,
+ NUM_CHAN_TEMP,
+ NUM_MUX_0_VSS,
+ NUM_MUX_1_VDD_DIV4,
+ NUM_MUX_2_VDD_DIV2,
+ NUM_MUX_3_VDD_MUL3_DIV4,
+ NUM_MUX_4_VDD,
+};
+
+static enum meson_sar_adc_chan7_mux_sel chan7_mux_values[] = {
+ CHAN7_MUX_VSS,
+ CHAN7_MUX_VDD_DIV4,
+ CHAN7_MUX_VDD_DIV2,
+ CHAN7_MUX_VDD_MUL3_DIV4,
+ CHAN7_MUX_VDD,
+};
+
+static const char * const chan7_mux_names[] = {
+ [CHAN7_MUX_VSS] = "gnd",
+ [CHAN7_MUX_VDD_DIV4] = "0.25vdd",
+ [CHAN7_MUX_VDD_DIV2] = "0.5vdd",
+ [CHAN7_MUX_VDD_MUL3_DIV4] = "0.75vdd",
+ [CHAN7_MUX_VDD] = "vdd",
+};
+
+static const struct iio_chan_spec meson_sar_adc_iio_channels[] = {
+ MESON_SAR_ADC_CHAN(NUM_CHAN_0),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_1),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_2),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_3),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_4),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_5),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_6),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_7),
+ MESON_SAR_ADC_MUX(NUM_MUX_0_VSS, 0),
+ MESON_SAR_ADC_MUX(NUM_MUX_1_VDD_DIV4, 1),
+ MESON_SAR_ADC_MUX(NUM_MUX_2_VDD_DIV2, 2),
+ MESON_SAR_ADC_MUX(NUM_MUX_3_VDD_MUL3_DIV4, 3),
+ MESON_SAR_ADC_MUX(NUM_MUX_4_VDD, 4),
+};
+
+static const struct iio_chan_spec meson_sar_adc_and_temp_iio_channels[] = {
+ MESON_SAR_ADC_CHAN(NUM_CHAN_0),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_1),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_2),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_3),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_4),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_5),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_6),
+ MESON_SAR_ADC_CHAN(NUM_CHAN_7),
+ MESON_SAR_ADC_TEMP_CHAN(NUM_CHAN_TEMP),
+ MESON_SAR_ADC_MUX(NUM_MUX_0_VSS, 0),
+ MESON_SAR_ADC_MUX(NUM_MUX_1_VDD_DIV4, 1),
+ MESON_SAR_ADC_MUX(NUM_MUX_2_VDD_DIV2, 2),
+ MESON_SAR_ADC_MUX(NUM_MUX_3_VDD_MUL3_DIV4, 3),
+ MESON_SAR_ADC_MUX(NUM_MUX_4_VDD, 4),
+};
+
struct meson_sar_adc_param {
bool has_bl30_integration;
unsigned long clock_rate;
- u32 bandgap_reg;
unsigned int resolution;
const struct regmap_config *regmap_config;
u8 temperature_trimming_bits;
unsigned int temperature_multiplier;
unsigned int temperature_divider;
+ u8 disable_ring_counter;
+ bool has_vref_select;
+ u8 vref_select;
+ u8 cmv_select;
+ u8 adc_eoc;
+ enum meson_sar_adc_vref_sel vref_voltage;
+ bool enable_mpll_clock_workaround;
};
struct meson_sar_adc_data {
@@ -276,12 +351,15 @@ struct meson_sar_adc_priv {
struct clk *adc_div_clk;
struct clk_divider clk_div;
struct completion done;
+ /* lock to protect against multiple access to the device */
+ struct mutex lock;
int calibbias;
int calibscale;
struct regmap *tsc_regmap;
bool temperature_sensor_calibrated;
u8 temperature_sensor_coefficient;
u16 temperature_sensor_adc_val;
+ enum meson_sar_adc_chan7_mux_sel chan7_mux_sel;
};
static const struct regmap_config meson_sar_adc_regmap_config_gxbb = {
@@ -298,6 +376,17 @@ static const struct regmap_config meson_sar_adc_regmap_config_meson8 = {
.max_register = MESON_SAR_ADC_DELTA_10,
};
+static const struct iio_chan_spec *
+find_channel_by_num(struct iio_dev *indio_dev, int num)
+{
+ int i;
+
+ for (i = 0; i < indio_dev->num_channels; i++)
+ if (indio_dev->channels[i].channel == num)
+ return &indio_dev->channels[i];
+ return NULL;
+}
+
static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
@@ -322,22 +411,32 @@ static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val)
static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
- int regval, timeout = 10000;
+ int val;
/*
* NOTE: we need a small delay before reading the status, otherwise
* the sample engine may not have started internally (which would
* seem to us that sampling is already finished).
*/
- do {
- udelay(1);
- regmap_read(priv->regmap, MESON_SAR_ADC_REG0, &regval);
- } while (FIELD_GET(MESON_SAR_ADC_REG0_BUSY_MASK, regval) && timeout--);
+ udelay(1);
+ return regmap_read_poll_timeout_atomic(priv->regmap, MESON_SAR_ADC_REG0, val,
+ !FIELD_GET(MESON_SAR_ADC_REG0_BUSY_MASK, val),
+ 1, 10000);
+}
- if (timeout < 0)
- return -ETIMEDOUT;
+static void meson_sar_adc_set_chan7_mux(struct iio_dev *indio_dev,
+ enum meson_sar_adc_chan7_mux_sel sel)
+{
+ struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
+ u32 regval;
- return 0;
+ regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, sel);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
+ MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval);
+
+ usleep_range(10, 20);
+
+ priv->chan7_mux_sel = sel;
}
static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
@@ -345,24 +444,23 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
int *val)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
+ struct device *dev = indio_dev->dev.parent;
int regval, fifo_chan, fifo_val, count;
- if(!wait_for_completion_timeout(&priv->done,
+ if (!wait_for_completion_timeout(&priv->done,
msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT)))
return -ETIMEDOUT;
count = meson_sar_adc_get_fifo_count(indio_dev);
if (count != 1) {
- dev_err(&indio_dev->dev,
- "ADC FIFO has %d element(s) instead of one\n", count);
+ dev_err(dev, "ADC FIFO has %d element(s) instead of one\n", count);
return -EINVAL;
}
regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &regval);
fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval);
if (fifo_chan != chan->address) {
- dev_err(&indio_dev->dev,
- "ADC FIFO entry belongs to channel %d instead of %lu\n",
+ dev_err(dev, "ADC FIFO entry belongs to channel %d instead of %lu\n",
fifo_chan, chan->address);
return -EINVAL;
}
@@ -434,20 +532,16 @@ static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev,
regmap_update_bits(priv->regmap,
MESON_SAR_ADC_DELTA_10,
MESON_SAR_ADC_DELTA_10_TEMP_SEL, regval);
- }
-}
-
-static void meson_sar_adc_set_chan7_mux(struct iio_dev *indio_dev,
- enum meson_sar_adc_chan7_mux_sel sel)
-{
- struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
- u32 regval;
-
- regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, sel);
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
- MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval);
+ } else if (chan->address == MESON_SAR_ADC_VOLTAGE_AND_MUX_CHANNEL) {
+ enum meson_sar_adc_chan7_mux_sel sel;
- usleep_range(10, 20);
+ if (chan->channel == NUM_CHAN_7)
+ sel = CHAN7_MUX_CH7_INPUT;
+ else
+ sel = chan7_mux_values[chan->channel - NUM_MUX_0_VSS];
+ if (sel != priv->chan7_mux_sel)
+ meson_sar_adc_set_chan7_mux(indio_dev, sel);
+ }
}
static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev)
@@ -456,62 +550,57 @@ static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev)
reinit_completion(&priv->done);
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
- MESON_SAR_ADC_REG0_FIFO_IRQ_EN,
- MESON_SAR_ADC_REG0_FIFO_IRQ_EN);
+ regmap_set_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_FIFO_IRQ_EN);
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
- MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
- MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
+ regmap_set_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
- MESON_SAR_ADC_REG0_SAMPLING_START,
- MESON_SAR_ADC_REG0_SAMPLING_START);
+ regmap_set_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_SAMPLING_START);
}
static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
- MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0);
+ regmap_clear_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_FIFO_IRQ_EN);
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
- MESON_SAR_ADC_REG0_SAMPLING_STOP,
- MESON_SAR_ADC_REG0_SAMPLING_STOP);
+ regmap_set_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_SAMPLING_STOP);
/* wait until all modules are stopped */
meson_sar_adc_wait_busy_clear(indio_dev);
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
- MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 0);
+ regmap_clear_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
}
static int meson_sar_adc_lock(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
- int val, timeout = 10000;
+ int val, ret;
- mutex_lock(&indio_dev->mlock);
+ mutex_lock(&priv->lock);
if (priv->param->has_bl30_integration) {
/* prevent BL30 from using the SAR ADC while we are using it */
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
- MESON_SAR_ADC_DELAY_KERNEL_BUSY,
+ regmap_set_bits(priv->regmap, MESON_SAR_ADC_DELAY,
MESON_SAR_ADC_DELAY_KERNEL_BUSY);
+ udelay(1);
+
/*
* wait until BL30 releases it's lock (so we can use the SAR
* ADC)
*/
- do {
- udelay(1);
- regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val);
- } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--);
-
- if (timeout < 0) {
- mutex_unlock(&indio_dev->mlock);
- return -ETIMEDOUT;
+ ret = regmap_read_poll_timeout_atomic(priv->regmap, MESON_SAR_ADC_DELAY, val,
+ !(val & MESON_SAR_ADC_DELAY_BL30_BUSY),
+ 1, 10000);
+ if (ret) {
+ mutex_unlock(&priv->lock);
+ return ret;
}
}
@@ -524,10 +613,10 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev)
if (priv->param->has_bl30_integration)
/* allow BL30 to use the SAR ADC again */
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
- MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0);
+ regmap_clear_bits(priv->regmap, MESON_SAR_ADC_DELAY,
+ MESON_SAR_ADC_DELAY_KERNEL_BUSY);
- mutex_unlock(&indio_dev->mlock);
+ mutex_unlock(&priv->lock);
}
static void meson_sar_adc_clear_fifo(struct iio_dev *indio_dev)
@@ -550,6 +639,7 @@ static int meson_sar_adc_get_sample(struct iio_dev *indio_dev,
int *val)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
+ struct device *dev = indio_dev->dev.parent;
int ret;
if (chan->type == IIO_TEMP && !priv->temperature_sensor_calibrated)
@@ -573,8 +663,7 @@ static int meson_sar_adc_get_sample(struct iio_dev *indio_dev,
meson_sar_adc_unlock(indio_dev);
if (ret) {
- dev_warn(indio_dev->dev.parent,
- "failed to read sample for channel %lu: %d\n",
+ dev_warn(dev, "failed to read sample for channel %lu: %d\n",
chan->address, ret);
return ret;
}
@@ -587,6 +676,7 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
+ struct device *dev = indio_dev->dev.parent;
int ret;
switch (mask) {
@@ -603,9 +693,7 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev,
if (chan->type == IIO_VOLTAGE) {
ret = regulator_get_voltage(priv->vref);
if (ret < 0) {
- dev_err(indio_dev->dev.parent,
- "failed to get vref voltage: %d\n",
- ret);
+ dev_err(dev, "failed to get vref voltage: %d\n", ret);
return ret;
}
@@ -650,11 +738,11 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
void __iomem *base)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
+ struct device *dev = indio_dev->dev.parent;
struct clk_init_data init;
const char *clk_parents[1];
- init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_div",
- dev_name(indio_dev->dev.parent));
+ init.name = devm_kasprintf(dev, GFP_KERNEL, "%s#adc_div", dev_name(dev));
if (!init.name)
return -ENOMEM;
@@ -670,13 +758,11 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
priv->clk_div.hw.init = &init;
priv->clk_div.flags = 0;
- priv->adc_div_clk = devm_clk_register(&indio_dev->dev,
- &priv->clk_div.hw);
+ priv->adc_div_clk = devm_clk_register(dev, &priv->clk_div.hw);
if (WARN_ON(IS_ERR(priv->adc_div_clk)))
return PTR_ERR(priv->adc_div_clk);
- init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_en",
- dev_name(indio_dev->dev.parent));
+ init.name = devm_kasprintf(dev, GFP_KERNEL, "%s#adc_en", dev_name(dev));
if (!init.name)
return -ENOMEM;
@@ -690,7 +776,7 @@ static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
priv->clk_gate.bit_idx = __ffs(MESON_SAR_ADC_REG3_CLK_EN);
priv->clk_gate.hw.init = &init;
- priv->adc_clk = devm_clk_register(&indio_dev->dev, &priv->clk_gate.hw);
+ priv->adc_clk = devm_clk_register(dev, &priv->clk_gate.hw);
if (WARN_ON(IS_ERR(priv->adc_clk)))
return PTR_ERR(priv->adc_clk);
@@ -701,12 +787,12 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
u8 *buf, trimming_bits, trimming_mask, upper_adc_val;
+ struct device *dev = indio_dev->dev.parent;
struct nvmem_cell *temperature_calib;
size_t read_len;
int ret;
- temperature_calib = devm_nvmem_cell_get(indio_dev->dev.parent,
- "temperature_calib");
+ temperature_calib = devm_nvmem_cell_get(dev, "temperature_calib");
if (IS_ERR(temperature_calib)) {
ret = PTR_ERR(temperature_calib);
@@ -717,30 +803,21 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
if (ret == -ENODEV)
return 0;
- return dev_err_probe(indio_dev->dev.parent, ret,
- "failed to get temperature_calib cell\n");
+ return dev_err_probe(dev, ret, "failed to get temperature_calib cell\n");
}
- priv->tsc_regmap =
- syscon_regmap_lookup_by_phandle(indio_dev->dev.parent->of_node,
- "amlogic,hhi-sysctrl");
- if (IS_ERR(priv->tsc_regmap)) {
- dev_err(indio_dev->dev.parent,
- "failed to get amlogic,hhi-sysctrl regmap\n");
- return PTR_ERR(priv->tsc_regmap);
- }
+ priv->tsc_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "amlogic,hhi-sysctrl");
+ if (IS_ERR(priv->tsc_regmap))
+ return dev_err_probe(dev, PTR_ERR(priv->tsc_regmap),
+ "failed to get amlogic,hhi-sysctrl regmap\n");
read_len = MESON_SAR_ADC_EFUSE_BYTES;
buf = nvmem_cell_read(temperature_calib, &read_len);
- if (IS_ERR(buf)) {
- dev_err(indio_dev->dev.parent,
- "failed to read temperature_calib cell\n");
- return PTR_ERR(buf);
- } else if (read_len != MESON_SAR_ADC_EFUSE_BYTES) {
+ if (IS_ERR(buf))
+ return dev_err_probe(dev, PTR_ERR(buf), "failed to read temperature_calib cell\n");
+ if (read_len != MESON_SAR_ADC_EFUSE_BYTES) {
kfree(buf);
- dev_err(indio_dev->dev.parent,
- "invalid read size of temperature_calib cell\n");
- return -EINVAL;
+ return dev_err_probe(dev, -EINVAL, "invalid read size of temperature_calib cell\n");
}
trimming_bits = priv->param->temperature_trimming_bits;
@@ -765,6 +842,7 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
static int meson_sar_adc_init(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
+ struct device *dev = indio_dev->dev.parent;
int regval, i, ret;
/*
@@ -790,17 +868,16 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
* disable this bit as seems to be only relevant for Meson6 (based
* on the vendor driver), which we don't support at the moment.
*/
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
- MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL, 0);
+ regmap_clear_bits(priv->regmap, MESON_SAR_ADC_REG0,
+ MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL);
/* disable all channels by default */
regmap_write(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 0x0);
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
- MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE, 0);
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
- MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY,
- MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY);
+ regmap_clear_bits(priv->regmap, MESON_SAR_ADC_REG3,
+ MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE);
+ regmap_set_bits(priv->regmap, MESON_SAR_ADC_REG3,
+ MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY);
/* delay between two samples = (10+1) * 1uS */
regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
@@ -835,6 +912,18 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK,
regval);
+ regmap_set_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
+ MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW);
+
+ regmap_set_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
+ MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW);
+
+ regmap_set_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
+ MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW);
+
+ regmap_set_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
+ MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW);
+
/*
* set up the input channel muxes in MESON_SAR_ADC_AUX_SW
* (2 = SAR_ADC_CH2, 3 = SAR_ADC_CH3, ...) and enable
@@ -849,12 +938,10 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval);
if (priv->temperature_sensor_calibrated) {
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
- MESON_SAR_ADC_DELTA_10_TS_REVE1,
- MESON_SAR_ADC_DELTA_10_TS_REVE1);
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
- MESON_SAR_ADC_DELTA_10_TS_REVE0,
- MESON_SAR_ADC_DELTA_10_TS_REVE0);
+ regmap_set_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
+ MESON_SAR_ADC_DELTA_10_TS_REVE1);
+ regmap_set_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
+ MESON_SAR_ADC_DELTA_10_TS_REVE0);
/*
* set bits [3:0] of the TSC (temperature sensor coefficient)
@@ -881,25 +968,57 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
regval);
}
} else {
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
- MESON_SAR_ADC_DELTA_10_TS_REVE1, 0);
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
- MESON_SAR_ADC_DELTA_10_TS_REVE0, 0);
+ regmap_clear_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
+ MESON_SAR_ADC_DELTA_10_TS_REVE1);
+ regmap_clear_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
+ MESON_SAR_ADC_DELTA_10_TS_REVE0);
}
- ret = clk_set_parent(priv->adc_sel_clk, priv->clkin);
- if (ret) {
- dev_err(indio_dev->dev.parent,
- "failed to set adc parent to clkin\n");
- return ret;
+ regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN,
+ priv->param->disable_ring_counter);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
+ MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN,
+ regval);
+
+ if (priv->param->regmap_config->max_register >= MESON_SAR_ADC_REG11) {
+ regval = FIELD_PREP(MESON_SAR_ADC_REG11_EOC, priv->param->adc_eoc);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
+ MESON_SAR_ADC_REG11_EOC, regval);
+
+ if (priv->param->has_vref_select) {
+ regval = FIELD_PREP(MESON_SAR_ADC_REG11_VREF_SEL,
+ priv->param->vref_select);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
+ MESON_SAR_ADC_REG11_VREF_SEL, regval);
+ }
+
+ regval = FIELD_PREP(MESON_SAR_ADC_REG11_VREF_VOLTAGE,
+ priv->param->vref_voltage);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
+ MESON_SAR_ADC_REG11_VREF_VOLTAGE, regval);
+
+ regval = FIELD_PREP(MESON_SAR_ADC_REG11_CMV_SEL,
+ priv->param->cmv_select);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
+ MESON_SAR_ADC_REG11_CMV_SEL, regval);
+
+ if (priv->param->enable_mpll_clock_workaround) {
+ dev_warn(dev,
+ "Enabling unknown bits to make the MPLL clocks work. This may change so always update dtbs and kernel together\n");
+ regmap_write(priv->regmap, MESON_SAR_ADC_REG12,
+ MESON_SAR_ADC_REG12_MPLL0_UNKNOWN |
+ MESON_SAR_ADC_REG12_MPLL1_UNKNOWN |
+ MESON_SAR_ADC_REG12_MPLL2_UNKNOWN);
+ }
}
+ ret = clk_set_parent(priv->adc_sel_clk, priv->clkin);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to set adc parent to clkin\n");
+
ret = clk_set_rate(priv->adc_clk, priv->param->clock_rate);
- if (ret) {
- dev_err(indio_dev->dev.parent,
- "failed to set adc clock rate\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to set adc clock rate\n");
return 0;
}
@@ -907,56 +1026,50 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev)
static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
- const struct meson_sar_adc_param *param = priv->param;
- u32 enable_mask;
- if (param->bandgap_reg == MESON_SAR_ADC_REG11)
- enable_mask = MESON_SAR_ADC_REG11_BANDGAP_EN;
+ if (priv->param->regmap_config->max_register >= MESON_SAR_ADC_REG11)
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
+ MESON_SAR_ADC_REG11_BANDGAP_EN,
+ on_off ? MESON_SAR_ADC_REG11_BANDGAP_EN : 0);
else
- enable_mask = MESON_SAR_ADC_DELTA_10_TS_VBG_EN;
-
- regmap_update_bits(priv->regmap, param->bandgap_reg, enable_mask,
- on_off ? enable_mask : 0);
+ regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
+ MESON_SAR_ADC_DELTA_10_TS_VBG_EN,
+ on_off ? MESON_SAR_ADC_DELTA_10_TS_VBG_EN : 0);
}
static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
+ struct device *dev = indio_dev->dev.parent;
int ret;
u32 regval;
ret = meson_sar_adc_lock(indio_dev);
- if (ret)
+ if (ret) {
+ dev_err(dev, "failed to lock adc\n");
goto err_lock;
+ }
ret = regulator_enable(priv->vref);
if (ret < 0) {
- dev_err(indio_dev->dev.parent,
- "failed to enable vref regulator\n");
+ dev_err(dev, "failed to enable vref regulator\n");
goto err_vref;
}
- ret = clk_prepare_enable(priv->core_clk);
- if (ret) {
- dev_err(indio_dev->dev.parent, "failed to enable core clk\n");
- goto err_core_clk;
- }
-
regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
meson_sar_adc_set_bandgap(indio_dev, true);
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
- MESON_SAR_ADC_REG3_ADC_EN,
- MESON_SAR_ADC_REG3_ADC_EN);
+ regmap_set_bits(priv->regmap, MESON_SAR_ADC_REG3,
+ MESON_SAR_ADC_REG3_ADC_EN);
udelay(5);
ret = clk_prepare_enable(priv->adc_clk);
if (ret) {
- dev_err(indio_dev->dev.parent, "failed to enable adc clk\n");
+ dev_err(dev, "failed to enable adc clk\n");
goto err_adc_clk;
}
@@ -965,11 +1078,9 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
return 0;
err_adc_clk:
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
- MESON_SAR_ADC_REG3_ADC_EN, 0);
+ regmap_clear_bits(priv->regmap, MESON_SAR_ADC_REG3,
+ MESON_SAR_ADC_REG3_ADC_EN);
meson_sar_adc_set_bandgap(indio_dev, false);
- clk_disable_unprepare(priv->core_clk);
-err_core_clk:
regulator_disable(priv->vref);
err_vref:
meson_sar_adc_unlock(indio_dev);
@@ -977,29 +1088,30 @@ err_lock:
return ret;
}
-static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
+static void meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
{
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
int ret;
+ /*
+ * If taking the lock fails we have to assume that BL30 is broken. The
+ * best we can do then is to release the resources anyhow.
+ */
ret = meson_sar_adc_lock(indio_dev);
if (ret)
- return ret;
+ dev_err(indio_dev->dev.parent, "Failed to lock ADC (%pE)\n", ERR_PTR(ret));
clk_disable_unprepare(priv->adc_clk);
- regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
- MESON_SAR_ADC_REG3_ADC_EN, 0);
+ regmap_clear_bits(priv->regmap, MESON_SAR_ADC_REG3,
+ MESON_SAR_ADC_REG3_ADC_EN);
meson_sar_adc_set_bandgap(indio_dev, false);
- clk_disable_unprepare(priv->core_clk);
-
regulator_disable(priv->vref);
- meson_sar_adc_unlock(indio_dev);
-
- return 0;
+ if (!ret)
+ meson_sar_adc_unlock(indio_dev);
}
static irqreturn_t meson_sar_adc_irq(int irq, void *data)
@@ -1033,7 +1145,8 @@ static int meson_sar_adc_calib(struct iio_dev *indio_dev)
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4);
usleep_range(10, 20);
ret = meson_sar_adc_get_sample(indio_dev,
- &indio_dev->channels[7],
+ find_channel_by_num(indio_dev,
+ NUM_MUX_1_VDD_DIV4),
MEAN_AVERAGING, EIGHT_SAMPLES, &value0);
if (ret < 0)
goto out;
@@ -1041,7 +1154,8 @@ static int meson_sar_adc_calib(struct iio_dev *indio_dev)
meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4);
usleep_range(10, 20);
ret = meson_sar_adc_get_sample(indio_dev,
- &indio_dev->channels[7],
+ find_channel_by_num(indio_dev,
+ NUM_MUX_3_VDD_MUL3_DIV4),
MEAN_AVERAGING, EIGHT_SAMPLES, &value1);
if (ret < 0)
goto out;
@@ -1062,14 +1176,28 @@ out:
return ret;
}
+static int read_label(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ char *label)
+{
+ if (chan->type == IIO_TEMP)
+ return sysfs_emit(label, "temp-sensor\n");
+ if (chan->type == IIO_VOLTAGE && chan->channel >= NUM_MUX_0_VSS)
+ return sysfs_emit(label, "%s\n",
+ chan7_mux_names[chan->channel - NUM_MUX_0_VSS]);
+ if (chan->type == IIO_VOLTAGE)
+ return sysfs_emit(label, "channel-%d\n", chan->channel);
+ return 0;
+}
+
static const struct iio_info meson_sar_adc_iio_info = {
.read_raw = meson_sar_adc_iio_info_read_raw,
+ .read_label = read_label,
};
static const struct meson_sar_adc_param meson_sar_adc_meson8_param = {
.has_bl30_integration = false,
.clock_rate = 1150000,
- .bandgap_reg = MESON_SAR_ADC_DELTA_10,
.regmap_config = &meson_sar_adc_regmap_config_meson8,
.resolution = 10,
.temperature_trimming_bits = 4,
@@ -1080,7 +1208,6 @@ static const struct meson_sar_adc_param meson_sar_adc_meson8_param = {
static const struct meson_sar_adc_param meson_sar_adc_meson8b_param = {
.has_bl30_integration = false,
.clock_rate = 1150000,
- .bandgap_reg = MESON_SAR_ADC_DELTA_10,
.regmap_config = &meson_sar_adc_regmap_config_meson8,
.resolution = 10,
.temperature_trimming_bits = 5,
@@ -1091,17 +1218,54 @@ static const struct meson_sar_adc_param meson_sar_adc_meson8b_param = {
static const struct meson_sar_adc_param meson_sar_adc_gxbb_param = {
.has_bl30_integration = true,
.clock_rate = 1200000,
- .bandgap_reg = MESON_SAR_ADC_REG11,
.regmap_config = &meson_sar_adc_regmap_config_gxbb,
.resolution = 10,
+ .vref_voltage = 1,
+ .cmv_select = 1,
};
static const struct meson_sar_adc_param meson_sar_adc_gxl_param = {
.has_bl30_integration = true,
.clock_rate = 1200000,
- .bandgap_reg = MESON_SAR_ADC_REG11,
.regmap_config = &meson_sar_adc_regmap_config_gxbb,
.resolution = 12,
+ .disable_ring_counter = 1,
+ .vref_voltage = 1,
+ .cmv_select = 1,
+};
+
+static const struct meson_sar_adc_param meson_sar_adc_gxlx_param = {
+ .has_bl30_integration = true,
+ .clock_rate = 1200000,
+ .regmap_config = &meson_sar_adc_regmap_config_gxbb,
+ .resolution = 12,
+ .disable_ring_counter = 1,
+ .vref_voltage = 1,
+ .cmv_select = true,
+ .enable_mpll_clock_workaround = true,
+};
+
+static const struct meson_sar_adc_param meson_sar_adc_axg_param = {
+ .has_bl30_integration = true,
+ .clock_rate = 1200000,
+ .regmap_config = &meson_sar_adc_regmap_config_gxbb,
+ .resolution = 12,
+ .disable_ring_counter = 1,
+ .vref_voltage = 1,
+ .has_vref_select = true,
+ .vref_select = VREF_VDDA,
+ .cmv_select = 1,
+};
+
+static const struct meson_sar_adc_param meson_sar_adc_g12a_param = {
+ .has_bl30_integration = false,
+ .clock_rate = 1200000,
+ .regmap_config = &meson_sar_adc_regmap_config_gxbb,
+ .resolution = 12,
+ .disable_ring_counter = 1,
+ .adc_eoc = 1,
+ .has_vref_select = true,
+ .vref_select = VREF_VDDA,
};
static const struct meson_sar_adc_data meson_sar_adc_meson8_data = {
@@ -1129,18 +1293,23 @@ static const struct meson_sar_adc_data meson_sar_adc_gxl_data = {
.name = "meson-gxl-saradc",
};
+static const struct meson_sar_adc_data meson_sar_adc_gxlx_data = {
+ .param = &meson_sar_adc_gxlx_param,
+ .name = "meson-gxlx-saradc",
+};
+
static const struct meson_sar_adc_data meson_sar_adc_gxm_data = {
.param = &meson_sar_adc_gxl_param,
.name = "meson-gxm-saradc",
};
static const struct meson_sar_adc_data meson_sar_adc_axg_data = {
- .param = &meson_sar_adc_gxl_param,
+ .param = &meson_sar_adc_axg_param,
.name = "meson-axg-saradc",
};
static const struct meson_sar_adc_data meson_sar_adc_g12a_data = {
- .param = &meson_sar_adc_gxl_param,
+ .param = &meson_sar_adc_g12a_param,
.name = "meson-g12a-saradc",
};
@@ -1161,6 +1330,9 @@ static const struct of_device_id meson_sar_adc_of_match[] = {
.compatible = "amlogic,meson-gxl-saradc",
.data = &meson_sar_adc_gxl_data,
}, {
+ .compatible = "amlogic,meson-gxlx-saradc",
+ .data = &meson_sar_adc_gxlx_data,
+ }, {
.compatible = "amlogic,meson-gxm-saradc",
.data = &meson_sar_adc_gxm_data,
}, {
@@ -1170,7 +1342,7 @@ static const struct of_device_id meson_sar_adc_of_match[] = {
.compatible = "amlogic,meson-g12a-saradc",
.data = &meson_sar_adc_g12a_data,
},
- { /* sentinel */ }
+ { }
};
MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match);
@@ -1178,24 +1350,21 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
{
const struct meson_sar_adc_data *match_data;
struct meson_sar_adc_priv *priv;
+ struct device *dev = &pdev->dev;
struct iio_dev *indio_dev;
void __iomem *base;
int irq, ret;
- indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
- if (!indio_dev) {
- dev_err(&pdev->dev, "failed allocating iio device\n");
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
+ if (!indio_dev)
return -ENOMEM;
- }
priv = iio_priv(indio_dev);
init_completion(&priv->done);
- match_data = of_device_get_match_data(&pdev->dev);
- if (!match_data) {
- dev_err(&pdev->dev, "failed to get match data\n");
- return -ENODEV;
- }
+ match_data = of_device_get_match_data(dev);
+ if (!match_data)
+ return dev_err_probe(dev, -ENODEV, "failed to get match data\n");
priv->param = match_data->param;
@@ -1207,64 +1376,44 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
if (IS_ERR(base))
return PTR_ERR(base);
- priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
- priv->param->regmap_config);
+ priv->regmap = devm_regmap_init_mmio(dev, base, priv->param->regmap_config);
if (IS_ERR(priv->regmap))
- return PTR_ERR(priv->regmap);
+ return dev_err_probe(dev, PTR_ERR(priv->regmap), "failed to init regmap\n");
- irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+ irq = irq_of_parse_and_map(dev->of_node, 0);
if (!irq)
- return -EINVAL;
+ return dev_err_probe(dev, -EINVAL, "failed to get irq\n");
- ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED,
- dev_name(&pdev->dev), indio_dev);
+ ret = devm_request_irq(dev, irq, meson_sar_adc_irq, IRQF_SHARED, dev_name(dev), indio_dev);
if (ret)
- return ret;
+ return dev_err_probe(dev, ret, "failed to request irq\n");
- priv->clkin = devm_clk_get(&pdev->dev, "clkin");
- if (IS_ERR(priv->clkin)) {
- dev_err(&pdev->dev, "failed to get clkin\n");
- return PTR_ERR(priv->clkin);
- }
+ priv->clkin = devm_clk_get(dev, "clkin");
+ if (IS_ERR(priv->clkin))
+ return dev_err_probe(dev, PTR_ERR(priv->clkin), "failed to get clkin\n");
- priv->core_clk = devm_clk_get(&pdev->dev, "core");
- if (IS_ERR(priv->core_clk)) {
- dev_err(&pdev->dev, "failed to get core clk\n");
- return PTR_ERR(priv->core_clk);
- }
+ priv->core_clk = devm_clk_get_enabled(dev, "core");
+ if (IS_ERR(priv->core_clk))
+ return dev_err_probe(dev, PTR_ERR(priv->core_clk), "failed to get core clk\n");
- priv->adc_clk = devm_clk_get(&pdev->dev, "adc_clk");
- if (IS_ERR(priv->adc_clk)) {
- if (PTR_ERR(priv->adc_clk) == -ENOENT) {
- priv->adc_clk = NULL;
- } else {
- dev_err(&pdev->dev, "failed to get adc clk\n");
- return PTR_ERR(priv->adc_clk);
- }
- }
+ priv->adc_clk = devm_clk_get_optional(dev, "adc_clk");
+ if (IS_ERR(priv->adc_clk))
+ return dev_err_probe(dev, PTR_ERR(priv->adc_clk), "failed to get adc clk\n");
- priv->adc_sel_clk = devm_clk_get(&pdev->dev, "adc_sel");
- if (IS_ERR(priv->adc_sel_clk)) {
- if (PTR_ERR(priv->adc_sel_clk) == -ENOENT) {
- priv->adc_sel_clk = NULL;
- } else {
- dev_err(&pdev->dev, "failed to get adc_sel clk\n");
- return PTR_ERR(priv->adc_sel_clk);
- }
- }
+ priv->adc_sel_clk = devm_clk_get_optional(dev, "adc_sel");
+ if (IS_ERR(priv->adc_sel_clk))
+ return dev_err_probe(dev, PTR_ERR(priv->adc_sel_clk), "failed to get adc_sel clk\n");
/* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */
if (!priv->adc_clk) {
ret = meson_sar_adc_clk_init(indio_dev, base);
if (ret)
- return ret;
+ return dev_err_probe(dev, ret, "failed to init internal clk\n");
}
- priv->vref = devm_regulator_get(&pdev->dev, "vref");
- if (IS_ERR(priv->vref)) {
- dev_err(&pdev->dev, "failed to get vref regulator\n");
- return PTR_ERR(priv->vref);
- }
+ priv->vref = devm_regulator_get(dev, "vref");
+ if (IS_ERR(priv->vref))
+ return dev_err_probe(dev, PTR_ERR(priv->vref), "failed to get vref regulator\n");
priv->calibscale = MILLION;
@@ -1288,19 +1437,23 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
if (ret)
goto err;
+ mutex_init(&priv->lock);
+
ret = meson_sar_adc_hw_enable(indio_dev);
if (ret)
goto err;
ret = meson_sar_adc_calib(indio_dev);
if (ret)
- dev_warn(&pdev->dev, "calibration failed\n");
+ dev_warn(dev, "calibration failed\n");
platform_set_drvdata(pdev, indio_dev);
ret = iio_device_register(indio_dev);
- if (ret)
+ if (ret) {
+ dev_err_probe(dev, ret, "failed to register iio device\n");
goto err_hw;
+ }
return 0;
@@ -1310,31 +1463,44 @@ err:
return ret;
}
-static int meson_sar_adc_remove(struct platform_device *pdev)
+static void meson_sar_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
iio_device_unregister(indio_dev);
- return meson_sar_adc_hw_disable(indio_dev);
+ meson_sar_adc_hw_disable(indio_dev);
}
-static int __maybe_unused meson_sar_adc_suspend(struct device *dev)
+static int meson_sar_adc_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
+
+ meson_sar_adc_hw_disable(indio_dev);
+
+ clk_disable_unprepare(priv->core_clk);
- return meson_sar_adc_hw_disable(indio_dev);
+ return 0;
}
-static int __maybe_unused meson_sar_adc_resume(struct device *dev)
+static int meson_sar_adc_resume(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
+ int ret;
+
+ ret = clk_prepare_enable(priv->core_clk);
+ if (ret) {
+ dev_err(dev, "failed to enable core clk\n");
+ return ret;
+ }
return meson_sar_adc_hw_enable(indio_dev);
}
-static SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops,
- meson_sar_adc_suspend, meson_sar_adc_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops,
+ meson_sar_adc_suspend, meson_sar_adc_resume);
static struct platform_driver meson_sar_adc_driver = {
.probe = meson_sar_adc_probe,
@@ -1342,7 +1508,7 @@ static struct platform_driver meson_sar_adc_driver = {
.driver = {
.name = "meson-saradc",
.of_match_table = meson_sar_adc_of_match,
- .pm = &meson_sar_adc_pm_ops,
+ .pm = pm_sleep_ptr(&meson_sar_adc_pm_ops),
},
};