linux/drivers/base/regmap/regmap-spi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Register map access API - SPI support
   4//
   5// Copyright 2011 Wolfson Microelectronics plc
   6//
   7// Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
   8
   9#include <linux/regmap.h>
  10#include <linux/spi/spi.h>
  11#include <linux/module.h>
  12
  13#include "internal.h"
  14
  15struct regmap_async_spi {
  16        struct regmap_async core;
  17        struct spi_message m;
  18        struct spi_transfer t[2];
  19};
  20
  21static void regmap_spi_complete(void *data)
  22{
  23        struct regmap_async_spi *async = data;
  24
  25        regmap_async_complete_cb(&async->core, async->m.status);
  26}
  27
  28static int regmap_spi_write(void *context, const void *data, size_t count)
  29{
  30        struct device *dev = context;
  31        struct spi_device *spi = to_spi_device(dev);
  32
  33        return spi_write(spi, data, count);
  34}
  35
  36static int regmap_spi_gather_write(void *context,
  37                                   const void *reg, size_t reg_len,
  38                                   const void *val, size_t val_len)
  39{
  40        struct device *dev = context;
  41        struct spi_device *spi = to_spi_device(dev);
  42        struct spi_message m;
  43        struct spi_transfer t[2] = { { .tx_buf = reg, .len = reg_len, },
  44                                     { .tx_buf = val, .len = val_len, }, };
  45
  46        spi_message_init(&m);
  47        spi_message_add_tail(&t[0], &m);
  48        spi_message_add_tail(&t[1], &m);
  49
  50        return spi_sync(spi, &m);
  51}
  52
  53static int regmap_spi_async_write(void *context,
  54                                  const void *reg, size_t reg_len,
  55                                  const void *val, size_t val_len,
  56                                  struct regmap_async *a)
  57{
  58        struct regmap_async_spi *async = container_of(a,
  59                                                      struct regmap_async_spi,
  60                                                      core);
  61        struct device *dev = context;
  62        struct spi_device *spi = to_spi_device(dev);
  63
  64        async->t[0].tx_buf = reg;
  65        async->t[0].len = reg_len;
  66        async->t[1].tx_buf = val;
  67        async->t[1].len = val_len;
  68
  69        spi_message_init(&async->m);
  70        spi_message_add_tail(&async->t[0], &async->m);
  71        if (val)
  72                spi_message_add_tail(&async->t[1], &async->m);
  73
  74        async->m.complete = regmap_spi_complete;
  75        async->m.context = async;
  76
  77        return spi_async(spi, &async->m);
  78}
  79
  80static struct regmap_async *regmap_spi_async_alloc(void)
  81{
  82        struct regmap_async_spi *async_spi;
  83
  84        async_spi = kzalloc(sizeof(*async_spi), GFP_KERNEL);
  85        if (!async_spi)
  86                return NULL;
  87
  88        return &async_spi->core;
  89}
  90
  91static int regmap_spi_read(void *context,
  92                           const void *reg, size_t reg_size,
  93                           void *val, size_t val_size)
  94{
  95        struct device *dev = context;
  96        struct spi_device *spi = to_spi_device(dev);
  97
  98        return spi_write_then_read(spi, reg, reg_size, val, val_size);
  99}
 100
 101static const struct regmap_bus regmap_spi = {
 102        .write = regmap_spi_write,
 103        .gather_write = regmap_spi_gather_write,
 104        .async_write = regmap_spi_async_write,
 105        .async_alloc = regmap_spi_async_alloc,
 106        .read = regmap_spi_read,
 107        .read_flag_mask = 0x80,
 108        .reg_format_endian_default = REGMAP_ENDIAN_BIG,
 109        .val_format_endian_default = REGMAP_ENDIAN_BIG,
 110};
 111
 112struct regmap *__regmap_init_spi(struct spi_device *spi,
 113                                 const struct regmap_config *config,
 114                                 struct lock_class_key *lock_key,
 115                                 const char *lock_name)
 116{
 117        return __regmap_init(&spi->dev, &regmap_spi, &spi->dev, config,
 118                             lock_key, lock_name);
 119}
 120EXPORT_SYMBOL_GPL(__regmap_init_spi);
 121
 122struct regmap *__devm_regmap_init_spi(struct spi_device *spi,
 123                                      const struct regmap_config *config,
 124                                      struct lock_class_key *lock_key,
 125                                      const char *lock_name)
 126{
 127        return __devm_regmap_init(&spi->dev, &regmap_spi, &spi->dev, config,
 128                                  lock_key, lock_name);
 129}
 130EXPORT_SYMBOL_GPL(__devm_regmap_init_spi);
 131
 132MODULE_LICENSE("GPL");
 133