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