1 // SPDX-License-Identifier: GPL-2.0
3 * Rockchip RK806 Core (SPI) driver
5 * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
6 * Copyright (c) 2023 Collabora Ltd.
8 * Author: Xu Shengfei <xsf@rock-chips.com>
9 * Author: Sebastian Reichel <sebastian.reichel@collabora.com>
12 #include <linux/interrupt.h>
13 #include <linux/mfd/core.h>
14 #include <linux/mfd/rk808.h>
15 #include <linux/module.h>
16 #include <linux/regmap.h>
17 #include <linux/spi/spi.h>
19 #define RK806_ADDR_SIZE 2
20 #define RK806_CMD_WITH_SIZE(CMD, VALUE_BYTES) \
21 (RK806_CMD_##CMD | RK806_CMD_CRC_DIS | (VALUE_BYTES - 1))
23 static const struct regmap_range rk806_volatile_ranges
[] = {
24 regmap_reg_range(RK806_POWER_EN0
, RK806_POWER_EN5
),
25 regmap_reg_range(RK806_DVS_START_CTRL
, RK806_INT_MSK1
),
28 static const struct regmap_access_table rk806_volatile_table
= {
29 .yes_ranges
= rk806_volatile_ranges
,
30 .n_yes_ranges
= ARRAY_SIZE(rk806_volatile_ranges
),
33 static const struct regmap_config rk806_regmap_config_spi
= {
36 .max_register
= RK806_BUCK_RSERVE_REG5
,
37 .cache_type
= REGCACHE_MAPLE
,
38 .volatile_table
= &rk806_volatile_table
,
41 static int rk806_spi_bus_write(void *context
, const void *vdata
, size_t count
)
43 struct device
*dev
= context
;
44 struct spi_device
*spi
= to_spi_device(dev
);
45 struct spi_transfer xfer
[2] = { 0 };
46 /* data and thus count includes the register address */
47 size_t val_size
= count
- RK806_ADDR_SIZE
;
50 if (val_size
< 1 || val_size
> (RK806_CMD_LEN_MSK
+ 1))
53 cmd
= RK806_CMD_WITH_SIZE(WRITE
, val_size
);
55 xfer
[0].tx_buf
= &cmd
;
56 xfer
[0].len
= sizeof(cmd
);
57 xfer
[1].tx_buf
= vdata
;
60 return spi_sync_transfer(spi
, xfer
, ARRAY_SIZE(xfer
));
63 static int rk806_spi_bus_read(void *context
, const void *vreg
, size_t reg_size
,
64 void *val
, size_t val_size
)
66 struct device
*dev
= context
;
67 struct spi_device
*spi
= to_spi_device(dev
);
68 char txbuf
[3] = { 0 };
70 if (reg_size
!= RK806_ADDR_SIZE
||
71 val_size
< 1 || val_size
> (RK806_CMD_LEN_MSK
+ 1))
74 /* TX buffer contains command byte followed by two address bytes */
75 txbuf
[0] = RK806_CMD_WITH_SIZE(READ
, val_size
);
76 memcpy(txbuf
+1, vreg
, reg_size
);
78 return spi_write_then_read(spi
, txbuf
, sizeof(txbuf
), val
, val_size
);
81 static const struct regmap_bus rk806_regmap_bus_spi
= {
82 .write
= rk806_spi_bus_write
,
83 .read
= rk806_spi_bus_read
,
84 .reg_format_endian_default
= REGMAP_ENDIAN_LITTLE
,
87 static int rk8xx_spi_probe(struct spi_device
*spi
)
89 struct regmap
*regmap
;
91 regmap
= devm_regmap_init(&spi
->dev
, &rk806_regmap_bus_spi
,
92 &spi
->dev
, &rk806_regmap_config_spi
);
94 return dev_err_probe(&spi
->dev
, PTR_ERR(regmap
),
95 "Failed to init regmap\n");
97 return rk8xx_probe(&spi
->dev
, RK806_ID
, spi
->irq
, regmap
);
100 static const struct of_device_id rk8xx_spi_of_match
[] = {
101 { .compatible
= "rockchip,rk806", },
104 MODULE_DEVICE_TABLE(of
, rk8xx_spi_of_match
);
106 static const struct spi_device_id rk8xx_spi_id_table
[] = {
110 MODULE_DEVICE_TABLE(spi
, rk8xx_spi_id_table
);
112 static struct spi_driver rk8xx_spi_driver
= {
115 .of_match_table
= rk8xx_spi_of_match
,
117 .probe
= rk8xx_spi_probe
,
118 .id_table
= rk8xx_spi_id_table
,
120 module_spi_driver(rk8xx_spi_driver
);
122 MODULE_AUTHOR("Xu Shengfei <xsf@rock-chips.com>");
123 MODULE_DESCRIPTION("RK8xx SPI PMIC driver");
124 MODULE_LICENSE("GPL");