root/drivers/iio/adc/aspeed_adc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. aspeed_adc_read_raw
  2. aspeed_adc_write_raw
  3. aspeed_adc_reg_access
  4. aspeed_adc_probe
  5. aspeed_adc_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Aspeed AST2400/2500 ADC
   4  *
   5  * Copyright (C) 2017 Google, Inc.
   6  */
   7 
   8 #include <linux/clk.h>
   9 #include <linux/clk-provider.h>
  10 #include <linux/err.h>
  11 #include <linux/errno.h>
  12 #include <linux/io.h>
  13 #include <linux/module.h>
  14 #include <linux/of_platform.h>
  15 #include <linux/platform_device.h>
  16 #include <linux/reset.h>
  17 #include <linux/spinlock.h>
  18 #include <linux/types.h>
  19 
  20 #include <linux/iio/iio.h>
  21 #include <linux/iio/driver.h>
  22 #include <linux/iopoll.h>
  23 
  24 #define ASPEED_RESOLUTION_BITS          10
  25 #define ASPEED_CLOCKS_PER_SAMPLE        12
  26 
  27 #define ASPEED_REG_ENGINE_CONTROL       0x00
  28 #define ASPEED_REG_INTERRUPT_CONTROL    0x04
  29 #define ASPEED_REG_VGA_DETECT_CONTROL   0x08
  30 #define ASPEED_REG_CLOCK_CONTROL        0x0C
  31 #define ASPEED_REG_MAX                  0xC0
  32 
  33 #define ASPEED_OPERATION_MODE_POWER_DOWN        (0x0 << 1)
  34 #define ASPEED_OPERATION_MODE_STANDBY           (0x1 << 1)
  35 #define ASPEED_OPERATION_MODE_NORMAL            (0x7 << 1)
  36 
  37 #define ASPEED_ENGINE_ENABLE            BIT(0)
  38 
  39 #define ASPEED_ADC_CTRL_INIT_RDY        BIT(8)
  40 
  41 #define ASPEED_ADC_INIT_POLLING_TIME    500
  42 #define ASPEED_ADC_INIT_TIMEOUT         500000
  43 
  44 struct aspeed_adc_model_data {
  45         const char *model_name;
  46         unsigned int min_sampling_rate; // Hz
  47         unsigned int max_sampling_rate; // Hz
  48         unsigned int vref_voltage;      // mV
  49         bool wait_init_sequence;
  50 };
  51 
  52 struct aspeed_adc_data {
  53         struct device           *dev;
  54         void __iomem            *base;
  55         spinlock_t              clk_lock;
  56         struct clk_hw           *clk_prescaler;
  57         struct clk_hw           *clk_scaler;
  58         struct reset_control    *rst;
  59 };
  60 
  61 #define ASPEED_CHAN(_idx, _data_reg_addr) {                     \
  62         .type = IIO_VOLTAGE,                                    \
  63         .indexed = 1,                                           \
  64         .channel = (_idx),                                      \
  65         .address = (_data_reg_addr),                            \
  66         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
  67         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
  68                                 BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
  69 }
  70 
  71 static const struct iio_chan_spec aspeed_adc_iio_channels[] = {
  72         ASPEED_CHAN(0, 0x10),
  73         ASPEED_CHAN(1, 0x12),
  74         ASPEED_CHAN(2, 0x14),
  75         ASPEED_CHAN(3, 0x16),
  76         ASPEED_CHAN(4, 0x18),
  77         ASPEED_CHAN(5, 0x1A),
  78         ASPEED_CHAN(6, 0x1C),
  79         ASPEED_CHAN(7, 0x1E),
  80         ASPEED_CHAN(8, 0x20),
  81         ASPEED_CHAN(9, 0x22),
  82         ASPEED_CHAN(10, 0x24),
  83         ASPEED_CHAN(11, 0x26),
  84         ASPEED_CHAN(12, 0x28),
  85         ASPEED_CHAN(13, 0x2A),
  86         ASPEED_CHAN(14, 0x2C),
  87         ASPEED_CHAN(15, 0x2E),
  88 };
  89 
  90 static int aspeed_adc_read_raw(struct iio_dev *indio_dev,
  91                                struct iio_chan_spec const *chan,
  92                                int *val, int *val2, long mask)
  93 {
  94         struct aspeed_adc_data *data = iio_priv(indio_dev);
  95         const struct aspeed_adc_model_data *model_data =
  96                         of_device_get_match_data(data->dev);
  97 
  98         switch (mask) {
  99         case IIO_CHAN_INFO_RAW:
 100                 *val = readw(data->base + chan->address);
 101                 return IIO_VAL_INT;
 102 
 103         case IIO_CHAN_INFO_SCALE:
 104                 *val = model_data->vref_voltage;
 105                 *val2 = ASPEED_RESOLUTION_BITS;
 106                 return IIO_VAL_FRACTIONAL_LOG2;
 107 
 108         case IIO_CHAN_INFO_SAMP_FREQ:
 109                 *val = clk_get_rate(data->clk_scaler->clk) /
 110                                 ASPEED_CLOCKS_PER_SAMPLE;
 111                 return IIO_VAL_INT;
 112 
 113         default:
 114                 return -EINVAL;
 115         }
 116 }
 117 
 118 static int aspeed_adc_write_raw(struct iio_dev *indio_dev,
 119                                 struct iio_chan_spec const *chan,
 120                                 int val, int val2, long mask)
 121 {
 122         struct aspeed_adc_data *data = iio_priv(indio_dev);
 123         const struct aspeed_adc_model_data *model_data =
 124                         of_device_get_match_data(data->dev);
 125 
 126         switch (mask) {
 127         case IIO_CHAN_INFO_SAMP_FREQ:
 128                 if (val < model_data->min_sampling_rate ||
 129                         val > model_data->max_sampling_rate)
 130                         return -EINVAL;
 131 
 132                 clk_set_rate(data->clk_scaler->clk,
 133                                 val * ASPEED_CLOCKS_PER_SAMPLE);
 134                 return 0;
 135 
 136         case IIO_CHAN_INFO_SCALE:
 137         case IIO_CHAN_INFO_RAW:
 138                 /*
 139                  * Technically, these could be written but the only reasons
 140                  * for doing so seem better handled in userspace.  EPERM is
 141                  * returned to signal this is a policy choice rather than a
 142                  * hardware limitation.
 143                  */
 144                 return -EPERM;
 145 
 146         default:
 147                 return -EINVAL;
 148         }
 149 }
 150 
 151 static int aspeed_adc_reg_access(struct iio_dev *indio_dev,
 152                                  unsigned int reg, unsigned int writeval,
 153                                  unsigned int *readval)
 154 {
 155         struct aspeed_adc_data *data = iio_priv(indio_dev);
 156 
 157         if (!readval || reg % 4 || reg > ASPEED_REG_MAX)
 158                 return -EINVAL;
 159 
 160         *readval = readl(data->base + reg);
 161 
 162         return 0;
 163 }
 164 
 165 static const struct iio_info aspeed_adc_iio_info = {
 166         .read_raw = aspeed_adc_read_raw,
 167         .write_raw = aspeed_adc_write_raw,
 168         .debugfs_reg_access = aspeed_adc_reg_access,
 169 };
 170 
 171 static int aspeed_adc_probe(struct platform_device *pdev)
 172 {
 173         struct iio_dev *indio_dev;
 174         struct aspeed_adc_data *data;
 175         const struct aspeed_adc_model_data *model_data;
 176         struct resource *res;
 177         const char *clk_parent_name;
 178         int ret;
 179         u32 adc_engine_control_reg_val;
 180 
 181         indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*data));
 182         if (!indio_dev)
 183                 return -ENOMEM;
 184 
 185         data = iio_priv(indio_dev);
 186         data->dev = &pdev->dev;
 187 
 188         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 189         data->base = devm_ioremap_resource(&pdev->dev, res);
 190         if (IS_ERR(data->base))
 191                 return PTR_ERR(data->base);
 192 
 193         /* Register ADC clock prescaler with source specified by device tree. */
 194         spin_lock_init(&data->clk_lock);
 195         clk_parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
 196 
 197         data->clk_prescaler = clk_hw_register_divider(
 198                                 &pdev->dev, "prescaler", clk_parent_name, 0,
 199                                 data->base + ASPEED_REG_CLOCK_CONTROL,
 200                                 17, 15, 0, &data->clk_lock);
 201         if (IS_ERR(data->clk_prescaler))
 202                 return PTR_ERR(data->clk_prescaler);
 203 
 204         /*
 205          * Register ADC clock scaler downstream from the prescaler. Allow rate
 206          * setting to adjust the prescaler as well.
 207          */
 208         data->clk_scaler = clk_hw_register_divider(
 209                                 &pdev->dev, "scaler", "prescaler",
 210                                 CLK_SET_RATE_PARENT,
 211                                 data->base + ASPEED_REG_CLOCK_CONTROL,
 212                                 0, 10, 0, &data->clk_lock);
 213         if (IS_ERR(data->clk_scaler)) {
 214                 ret = PTR_ERR(data->clk_scaler);
 215                 goto scaler_error;
 216         }
 217 
 218         data->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
 219         if (IS_ERR(data->rst)) {
 220                 dev_err(&pdev->dev,
 221                         "invalid or missing reset controller device tree entry");
 222                 ret = PTR_ERR(data->rst);
 223                 goto reset_error;
 224         }
 225         reset_control_deassert(data->rst);
 226 
 227         model_data = of_device_get_match_data(&pdev->dev);
 228 
 229         if (model_data->wait_init_sequence) {
 230                 /* Enable engine in normal mode. */
 231                 writel(ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE,
 232                        data->base + ASPEED_REG_ENGINE_CONTROL);
 233 
 234                 /* Wait for initial sequence complete. */
 235                 ret = readl_poll_timeout(data->base + ASPEED_REG_ENGINE_CONTROL,
 236                                          adc_engine_control_reg_val,
 237                                          adc_engine_control_reg_val &
 238                                          ASPEED_ADC_CTRL_INIT_RDY,
 239                                          ASPEED_ADC_INIT_POLLING_TIME,
 240                                          ASPEED_ADC_INIT_TIMEOUT);
 241                 if (ret)
 242                         goto poll_timeout_error;
 243         }
 244 
 245         /* Start all channels in normal mode. */
 246         ret = clk_prepare_enable(data->clk_scaler->clk);
 247         if (ret)
 248                 goto clk_enable_error;
 249 
 250         adc_engine_control_reg_val = GENMASK(31, 16) |
 251                 ASPEED_OPERATION_MODE_NORMAL | ASPEED_ENGINE_ENABLE;
 252         writel(adc_engine_control_reg_val,
 253                 data->base + ASPEED_REG_ENGINE_CONTROL);
 254 
 255         model_data = of_device_get_match_data(&pdev->dev);
 256         indio_dev->name = model_data->model_name;
 257         indio_dev->dev.parent = &pdev->dev;
 258         indio_dev->info = &aspeed_adc_iio_info;
 259         indio_dev->modes = INDIO_DIRECT_MODE;
 260         indio_dev->channels = aspeed_adc_iio_channels;
 261         indio_dev->num_channels = ARRAY_SIZE(aspeed_adc_iio_channels);
 262 
 263         ret = iio_device_register(indio_dev);
 264         if (ret)
 265                 goto iio_register_error;
 266 
 267         return 0;
 268 
 269 iio_register_error:
 270         writel(ASPEED_OPERATION_MODE_POWER_DOWN,
 271                 data->base + ASPEED_REG_ENGINE_CONTROL);
 272         clk_disable_unprepare(data->clk_scaler->clk);
 273 clk_enable_error:
 274 poll_timeout_error:
 275         reset_control_assert(data->rst);
 276 reset_error:
 277         clk_hw_unregister_divider(data->clk_scaler);
 278 scaler_error:
 279         clk_hw_unregister_divider(data->clk_prescaler);
 280         return ret;
 281 }
 282 
 283 static int aspeed_adc_remove(struct platform_device *pdev)
 284 {
 285         struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 286         struct aspeed_adc_data *data = iio_priv(indio_dev);
 287 
 288         iio_device_unregister(indio_dev);
 289         writel(ASPEED_OPERATION_MODE_POWER_DOWN,
 290                 data->base + ASPEED_REG_ENGINE_CONTROL);
 291         clk_disable_unprepare(data->clk_scaler->clk);
 292         reset_control_assert(data->rst);
 293         clk_hw_unregister_divider(data->clk_scaler);
 294         clk_hw_unregister_divider(data->clk_prescaler);
 295 
 296         return 0;
 297 }
 298 
 299 static const struct aspeed_adc_model_data ast2400_model_data = {
 300         .model_name = "ast2400-adc",
 301         .vref_voltage = 2500, // mV
 302         .min_sampling_rate = 10000,
 303         .max_sampling_rate = 500000,
 304 };
 305 
 306 static const struct aspeed_adc_model_data ast2500_model_data = {
 307         .model_name = "ast2500-adc",
 308         .vref_voltage = 1800, // mV
 309         .min_sampling_rate = 1,
 310         .max_sampling_rate = 1000000,
 311         .wait_init_sequence = true,
 312 };
 313 
 314 static const struct of_device_id aspeed_adc_matches[] = {
 315         { .compatible = "aspeed,ast2400-adc", .data = &ast2400_model_data },
 316         { .compatible = "aspeed,ast2500-adc", .data = &ast2500_model_data },
 317         {},
 318 };
 319 MODULE_DEVICE_TABLE(of, aspeed_adc_matches);
 320 
 321 static struct platform_driver aspeed_adc_driver = {
 322         .probe = aspeed_adc_probe,
 323         .remove = aspeed_adc_remove,
 324         .driver = {
 325                 .name = KBUILD_MODNAME,
 326                 .of_match_table = aspeed_adc_matches,
 327         }
 328 };
 329 
 330 module_platform_driver(aspeed_adc_driver);
 331 
 332 MODULE_AUTHOR("Rick Altherr <raltherr@google.com>");
 333 MODULE_DESCRIPTION("Aspeed AST2400/2500 ADC Driver");
 334 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */