Commit ae3ed042ed31d1acbdd56938b45bd6c5076bebe3

Authored by David Wu
Committed by Philipp Tomsich
1 parent 6ca43a58db

dm: adc: Add driver for Rockchip SARADC

The ADC can support some channels signal-ended some bits Successive Approximation
Register (SAR) A/D Converter, like 6-channel and 10-bit. It converts the analog
input signal into some bits binary digital codes.

Signed-off-by: David Wu <david.wu@rock-chips.com>
Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
Reviewed-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

Showing 3 changed files with 193 additions and 0 deletions Side-by-side Diff

... ... @@ -28,4 +28,13 @@
28 28 - 4 analog input channels
29 29 - 16-bit resolution
30 30 - single and multi-channel conversion mode
  31 +
  32 +config SARADC_ROCKCHIP
  33 + bool "Enable Rockchip SARADC driver"
  34 + help
  35 + This enables driver for Rockchip SARADC.
  36 + It provides:
  37 + - 2~6 analog input channels
  38 + - 1O or 12 bits resolution
  39 + - Up to 1MSPS of sample rate
drivers/adc/Makefile
... ... @@ -8,4 +8,5 @@
8 8 obj-$(CONFIG_ADC) += adc-uclass.o
9 9 obj-$(CONFIG_ADC_EXYNOS) += exynos-adc.o
10 10 obj-$(CONFIG_ADC_SANDBOX) += sandbox.o
  11 +obj-$(CONFIG_SARADC_ROCKCHIP) += rockchip-saradc.o
drivers/adc/rockchip-saradc.c
  1 +/*
  2 + * (C) Copyright 2017, Fuzhou Rockchip Electronics Co., Ltd
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + *
  6 + * Rockchip SARADC driver for U-Boot
  7 + */
  8 +
  9 +#include <common.h>
  10 +#include <adc.h>
  11 +#include <clk.h>
  12 +#include <dm.h>
  13 +#include <errno.h>
  14 +#include <asm/io.h>
  15 +
  16 +#define SARADC_CTRL_CHN_MASK GENMASK(2, 0)
  17 +#define SARADC_CTRL_POWER_CTRL BIT(3)
  18 +#define SARADC_CTRL_IRQ_ENABLE BIT(5)
  19 +#define SARADC_CTRL_IRQ_STATUS BIT(6)
  20 +
  21 +#define SARADC_TIMEOUT (100 * 1000)
  22 +
  23 +struct rockchip_saradc_regs {
  24 + unsigned int data;
  25 + unsigned int stas;
  26 + unsigned int ctrl;
  27 + unsigned int dly_pu_soc;
  28 +};
  29 +
  30 +struct rockchip_saradc_data {
  31 + int num_bits;
  32 + int num_channels;
  33 + unsigned long clk_rate;
  34 +};
  35 +
  36 +struct rockchip_saradc_priv {
  37 + struct rockchip_saradc_regs *regs;
  38 + int active_channel;
  39 + const struct rockchip_saradc_data *data;
  40 +};
  41 +
  42 +int rockchip_saradc_channel_data(struct udevice *dev, int channel,
  43 + unsigned int *data)
  44 +{
  45 + struct rockchip_saradc_priv *priv = dev_get_priv(dev);
  46 + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
  47 +
  48 + if (channel != priv->active_channel) {
  49 + error("Requested channel is not active!");
  50 + return -EINVAL;
  51 + }
  52 +
  53 + if ((readl(&priv->regs->ctrl) & SARADC_CTRL_IRQ_STATUS) !=
  54 + SARADC_CTRL_IRQ_STATUS)
  55 + return -EBUSY;
  56 +
  57 + /* Read value */
  58 + *data = readl(&priv->regs->data);
  59 + *data &= uc_pdata->data_mask;
  60 +
  61 + /* Power down adc */
  62 + writel(0, &priv->regs->ctrl);
  63 +
  64 + return 0;
  65 +}
  66 +
  67 +int rockchip_saradc_start_channel(struct udevice *dev, int channel)
  68 +{
  69 + struct rockchip_saradc_priv *priv = dev_get_priv(dev);
  70 +
  71 + if (channel < 0 || channel >= priv->data->num_channels) {
  72 + error("Requested channel is invalid!");
  73 + return -EINVAL;
  74 + }
  75 +
  76 + /* 8 clock periods as delay between power up and start cmd */
  77 + writel(8, &priv->regs->dly_pu_soc);
  78 +
  79 + /* Select the channel to be used and trigger conversion */
  80 + writel(SARADC_CTRL_POWER_CTRL | (channel & SARADC_CTRL_CHN_MASK) |
  81 + SARADC_CTRL_IRQ_ENABLE, &priv->regs->ctrl);
  82 +
  83 + priv->active_channel = channel;
  84 +
  85 + return 0;
  86 +}
  87 +
  88 +int rockchip_saradc_stop(struct udevice *dev)
  89 +{
  90 + struct rockchip_saradc_priv *priv = dev_get_priv(dev);
  91 +
  92 + /* Power down adc */
  93 + writel(0, &priv->regs->ctrl);
  94 +
  95 + priv->active_channel = -1;
  96 +
  97 + return 0;
  98 +}
  99 +
  100 +int rockchip_saradc_probe(struct udevice *dev)
  101 +{
  102 + struct rockchip_saradc_priv *priv = dev_get_priv(dev);
  103 + struct clk clk;
  104 + int ret;
  105 +
  106 + ret = clk_get_by_index(dev, 0, &clk);
  107 + if (ret)
  108 + return ret;
  109 +
  110 + ret = clk_set_rate(&clk, priv->data->clk_rate);
  111 + if (IS_ERR_VALUE(ret))
  112 + return ret;
  113 +
  114 + priv->active_channel = -1;
  115 +
  116 + return 0;
  117 +}
  118 +
  119 +int rockchip_saradc_ofdata_to_platdata(struct udevice *dev)
  120 +{
  121 + struct adc_uclass_platdata *uc_pdata = dev_get_uclass_platdata(dev);
  122 + struct rockchip_saradc_priv *priv = dev_get_priv(dev);
  123 + struct rockchip_saradc_data *data;
  124 +
  125 + data = (struct rockchip_saradc_data *)dev_get_driver_data(dev);
  126 + priv->regs = (struct rockchip_saradc_regs *)dev_read_addr(dev);
  127 + if (priv->regs == (struct rockchip_saradc_regs *)FDT_ADDR_T_NONE) {
  128 + error("Dev: %s - can't get address!", dev->name);
  129 + return -ENODATA;
  130 + }
  131 +
  132 + priv->data = data;
  133 + uc_pdata->data_mask = (1 << priv->data->num_bits) - 1;;
  134 + uc_pdata->data_format = ADC_DATA_FORMAT_BIN;
  135 + uc_pdata->data_timeout_us = SARADC_TIMEOUT / 5;
  136 + uc_pdata->channel_mask = (1 << priv->data->num_channels) - 1;
  137 +
  138 + return 0;
  139 +}
  140 +
  141 +static const struct adc_ops rockchip_saradc_ops = {
  142 + .start_channel = rockchip_saradc_start_channel,
  143 + .channel_data = rockchip_saradc_channel_data,
  144 + .stop = rockchip_saradc_stop,
  145 +};
  146 +
  147 +static const struct rockchip_saradc_data saradc_data = {
  148 + .num_bits = 10,
  149 + .num_channels = 3,
  150 + .clk_rate = 1000000,
  151 +};
  152 +
  153 +static const struct rockchip_saradc_data rk3066_tsadc_data = {
  154 + .num_bits = 12,
  155 + .num_channels = 2,
  156 + .clk_rate = 50000,
  157 +};
  158 +
  159 +static const struct rockchip_saradc_data rk3399_saradc_data = {
  160 + .num_bits = 10,
  161 + .num_channels = 6,
  162 + .clk_rate = 1000000,
  163 +};
  164 +
  165 +static const struct udevice_id rockchip_saradc_ids[] = {
  166 + { .compatible = "rockchip,saradc",
  167 + .data = (ulong)&saradc_data },
  168 + { .compatible = "rockchip,rk3066-tsadc",
  169 + .data = (ulong)&rk3066_tsadc_data },
  170 + { .compatible = "rockchip,rk3399-saradc",
  171 + .data = (ulong)&rk3399_saradc_data },
  172 + { }
  173 +};
  174 +
  175 +U_BOOT_DRIVER(rockchip_saradc) = {
  176 + .name = "rockchip_saradc",
  177 + .id = UCLASS_ADC,
  178 + .of_match = rockchip_saradc_ids,
  179 + .ops = &rockchip_saradc_ops,
  180 + .probe = rockchip_saradc_probe,
  181 + .ofdata_to_platdata = rockchip_saradc_ofdata_to_platdata,
  182 + .priv_auto_alloc_size = sizeof(struct rockchip_saradc_priv),
  183 +};