Merge tag 'eventfs-v6.8-2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[linux-block.git] / drivers / mfd / rk8xx-spi.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Rockchip RK806 Core (SPI) driver
4  *
5  * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
6  * Copyright (c) 2023 Collabora Ltd.
7  *
8  * Author: Xu Shengfei <xsf@rock-chips.com>
9  * Author: Sebastian Reichel <sebastian.reichel@collabora.com>
10  */
11
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>
18
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))
22
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),
26 };
27
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),
31 };
32
33 static const struct regmap_config rk806_regmap_config_spi = {
34         .reg_bits = 16,
35         .val_bits = 8,
36         .max_register = RK806_BUCK_RSERVE_REG5,
37         .cache_type = REGCACHE_RBTREE,
38         .volatile_table = &rk806_volatile_table,
39 };
40
41 static int rk806_spi_bus_write(void *context, const void *vdata, size_t count)
42 {
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;
48         char cmd;
49
50         if (val_size < 1 || val_size > (RK806_CMD_LEN_MSK + 1))
51                 return -EINVAL;
52
53         cmd = RK806_CMD_WITH_SIZE(WRITE, val_size);
54
55         xfer[0].tx_buf = &cmd;
56         xfer[0].len = sizeof(cmd);
57         xfer[1].tx_buf = vdata;
58         xfer[1].len = count;
59
60         return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
61 }
62
63 static int rk806_spi_bus_read(void *context, const void *vreg, size_t reg_size,
64                               void *val, size_t val_size)
65 {
66         struct device *dev = context;
67         struct spi_device *spi = to_spi_device(dev);
68         char txbuf[3] = { 0 };
69
70         if (reg_size != RK806_ADDR_SIZE ||
71             val_size < 1 || val_size > (RK806_CMD_LEN_MSK + 1))
72                 return -EINVAL;
73
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);
77
78         return spi_write_then_read(spi, txbuf, sizeof(txbuf), val, val_size);
79 }
80
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,
85 };
86
87 static int rk8xx_spi_probe(struct spi_device *spi)
88 {
89         struct regmap *regmap;
90
91         regmap = devm_regmap_init(&spi->dev, &rk806_regmap_bus_spi,
92                                   &spi->dev, &rk806_regmap_config_spi);
93         if (IS_ERR(regmap))
94                 return dev_err_probe(&spi->dev, PTR_ERR(regmap),
95                                      "Failed to init regmap\n");
96
97         return rk8xx_probe(&spi->dev, RK806_ID, spi->irq, regmap);
98 }
99
100 static const struct of_device_id rk8xx_spi_of_match[] = {
101         { .compatible = "rockchip,rk806", },
102         { }
103 };
104 MODULE_DEVICE_TABLE(of, rk8xx_spi_of_match);
105
106 static const struct spi_device_id rk8xx_spi_id_table[] = {
107         { "rk806", 0 },
108         { }
109 };
110 MODULE_DEVICE_TABLE(spi, rk8xx_spi_id_table);
111
112 static struct spi_driver rk8xx_spi_driver = {
113         .driver         = {
114                 .name   = "rk8xx-spi",
115                 .of_match_table = rk8xx_spi_of_match,
116         },
117         .probe          = rk8xx_spi_probe,
118         .id_table       = rk8xx_spi_id_table,
119 };
120 module_spi_driver(rk8xx_spi_driver);
121
122 MODULE_AUTHOR("Xu Shengfei <xsf@rock-chips.com>");
123 MODULE_DESCRIPTION("RK8xx SPI PMIC driver");
124 MODULE_LICENSE("GPL");