can: tcan4x5x: tcan4x5x_regmap: set reg_stride to 4
[linux-block.git] / drivers / net / can / m_can / tcan4x5x-regmap.c
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // tcan4x5x - Texas Instruments TCAN4x5x Family CAN controller driver
4 //
5 // Copyright (c) 2020 Pengutronix,
6 //                    Marc Kleine-Budde <kernel@pengutronix.de>
7 // Copyright (c) 2018-2019 Texas Instruments Incorporated
8 //                    http://www.ti.com/
9
10 #include "tcan4x5x.h"
11
12 #define TCAN4X5X_WRITE_CMD (0x61 << 24)
13 #define TCAN4X5X_READ_CMD (0x41 << 24)
14
15 #define TCAN4X5X_MAX_REGISTER 0x8ffc
16
17 static int tcan4x5x_regmap_gather_write(void *context, const void *reg,
18                                         size_t reg_len, const void *val,
19                                         size_t val_len)
20 {
21         struct spi_device *spi = context;
22         struct spi_message m;
23         u32 addr;
24         struct spi_transfer t[2] = {
25                 { .tx_buf = &addr, .len = reg_len, .cs_change = 0,},
26                 { .tx_buf = val, .len = val_len, },
27         };
28
29         addr = TCAN4X5X_WRITE_CMD | (*((u16 *)reg) << 8) | val_len >> 2;
30
31         spi_message_init(&m);
32         spi_message_add_tail(&t[0], &m);
33         spi_message_add_tail(&t[1], &m);
34
35         return spi_sync(spi, &m);
36 }
37
38 static int tcan4x5x_regmap_write(void *context, const void *data, size_t count)
39 {
40         return tcan4x5x_regmap_gather_write(context, data, sizeof(u32),
41                                             data + sizeof(u32),
42                                             count - sizeof(u32));
43 }
44
45 static int tcan4x5x_regmap_read(void *context,
46                                 const void *reg, size_t reg_size,
47                                 void *val, size_t val_size)
48 {
49         struct spi_device *spi = context;
50
51         u32 addr = TCAN4X5X_READ_CMD | (*((u16 *)reg) << 8) | val_size >> 2;
52
53         return spi_write_then_read(spi, &addr, reg_size, (u32 *)val, val_size);
54 }
55
56 static const struct regmap_config tcan4x5x_regmap = {
57         .reg_bits = 32,
58         .reg_stride = 4,
59         .val_bits = 32,
60         .cache_type = REGCACHE_NONE,
61         .max_register = TCAN4X5X_MAX_REGISTER,
62 };
63
64 static const struct regmap_bus tcan4x5x_bus = {
65         .write = tcan4x5x_regmap_write,
66         .gather_write = tcan4x5x_regmap_gather_write,
67         .read = tcan4x5x_regmap_read,
68         .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
69         .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
70 };
71
72 int tcan4x5x_regmap_init(struct tcan4x5x_priv *priv)
73 {
74         priv->regmap = devm_regmap_init(&priv->spi->dev, &tcan4x5x_bus,
75                                         priv->spi, &tcan4x5x_regmap);
76         return PTR_ERR_OR_ZERO(priv->regmap);
77 }