1 // SPDX-License-Identifier: GPL-2.0
3 // tcan4x5x - Texas Instruments TCAN4x5x Family CAN controller driver
5 // Copyright (c) 2020 Pengutronix,
6 // Marc Kleine-Budde <kernel@pengutronix.de>
7 // Copyright (c) 2018-2019 Texas Instruments Incorporated
12 #define TCAN4X5X_SPI_INSTRUCTION_WRITE (0x61 << 24)
13 #define TCAN4X5X_SPI_INSTRUCTION_READ (0x41 << 24)
15 #define TCAN4X5X_MAX_REGISTER 0x87fc
17 static int tcan4x5x_regmap_gather_write(void *context
,
18 const void *reg
, size_t reg_len
,
19 const void *val
, size_t val_len
)
21 struct spi_device
*spi
= context
;
22 struct tcan4x5x_priv
*priv
= spi_get_drvdata(spi
);
23 struct tcan4x5x_map_buf
*buf_tx
= &priv
->map_buf_tx
;
24 struct spi_transfer xfer
[] = {
27 .len
= sizeof(buf_tx
->cmd
) + val_len
,
31 memcpy(&buf_tx
->cmd
, reg
, sizeof(buf_tx
->cmd
.cmd
) +
32 sizeof(buf_tx
->cmd
.addr
));
33 tcan4x5x_spi_cmd_set_len(&buf_tx
->cmd
, val_len
);
34 memcpy(buf_tx
->data
, val
, val_len
);
36 return spi_sync_transfer(spi
, xfer
, ARRAY_SIZE(xfer
));
39 static int tcan4x5x_regmap_write(void *context
, const void *data
, size_t count
)
41 return tcan4x5x_regmap_gather_write(context
, data
, sizeof(__be32
),
42 data
+ sizeof(__be32
),
43 count
- sizeof(__be32
));
46 static int tcan4x5x_regmap_read(void *context
,
47 const void *reg_buf
, size_t reg_len
,
48 void *val_buf
, size_t val_len
)
50 struct spi_device
*spi
= context
;
51 struct tcan4x5x_priv
*priv
= spi_get_drvdata(spi
);
52 struct tcan4x5x_map_buf
*buf_rx
= &priv
->map_buf_rx
;
53 struct tcan4x5x_map_buf
*buf_tx
= &priv
->map_buf_tx
;
54 struct spi_transfer xfer
[2] = {
59 struct spi_message msg
;
62 spi_message_init(&msg
);
63 spi_message_add_tail(&xfer
[0], &msg
);
65 memcpy(&buf_tx
->cmd
, reg_buf
, sizeof(buf_tx
->cmd
.cmd
) +
66 sizeof(buf_tx
->cmd
.addr
));
67 tcan4x5x_spi_cmd_set_len(&buf_tx
->cmd
, val_len
);
69 if (spi
->controller
->flags
& SPI_CONTROLLER_HALF_DUPLEX
) {
70 xfer
[0].len
= sizeof(buf_tx
->cmd
);
72 xfer
[1].rx_buf
= val_buf
;
73 xfer
[1].len
= val_len
;
74 spi_message_add_tail(&xfer
[1], &msg
);
76 xfer
[0].rx_buf
= buf_rx
;
77 xfer
[0].len
= sizeof(buf_tx
->cmd
) + val_len
;
79 if (TCAN4X5X_SANITIZE_SPI
)
80 memset(buf_tx
->data
, 0x0, val_len
);
83 err
= spi_sync(spi
, &msg
);
87 if (!(spi
->controller
->flags
& SPI_CONTROLLER_HALF_DUPLEX
))
88 memcpy(val_buf
, buf_rx
->data
, val_len
);
93 static const struct regmap_range tcan4x5x_reg_table_wr_range
[] = {
94 /* Device ID and SPI Registers */
95 regmap_reg_range(0x000c, 0x0010),
96 /* Device configuration registers and Interrupt Flags*/
97 regmap_reg_range(0x0800, 0x080c),
98 regmap_reg_range(0x0820, 0x0820),
99 regmap_reg_range(0x0830, 0x0830),
101 regmap_reg_range(0x100c, 0x102c),
102 regmap_reg_range(0x1048, 0x1048),
103 regmap_reg_range(0x1050, 0x105c),
104 regmap_reg_range(0x1080, 0x1088),
105 regmap_reg_range(0x1090, 0x1090),
106 regmap_reg_range(0x1098, 0x10a0),
107 regmap_reg_range(0x10a8, 0x10b0),
108 regmap_reg_range(0x10b8, 0x10c0),
109 regmap_reg_range(0x10c8, 0x10c8),
110 regmap_reg_range(0x10d0, 0x10d4),
111 regmap_reg_range(0x10e0, 0x10e4),
112 regmap_reg_range(0x10f0, 0x10f0),
113 regmap_reg_range(0x10f8, 0x10f8),
115 regmap_reg_range(0x8000, 0x87fc),
118 static const struct regmap_range tcan4x5x_reg_table_rd_range
[] = {
119 regmap_reg_range(0x0000, 0x0010), /* Device ID and SPI Registers */
120 regmap_reg_range(0x0800, 0x0830), /* Device configuration registers and Interrupt Flags*/
121 regmap_reg_range(0x1000, 0x10fc), /* M_CAN */
122 regmap_reg_range(0x8000, 0x87fc), /* MRAM */
125 static const struct regmap_access_table tcan4x5x_reg_table_wr
= {
126 .yes_ranges
= tcan4x5x_reg_table_wr_range
,
127 .n_yes_ranges
= ARRAY_SIZE(tcan4x5x_reg_table_wr_range
),
130 static const struct regmap_access_table tcan4x5x_reg_table_rd
= {
131 .yes_ranges
= tcan4x5x_reg_table_rd_range
,
132 .n_yes_ranges
= ARRAY_SIZE(tcan4x5x_reg_table_rd_range
),
135 static const struct regmap_config tcan4x5x_regmap
= {
140 .wr_table
= &tcan4x5x_reg_table_wr
,
141 .rd_table
= &tcan4x5x_reg_table_rd
,
142 .max_register
= TCAN4X5X_MAX_REGISTER
,
143 .cache_type
= REGCACHE_NONE
,
144 .read_flag_mask
= (__force
unsigned long)
145 cpu_to_be32(TCAN4X5X_SPI_INSTRUCTION_READ
),
146 .write_flag_mask
= (__force
unsigned long)
147 cpu_to_be32(TCAN4X5X_SPI_INSTRUCTION_WRITE
),
150 static const struct regmap_bus tcan4x5x_bus
= {
151 .write
= tcan4x5x_regmap_write
,
152 .gather_write
= tcan4x5x_regmap_gather_write
,
153 .read
= tcan4x5x_regmap_read
,
154 .reg_format_endian_default
= REGMAP_ENDIAN_BIG
,
155 .val_format_endian_default
= REGMAP_ENDIAN_BIG
,
157 .max_raw_write
= 256,
160 int tcan4x5x_regmap_init(struct tcan4x5x_priv
*priv
)
162 priv
->regmap
= devm_regmap_init(&priv
->spi
->dev
, &tcan4x5x_bus
,
163 priv
->spi
, &tcan4x5x_regmap
);
164 return PTR_ERR_OR_ZERO(priv
->regmap
);