summaryrefslogtreecommitdiff
path: root/drivers/iio/adc/sc27xx_adc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/adc/sc27xx_adc.c')
-rw-r--r--drivers/iio/adc/sc27xx_adc.c470
1 files changed, 435 insertions, 35 deletions
diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c
index 00098caf6d9e..e9ff2d6a8a57 100644
--- a/drivers/iio/adc/sc27xx_adc.c
+++ b/drivers/iio/adc/sc27xx_adc.c
@@ -9,12 +9,16 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
#include <linux/slab.h>
/* PMIC global registers definition */
-#define SC27XX_MODULE_EN 0xc08
+#define SC2730_MODULE_EN 0x1808
+#define SC2731_MODULE_EN 0xc08
#define SC27XX_MODULE_ADC_EN BIT(5)
-#define SC27XX_ARM_CLK_EN 0xc10
+#define SC2721_ARM_CLK_EN 0xc0c
+#define SC2730_ARM_CLK_EN 0x180c
+#define SC2731_ARM_CLK_EN 0xc10
#define SC27XX_CLK_ADC_EN BIT(5)
#define SC27XX_CLK_ADC_CLK_EN BIT(6)
@@ -36,8 +40,10 @@
/* Bits and mask definition for SC27XX_ADC_CH_CFG register */
#define SC27XX_ADC_CHN_ID_MASK GENMASK(4, 0)
-#define SC27XX_ADC_SCALE_MASK GENMASK(10, 8)
-#define SC27XX_ADC_SCALE_SHIFT 8
+#define SC27XX_ADC_SCALE_MASK GENMASK(10, 9)
+#define SC2721_ADC_SCALE_MASK BIT(5)
+#define SC27XX_ADC_SCALE_SHIFT 9
+#define SC2721_ADC_SCALE_SHIFT 5
/* Bits definitions for SC27XX_ADC_INT_EN registers */
#define SC27XX_ADC_IRQ_EN BIT(0)
@@ -67,8 +73,15 @@
#define SC27XX_RATIO_NUMERATOR_OFFSET 16
#define SC27XX_RATIO_DENOMINATOR_MASK GENMASK(15, 0)
+/* ADC specific channel reference voltage 3.5V */
+#define SC27XX_ADC_REFVOL_VDD35 3500000
+
+/* ADC default channel reference voltage is 2.8V */
+#define SC27XX_ADC_REFVOL_VDD28 2800000
+
struct sc27xx_adc_data {
struct device *dev;
+ struct regulator *volref;
struct regmap *regmap;
/*
* One hardware spinlock to synchronize between the multiple
@@ -78,6 +91,24 @@ struct sc27xx_adc_data {
int channel_scale[SC27XX_ADC_CHANNEL_MAX];
u32 base;
int irq;
+ const struct sc27xx_adc_variant_data *var_data;
+};
+
+/*
+ * Since different PMICs of SC27xx series can have different
+ * address and ratio, we should save ratio config and base
+ * in the device data structure.
+ */
+struct sc27xx_adc_variant_data {
+ u32 module_en;
+ u32 clk_en;
+ u32 scale_shift;
+ u32 scale_mask;
+ const struct sc27xx_adc_linear_graph *bscale_cal;
+ const struct sc27xx_adc_linear_graph *sscale_cal;
+ void (*init_scale)(struct sc27xx_adc_data *data);
+ int (*get_ratio)(int channel, int scale);
+ bool set_volref;
};
struct sc27xx_adc_linear_graph {
@@ -103,6 +134,16 @@ static struct sc27xx_adc_linear_graph small_scale_graph = {
100, 341,
};
+static const struct sc27xx_adc_linear_graph sc2731_big_scale_graph_calib = {
+ 4200, 850,
+ 3600, 728,
+};
+
+static const struct sc27xx_adc_linear_graph sc2731_small_scale_graph_calib = {
+ 1000, 838,
+ 100, 84,
+};
+
static const struct sc27xx_adc_linear_graph big_scale_graph_calib = {
4200, 856,
3600, 733,
@@ -118,49 +159,225 @@ static int sc27xx_adc_get_calib_data(u32 calib_data, int calib_adc)
return ((calib_data & 0xff) + calib_adc - 128) * 4;
}
+/* get the adc nvmem cell calibration data */
+static int adc_nvmem_cell_calib_data(struct sc27xx_adc_data *data, const char *cell_name)
+{
+ struct nvmem_cell *cell;
+ void *buf;
+ u32 origin_calib_data = 0;
+ size_t len;
+
+ if (!data)
+ return -EINVAL;
+
+ cell = nvmem_cell_get(data->dev, cell_name);
+ if (IS_ERR(cell))
+ return PTR_ERR(cell);
+
+ buf = nvmem_cell_read(cell, &len);
+ if (IS_ERR(buf)) {
+ nvmem_cell_put(cell);
+ return PTR_ERR(buf);
+ }
+
+ memcpy(&origin_calib_data, buf, min(len, sizeof(u32)));
+
+ kfree(buf);
+ nvmem_cell_put(cell);
+ return origin_calib_data;
+}
+
static int sc27xx_adc_scale_calibration(struct sc27xx_adc_data *data,
bool big_scale)
{
const struct sc27xx_adc_linear_graph *calib_graph;
struct sc27xx_adc_linear_graph *graph;
- struct nvmem_cell *cell;
const char *cell_name;
u32 calib_data = 0;
- void *buf;
- size_t len;
if (big_scale) {
- calib_graph = &big_scale_graph_calib;
+ calib_graph = data->var_data->bscale_cal;
graph = &big_scale_graph;
cell_name = "big_scale_calib";
} else {
- calib_graph = &small_scale_graph_calib;
+ calib_graph = data->var_data->sscale_cal;
graph = &small_scale_graph;
cell_name = "small_scale_calib";
}
- cell = nvmem_cell_get(data->dev, cell_name);
- if (IS_ERR(cell))
- return PTR_ERR(cell);
-
- buf = nvmem_cell_read(cell, &len);
- nvmem_cell_put(cell);
-
- if (IS_ERR(buf))
- return PTR_ERR(buf);
-
- memcpy(&calib_data, buf, min(len, sizeof(u32)));
+ calib_data = adc_nvmem_cell_calib_data(data, cell_name);
/* Only need to calibrate the adc values in the linear graph. */
graph->adc0 = sc27xx_adc_get_calib_data(calib_data, calib_graph->adc0);
graph->adc1 = sc27xx_adc_get_calib_data(calib_data >> 8,
calib_graph->adc1);
- kfree(buf);
return 0;
}
-static int sc27xx_adc_get_ratio(int channel, int scale)
+static int sc2720_adc_get_ratio(int channel, int scale)
+{
+ switch (channel) {
+ case 14:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(68, 900);
+ case 1:
+ return SC27XX_VOLT_RATIO(68, 1760);
+ case 2:
+ return SC27XX_VOLT_RATIO(68, 2327);
+ case 3:
+ return SC27XX_VOLT_RATIO(68, 3654);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ case 16:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(48, 100);
+ case 1:
+ return SC27XX_VOLT_RATIO(480, 1955);
+ case 2:
+ return SC27XX_VOLT_RATIO(480, 2586);
+ case 3:
+ return SC27XX_VOLT_RATIO(48, 406);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ case 21:
+ case 22:
+ case 23:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(3, 8);
+ case 1:
+ return SC27XX_VOLT_RATIO(375, 1955);
+ case 2:
+ return SC27XX_VOLT_RATIO(375, 2586);
+ case 3:
+ return SC27XX_VOLT_RATIO(300, 3248);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ default:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(1, 1);
+ case 1:
+ return SC27XX_VOLT_RATIO(1000, 1955);
+ case 2:
+ return SC27XX_VOLT_RATIO(1000, 2586);
+ case 3:
+ return SC27XX_VOLT_RATIO(100, 406);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ }
+ return SC27XX_VOLT_RATIO(1, 1);
+}
+
+static int sc2721_adc_get_ratio(int channel, int scale)
+{
+ switch (channel) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ return scale ? SC27XX_VOLT_RATIO(400, 1025) :
+ SC27XX_VOLT_RATIO(1, 1);
+ case 5:
+ return SC27XX_VOLT_RATIO(7, 29);
+ case 7:
+ case 9:
+ return scale ? SC27XX_VOLT_RATIO(100, 125) :
+ SC27XX_VOLT_RATIO(1, 1);
+ case 14:
+ return SC27XX_VOLT_RATIO(68, 900);
+ case 16:
+ return SC27XX_VOLT_RATIO(48, 100);
+ case 19:
+ return SC27XX_VOLT_RATIO(1, 3);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ return SC27XX_VOLT_RATIO(1, 1);
+}
+
+static int sc2730_adc_get_ratio(int channel, int scale)
+{
+ switch (channel) {
+ case 14:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(68, 900);
+ case 1:
+ return SC27XX_VOLT_RATIO(68, 1760);
+ case 2:
+ return SC27XX_VOLT_RATIO(68, 2327);
+ case 3:
+ return SC27XX_VOLT_RATIO(68, 3654);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ case 15:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(1, 3);
+ case 1:
+ return SC27XX_VOLT_RATIO(1000, 5865);
+ case 2:
+ return SC27XX_VOLT_RATIO(500, 3879);
+ case 3:
+ return SC27XX_VOLT_RATIO(500, 6090);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ case 16:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(48, 100);
+ case 1:
+ return SC27XX_VOLT_RATIO(480, 1955);
+ case 2:
+ return SC27XX_VOLT_RATIO(480, 2586);
+ case 3:
+ return SC27XX_VOLT_RATIO(48, 406);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ case 21:
+ case 22:
+ case 23:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(3, 8);
+ case 1:
+ return SC27XX_VOLT_RATIO(375, 1955);
+ case 2:
+ return SC27XX_VOLT_RATIO(375, 2586);
+ case 3:
+ return SC27XX_VOLT_RATIO(300, 3248);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ default:
+ switch (scale) {
+ case 0:
+ return SC27XX_VOLT_RATIO(1, 1);
+ case 1:
+ return SC27XX_VOLT_RATIO(1000, 1955);
+ case 2:
+ return SC27XX_VOLT_RATIO(1000, 2586);
+ case 3:
+ return SC27XX_VOLT_RATIO(1000, 4060);
+ default:
+ return SC27XX_VOLT_RATIO(1, 1);
+ }
+ }
+ return SC27XX_VOLT_RATIO(1, 1);
+}
+
+static int sc2731_adc_get_ratio(int channel, int scale)
{
switch (channel) {
case 1:
@@ -185,10 +402,87 @@ static int sc27xx_adc_get_ratio(int channel, int scale)
return SC27XX_VOLT_RATIO(1, 1);
}
+/*
+ * According to the datasheet set specific value on some channel.
+ */
+static void sc2720_adc_scale_init(struct sc27xx_adc_data *data)
+{
+ int i;
+
+ for (i = 0; i < SC27XX_ADC_CHANNEL_MAX; i++) {
+ switch (i) {
+ case 5:
+ data->channel_scale[i] = 3;
+ break;
+ case 7:
+ case 9:
+ data->channel_scale[i] = 2;
+ break;
+ case 13:
+ data->channel_scale[i] = 1;
+ break;
+ case 19:
+ case 30:
+ case 31:
+ data->channel_scale[i] = 3;
+ break;
+ default:
+ data->channel_scale[i] = 0;
+ break;
+ }
+ }
+}
+
+static void sc2730_adc_scale_init(struct sc27xx_adc_data *data)
+{
+ int i;
+
+ for (i = 0; i < SC27XX_ADC_CHANNEL_MAX; i++) {
+ switch (i) {
+ case 5:
+ case 10:
+ case 19:
+ case 30:
+ case 31:
+ data->channel_scale[i] = 3;
+ break;
+ case 7:
+ case 9:
+ data->channel_scale[i] = 2;
+ break;
+ case 13:
+ data->channel_scale[i] = 1;
+ break;
+ default:
+ data->channel_scale[i] = 0;
+ break;
+ }
+ }
+}
+
+static void sc2731_adc_scale_init(struct sc27xx_adc_data *data)
+{
+ int i;
+ /*
+ * In the current software design, SC2731 support 2 scales,
+ * channels 5 uses big scale, others use smale.
+ */
+ for (i = 0; i < SC27XX_ADC_CHANNEL_MAX; i++) {
+ switch (i) {
+ case 5:
+ data->channel_scale[i] = 1;
+ break;
+ default:
+ data->channel_scale[i] = 0;
+ break;
+ }
+ }
+}
+
static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel,
int scale, int *val)
{
- int ret;
+ int ret, ret_volref;
u32 tmp, value, status;
ret = hwspin_lock_timeout_raw(data->hwlock, SC27XX_ADC_HWLOCK_TIMEOUT);
@@ -197,10 +491,25 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel,
return ret;
}
+ /*
+ * According to the sc2721 chip data sheet, the reference voltage of
+ * specific channel 30 and channel 31 in ADC module needs to be set from
+ * the default 2.8v to 3.5v.
+ */
+ if ((data->var_data->set_volref) && (channel == 30 || channel == 31)) {
+ ret = regulator_set_voltage(data->volref,
+ SC27XX_ADC_REFVOL_VDD35,
+ SC27XX_ADC_REFVOL_VDD35);
+ if (ret) {
+ dev_err(data->dev, "failed to set the volref 3.5v\n");
+ goto unlock_adc;
+ }
+ }
+
ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CTL,
SC27XX_ADC_EN, SC27XX_ADC_EN);
if (ret)
- goto unlock_adc;
+ goto regulator_restore;
ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_CLR,
SC27XX_ADC_IRQ_CLR, SC27XX_ADC_IRQ_CLR);
@@ -208,10 +517,11 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel,
goto disable_adc;
/* Configure the channel id and scale */
- tmp = (scale << SC27XX_ADC_SCALE_SHIFT) & SC27XX_ADC_SCALE_MASK;
+ tmp = (scale << data->var_data->scale_shift) & data->var_data->scale_mask;
tmp |= channel & SC27XX_ADC_CHN_ID_MASK;
ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CH_CFG,
- SC27XX_ADC_CHN_ID_MASK | SC27XX_ADC_SCALE_MASK,
+ SC27XX_ADC_CHN_ID_MASK |
+ data->var_data->scale_mask,
tmp);
if (ret)
goto disable_adc;
@@ -249,6 +559,17 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel,
disable_adc:
regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CTL,
SC27XX_ADC_EN, 0);
+regulator_restore:
+ if ((data->var_data->set_volref) && (channel == 30 || channel == 31)) {
+ ret_volref = regulator_set_voltage(data->volref,
+ SC27XX_ADC_REFVOL_VDD28,
+ SC27XX_ADC_REFVOL_VDD28);
+ if (ret_volref) {
+ dev_err(data->dev, "failed to set the volref 2.8v,ret_volref = 0x%x\n",
+ ret_volref);
+ ret = ret || ret_volref;
+ }
+ }
unlock_adc:
hwspin_unlock_raw(data->hwlock);
@@ -262,13 +583,14 @@ static void sc27xx_adc_volt_ratio(struct sc27xx_adc_data *data,
int channel, int scale,
u32 *div_numerator, u32 *div_denominator)
{
- u32 ratio = sc27xx_adc_get_ratio(channel, scale);
+ u32 ratio;
+ ratio = data->var_data->get_ratio(channel, scale);
*div_numerator = ratio >> SC27XX_RATIO_NUMERATOR_OFFSET;
*div_denominator = ratio & SC27XX_RATIO_DENOMINATOR_MASK;
}
-static int sc27xx_adc_to_volt(struct sc27xx_adc_linear_graph *graph,
+static int adc_to_volt(struct sc27xx_adc_linear_graph *graph,
int raw_adc)
{
int tmp;
@@ -277,6 +599,16 @@ static int sc27xx_adc_to_volt(struct sc27xx_adc_linear_graph *graph,
tmp /= (graph->adc0 - graph->adc1);
tmp += graph->volt1;
+ return tmp;
+}
+
+static int sc27xx_adc_to_volt(struct sc27xx_adc_linear_graph *graph,
+ int raw_adc)
+{
+ int tmp;
+
+ tmp = adc_to_volt(graph, raw_adc);
+
return tmp < 0 ? 0 : tmp;
}
@@ -432,13 +764,13 @@ static int sc27xx_adc_enable(struct sc27xx_adc_data *data)
{
int ret;
- ret = regmap_update_bits(data->regmap, SC27XX_MODULE_EN,
+ ret = regmap_update_bits(data->regmap, data->var_data->module_en,
SC27XX_MODULE_ADC_EN, SC27XX_MODULE_ADC_EN);
if (ret)
return ret;
/* Enable ADC work clock and controller clock */
- ret = regmap_update_bits(data->regmap, SC27XX_ARM_CLK_EN,
+ ret = regmap_update_bits(data->regmap, data->var_data->clk_en,
SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN,
SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN);
if (ret)
@@ -456,10 +788,10 @@ static int sc27xx_adc_enable(struct sc27xx_adc_data *data)
return 0;
disable_clk:
- regmap_update_bits(data->regmap, SC27XX_ARM_CLK_EN,
+ regmap_update_bits(data->regmap, data->var_data->clk_en,
SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, 0);
disable_adc:
- regmap_update_bits(data->regmap, SC27XX_MODULE_EN,
+ regmap_update_bits(data->regmap, data->var_data->module_en,
SC27XX_MODULE_ADC_EN, 0);
return ret;
@@ -470,21 +802,76 @@ static void sc27xx_adc_disable(void *_data)
struct sc27xx_adc_data *data = _data;
/* Disable ADC work clock and controller clock */
- regmap_update_bits(data->regmap, SC27XX_ARM_CLK_EN,
+ regmap_update_bits(data->regmap, data->var_data->clk_en,
SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, 0);
- regmap_update_bits(data->regmap, SC27XX_MODULE_EN,
+ regmap_update_bits(data->regmap, data->var_data->module_en,
SC27XX_MODULE_ADC_EN, 0);
}
+static const struct sc27xx_adc_variant_data sc2731_data = {
+ .module_en = SC2731_MODULE_EN,
+ .clk_en = SC2731_ARM_CLK_EN,
+ .scale_shift = SC27XX_ADC_SCALE_SHIFT,
+ .scale_mask = SC27XX_ADC_SCALE_MASK,
+ .bscale_cal = &sc2731_big_scale_graph_calib,
+ .sscale_cal = &sc2731_small_scale_graph_calib,
+ .init_scale = sc2731_adc_scale_init,
+ .get_ratio = sc2731_adc_get_ratio,
+ .set_volref = false,
+};
+
+static const struct sc27xx_adc_variant_data sc2730_data = {
+ .module_en = SC2730_MODULE_EN,
+ .clk_en = SC2730_ARM_CLK_EN,
+ .scale_shift = SC27XX_ADC_SCALE_SHIFT,
+ .scale_mask = SC27XX_ADC_SCALE_MASK,
+ .bscale_cal = &big_scale_graph_calib,
+ .sscale_cal = &small_scale_graph_calib,
+ .init_scale = sc2730_adc_scale_init,
+ .get_ratio = sc2730_adc_get_ratio,
+ .set_volref = false,
+};
+
+static const struct sc27xx_adc_variant_data sc2721_data = {
+ .module_en = SC2731_MODULE_EN,
+ .clk_en = SC2721_ARM_CLK_EN,
+ .scale_shift = SC2721_ADC_SCALE_SHIFT,
+ .scale_mask = SC2721_ADC_SCALE_MASK,
+ .bscale_cal = &sc2731_big_scale_graph_calib,
+ .sscale_cal = &sc2731_small_scale_graph_calib,
+ .init_scale = sc2731_adc_scale_init,
+ .get_ratio = sc2721_adc_get_ratio,
+ .set_volref = true,
+};
+
+static const struct sc27xx_adc_variant_data sc2720_data = {
+ .module_en = SC2731_MODULE_EN,
+ .clk_en = SC2721_ARM_CLK_EN,
+ .scale_shift = SC27XX_ADC_SCALE_SHIFT,
+ .scale_mask = SC27XX_ADC_SCALE_MASK,
+ .bscale_cal = &big_scale_graph_calib,
+ .sscale_cal = &small_scale_graph_calib,
+ .init_scale = sc2720_adc_scale_init,
+ .get_ratio = sc2720_adc_get_ratio,
+ .set_volref = false,
+};
+
static int sc27xx_adc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct sc27xx_adc_data *sc27xx_data;
+ const struct sc27xx_adc_variant_data *pdata;
struct iio_dev *indio_dev;
int ret;
+ pdata = of_device_get_match_data(dev);
+ if (!pdata) {
+ dev_err(dev, "No matching driver data found\n");
+ return -EINVAL;
+ }
+
indio_dev = devm_iio_device_alloc(dev, sizeof(*sc27xx_data));
if (!indio_dev)
return -ENOMEM;
@@ -520,6 +907,16 @@ static int sc27xx_adc_probe(struct platform_device *pdev)
}
sc27xx_data->dev = dev;
+ if (pdata->set_volref) {
+ sc27xx_data->volref = devm_regulator_get(dev, "vref");
+ if (IS_ERR(sc27xx_data->volref)) {
+ ret = PTR_ERR(sc27xx_data->volref);
+ return dev_err_probe(dev, ret, "failed to get ADC volref\n");
+ }
+ }
+
+ sc27xx_data->var_data = pdata;
+ sc27xx_data->var_data->init_scale(sc27xx_data);
ret = sc27xx_adc_enable(sc27xx_data);
if (ret) {
@@ -546,7 +943,10 @@ static int sc27xx_adc_probe(struct platform_device *pdev)
}
static const struct of_device_id sc27xx_adc_of_match[] = {
- { .compatible = "sprd,sc2731-adc", },
+ { .compatible = "sprd,sc2731-adc", .data = &sc2731_data},
+ { .compatible = "sprd,sc2730-adc", .data = &sc2730_data},
+ { .compatible = "sprd,sc2721-adc", .data = &sc2721_data},
+ { .compatible = "sprd,sc2720-adc", .data = &sc2720_data},
{ }
};
MODULE_DEVICE_TABLE(of, sc27xx_adc_of_match);