blob: 5bd23262abd611d836c728d3455caa3b8f1b5406 [file] [log] [blame]
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +02001// SPDX-License-Identifier: GPL-2.0
Mayulong70f59c92020-08-17 09:10:20 +02002
3#include <linux/delay.h>
4#include <linux/err.h>
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +02005#include <linux/interrupt.h>
Mayulong70f59c92020-08-17 09:10:20 +02006#include <linux/io.h>
7#include <linux/kernel.h>
Mayulong70f59c92020-08-17 09:10:20 +02008#include <linux/module.h>
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +02009#include <linux/of.h>
10#include <linux/platform_device.h>
Mayulong70f59c92020-08-17 09:10:20 +020011#include <linux/seq_file.h>
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +020012#include <linux/slab.h>
Mayulong70f59c92020-08-17 09:10:20 +020013#include <linux/spmi.h>
Mayulong70f59c92020-08-17 09:10:20 +020014
Mayulong70f59c92020-08-17 09:10:20 +020015/*
16 * SPMI register addr
17 */
Mauro Carvalho Chehab974e3bd2020-08-17 09:10:24 +020018#define SPMI_CHANNEL_OFFSET 0x0300
19#define SPMI_SLAVE_OFFSET 0x20
Mayulong70f59c92020-08-17 09:10:20 +020020
Mauro Carvalho Chehab974e3bd2020-08-17 09:10:24 +020021#define SPMI_APB_SPMI_CMD_BASE_ADDR 0x0100
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +020022
Mayulong70f59c92020-08-17 09:10:20 +020023#define SPMI_APB_SPMI_WDATA0_BASE_ADDR 0x0104
24#define SPMI_APB_SPMI_WDATA1_BASE_ADDR 0x0108
25#define SPMI_APB_SPMI_WDATA2_BASE_ADDR 0x010c
26#define SPMI_APB_SPMI_WDATA3_BASE_ADDR 0x0110
27
28#define SPMI_APB_SPMI_STATUS_BASE_ADDR 0x0200
29
30#define SPMI_APB_SPMI_RDATA0_BASE_ADDR 0x0204
31#define SPMI_APB_SPMI_RDATA1_BASE_ADDR 0x0208
32#define SPMI_APB_SPMI_RDATA2_BASE_ADDR 0x020c
33#define SPMI_APB_SPMI_RDATA3_BASE_ADDR 0x0210
Mayulong70f59c92020-08-17 09:10:20 +020034
Mauro Carvalho Chehab974e3bd2020-08-17 09:10:24 +020035#define SPMI_PER_DATAREG_BYTE 4
Mayulong70f59c92020-08-17 09:10:20 +020036/*
37 * SPMI cmd register
38 */
Mauro Carvalho Chehab974e3bd2020-08-17 09:10:24 +020039#define SPMI_APB_SPMI_CMD_EN BIT(31)
Mayulong70f59c92020-08-17 09:10:20 +020040#define SPMI_APB_SPMI_CMD_TYPE_OFFSET 24
41#define SPMI_APB_SPMI_CMD_LENGTH_OFFSET 20
Mauro Carvalho Chehab974e3bd2020-08-17 09:10:24 +020042#define SPMI_APB_SPMI_CMD_SLAVEID_OFFSET 16
43#define SPMI_APB_SPMI_CMD_ADDR_OFFSET 0
Mayulong70f59c92020-08-17 09:10:20 +020044
45/* Command Opcodes */
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +020046
Mayulong70f59c92020-08-17 09:10:20 +020047enum spmi_controller_cmd_op_code {
48 SPMI_CMD_REG_ZERO_WRITE = 0,
49 SPMI_CMD_REG_WRITE = 1,
50 SPMI_CMD_REG_READ = 2,
51 SPMI_CMD_EXT_REG_WRITE = 3,
52 SPMI_CMD_EXT_REG_READ = 4,
53 SPMI_CMD_EXT_REG_WRITE_L = 5,
54 SPMI_CMD_EXT_REG_READ_L = 6,
55 SPMI_CMD_REG_RESET = 7,
56 SPMI_CMD_REG_SLEEP = 8,
57 SPMI_CMD_REG_SHUTDOWN = 9,
58 SPMI_CMD_REG_WAKEUP = 10,
59};
Mayulong70f59c92020-08-17 09:10:20 +020060
61/*
62 * SPMI status register
63 */
Mauro Carvalho Chehab974e3bd2020-08-17 09:10:24 +020064#define SPMI_APB_TRANS_DONE BIT(0)
65#define SPMI_APB_TRANS_FAIL BIT(2)
Mayulong70f59c92020-08-17 09:10:20 +020066
67/* Command register fields */
68#define SPMI_CONTROLLER_CMD_MAX_BYTE_COUNT 16
69
70/* Maximum number of support PMIC peripherals */
71#define SPMI_CONTROLLER_TIMEOUT_US 1000
Mauro Carvalho Chehab974e3bd2020-08-17 09:10:24 +020072#define SPMI_CONTROLLER_MAX_TRANS_BYTES 16
Mayulong70f59c92020-08-17 09:10:20 +020073
Mayulong70f59c92020-08-17 09:10:20 +020074struct spmi_controller_dev {
75 struct spmi_controller *controller;
76 struct device *dev;
77 void __iomem *base;
78 spinlock_t lock;
79 u32 channel;
80};
81
Mauro Carvalho Chehab4d914a82020-08-17 09:10:27 +020082static int spmi_controller_wait_for_done(struct device *dev,
83 struct spmi_controller_dev *ctrl_dev,
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +020084 void __iomem *base, u8 sid, u16 addr)
Mayulong70f59c92020-08-17 09:10:20 +020085{
Mayulong70f59c92020-08-17 09:10:20 +020086 u32 timeout = SPMI_CONTROLLER_TIMEOUT_US;
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +020087 u32 status, offset;
Mauro Carvalho Chehab974e3bd2020-08-17 09:10:24 +020088
89 offset = SPMI_APB_SPMI_STATUS_BASE_ADDR;
90 offset += SPMI_CHANNEL_OFFSET * ctrl_dev->channel + SPMI_SLAVE_OFFSET * sid;
Mayulong70f59c92020-08-17 09:10:20 +020091
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +020092 do {
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +020093 status = readl(base + offset);
Mayulong70f59c92020-08-17 09:10:20 +020094
95 if (status & SPMI_APB_TRANS_DONE) {
96 if (status & SPMI_APB_TRANS_FAIL) {
Mauro Carvalho Chehab4d914a82020-08-17 09:10:27 +020097 dev_err(dev, "%s: transaction failed (0x%x)\n",
Mayulong70f59c92020-08-17 09:10:20 +020098 __func__, status);
99 return -EIO;
100 }
Mauro Carvalho Chehab4d914a82020-08-17 09:10:27 +0200101 dev_dbg(dev, "%s: status 0x%x\n", __func__, status);
Mayulong70f59c92020-08-17 09:10:20 +0200102 return 0;
103 }
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200104 udelay(1);
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200105 } while (timeout--);
Mayulong70f59c92020-08-17 09:10:20 +0200106
Mauro Carvalho Chehab4d914a82020-08-17 09:10:27 +0200107 dev_err(dev, "%s: timeout, status 0x%x\n", __func__, status);
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200108 return -ETIMEDOUT;
109}
Mayulong70f59c92020-08-17 09:10:20 +0200110
111static int spmi_read_cmd(struct spmi_controller *ctrl,
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200112 u8 opc, u8 slave_id, u16 slave_addr, u8 *__buf, size_t bc)
Mayulong70f59c92020-08-17 09:10:20 +0200113{
114 struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev);
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200115 u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel;
Mayulong70f59c92020-08-17 09:10:20 +0200116 unsigned long flags;
Mauro Carvalho Chehab6af36452020-08-17 09:10:26 +0200117 u8 *buf = __buf;
Mayulong70f59c92020-08-17 09:10:20 +0200118 u32 cmd, data;
119 int rc;
Mayulong70f59c92020-08-17 09:10:20 +0200120 u8 op_code, i;
121
122 if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) {
Mauro Carvalho Chehab4d914a82020-08-17 09:10:27 +0200123 dev_err(&ctrl->dev,
YueHaibing4c6491a2020-09-01 11:57:22 +0800124 "spmi_controller supports 1..%d bytes per trans, but:%zu requested\n",
Mauro Carvalho Chehab4d914a82020-08-17 09:10:27 +0200125 SPMI_CONTROLLER_MAX_TRANS_BYTES, bc);
Mayulong70f59c92020-08-17 09:10:20 +0200126 return -EINVAL;
127 }
128
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200129 switch (opc) {
130 case SPMI_CMD_READ:
Mayulong70f59c92020-08-17 09:10:20 +0200131 op_code = SPMI_CMD_REG_READ;
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200132 break;
133 case SPMI_CMD_EXT_READ:
Mayulong70f59c92020-08-17 09:10:20 +0200134 op_code = SPMI_CMD_EXT_REG_READ;
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200135 break;
136 case SPMI_CMD_EXT_READL:
Mayulong70f59c92020-08-17 09:10:20 +0200137 op_code = SPMI_CMD_EXT_REG_READ_L;
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200138 break;
139 default:
140 dev_err(&ctrl->dev, "invalid read cmd 0x%x\n", opc);
Mayulong70f59c92020-08-17 09:10:20 +0200141 return -EINVAL;
142 }
143
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200144 cmd = SPMI_APB_SPMI_CMD_EN |
145 (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) |
146 ((bc - 1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) |
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200147 ((slave_id & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) | /* slvid */
148 ((slave_addr & 0xffff) << SPMI_APB_SPMI_CMD_ADDR_OFFSET); /* slave_addr */
Mayulong70f59c92020-08-17 09:10:20 +0200149
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200150 spin_lock_irqsave(&spmi_controller->lock, flags);
Mayulong70f59c92020-08-17 09:10:20 +0200151
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200152 writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR);
Mayulong70f59c92020-08-17 09:10:20 +0200153
Mauro Carvalho Chehab4d914a82020-08-17 09:10:27 +0200154 rc = spmi_controller_wait_for_done(&ctrl->dev, spmi_controller,
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200155 spmi_controller->base, slave_id, slave_addr);
Mayulong70f59c92020-08-17 09:10:20 +0200156 if (rc)
157 goto done;
158
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200159 for (i = 0; bc > i * SPMI_PER_DATAREG_BYTE; i++) {
160 data = readl(spmi_controller->base + chnl_ofst +
161 SPMI_SLAVE_OFFSET * slave_id +
162 SPMI_APB_SPMI_RDATA0_BASE_ADDR +
163 i * SPMI_PER_DATAREG_BYTE);
Juan Antonio Aldea-Armenteros1b9419d2020-11-19 13:27:38 +0100164 data = be32_to_cpu((__be32 __force)data);
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200165 if ((bc - i * SPMI_PER_DATAREG_BYTE) >> 2) {
Mayulong70f59c92020-08-17 09:10:20 +0200166 memcpy(buf, &data, sizeof(data));
167 buf += sizeof(data);
168 } else {
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200169 memcpy(buf, &data, bc % SPMI_PER_DATAREG_BYTE);
170 buf += (bc % SPMI_PER_DATAREG_BYTE);
Mayulong70f59c92020-08-17 09:10:20 +0200171 }
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200172 }
Mayulong70f59c92020-08-17 09:10:20 +0200173
174done:
175 spin_unlock_irqrestore(&spmi_controller->lock, flags);
176 if (rc)
Mauro Carvalho Chehab4d914a82020-08-17 09:10:27 +0200177 dev_err(&ctrl->dev,
YueHaibing4c6491a2020-09-01 11:57:22 +0800178 "spmi read wait timeout op:0x%x slave_id:%d slave_addr:0x%x bc:%zu\n",
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200179 opc, slave_id, slave_addr, bc + 1);
Mauro Carvalho Chehab6af36452020-08-17 09:10:26 +0200180 else
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200181 dev_dbg(&ctrl->dev, "%s: id:%d slave_addr:0x%x, read value: %*ph\n",
182 __func__, slave_id, slave_addr, (int)bc, __buf);
Mauro Carvalho Chehab6af36452020-08-17 09:10:26 +0200183
Mayulong70f59c92020-08-17 09:10:20 +0200184 return rc;
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200185}
Mayulong70f59c92020-08-17 09:10:20 +0200186
Mayulong70f59c92020-08-17 09:10:20 +0200187static int spmi_write_cmd(struct spmi_controller *ctrl,
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200188 u8 opc, u8 slave_id, u16 slave_addr, const u8 *__buf, size_t bc)
Mayulong70f59c92020-08-17 09:10:20 +0200189{
190 struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev);
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200191 u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel;
Mauro Carvalho Chehab6af36452020-08-17 09:10:26 +0200192 const u8 *buf = __buf;
Mayulong70f59c92020-08-17 09:10:20 +0200193 unsigned long flags;
Mauro Carvalho Chehab8788a302020-08-17 09:10:25 +0200194 u32 cmd, data;
Mayulong70f59c92020-08-17 09:10:20 +0200195 int rc;
Mayulong70f59c92020-08-17 09:10:20 +0200196 u8 op_code, i;
197
Mayulong70f59c92020-08-17 09:10:20 +0200198 if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) {
Mauro Carvalho Chehab4d914a82020-08-17 09:10:27 +0200199 dev_err(&ctrl->dev,
YueHaibing4c6491a2020-09-01 11:57:22 +0800200 "spmi_controller supports 1..%d bytes per trans, but:%zu requested\n",
Mauro Carvalho Chehab4d914a82020-08-17 09:10:27 +0200201 SPMI_CONTROLLER_MAX_TRANS_BYTES, bc);
Mayulong70f59c92020-08-17 09:10:20 +0200202 return -EINVAL;
203 }
204
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200205 switch (opc) {
206 case SPMI_CMD_WRITE:
Mayulong70f59c92020-08-17 09:10:20 +0200207 op_code = SPMI_CMD_REG_WRITE;
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200208 break;
209 case SPMI_CMD_EXT_WRITE:
Mayulong70f59c92020-08-17 09:10:20 +0200210 op_code = SPMI_CMD_EXT_REG_WRITE;
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200211 break;
212 case SPMI_CMD_EXT_WRITEL:
Mayulong70f59c92020-08-17 09:10:20 +0200213 op_code = SPMI_CMD_EXT_REG_WRITE_L;
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200214 break;
215 default:
216 dev_err(&ctrl->dev, "invalid write cmd 0x%x\n", opc);
Mayulong70f59c92020-08-17 09:10:20 +0200217 return -EINVAL;
218 }
219
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200220 cmd = SPMI_APB_SPMI_CMD_EN |
221 (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) |
222 ((bc - 1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) |
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200223 ((slave_id & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) |
224 ((slave_addr & 0xffff) << SPMI_APB_SPMI_CMD_ADDR_OFFSET);
Mayulong70f59c92020-08-17 09:10:20 +0200225
226 /* Write data to FIFOs */
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200227 spin_lock_irqsave(&spmi_controller->lock, flags);
Mayulong70f59c92020-08-17 09:10:20 +0200228
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200229 for (i = 0; bc > i * SPMI_PER_DATAREG_BYTE; i++) {
Mauro Carvalho Chehab8788a302020-08-17 09:10:25 +0200230 data = 0;
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200231 if ((bc - i * SPMI_PER_DATAREG_BYTE) >> 2) {
Mayulong70f59c92020-08-17 09:10:20 +0200232 memcpy(&data, buf, sizeof(data));
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200233 buf += sizeof(data);
Mayulong70f59c92020-08-17 09:10:20 +0200234 } else {
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200235 memcpy(&data, buf, bc % SPMI_PER_DATAREG_BYTE);
236 buf += (bc % SPMI_PER_DATAREG_BYTE);
Mayulong70f59c92020-08-17 09:10:20 +0200237 }
238
Juan Antonio Aldea-Armenteros1b9419d2020-11-19 13:27:38 +0100239 writel((u32 __force)cpu_to_be32(data),
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200240 spmi_controller->base + chnl_ofst +
241 SPMI_APB_SPMI_WDATA0_BASE_ADDR +
242 SPMI_PER_DATAREG_BYTE * i);
243 }
Mayulong70f59c92020-08-17 09:10:20 +0200244
245 /* Start the transaction */
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200246 writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR);
Mayulong70f59c92020-08-17 09:10:20 +0200247
Mauro Carvalho Chehab4d914a82020-08-17 09:10:27 +0200248 rc = spmi_controller_wait_for_done(&ctrl->dev, spmi_controller,
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200249 spmi_controller->base, slave_id,
250 slave_addr);
Mayulong70f59c92020-08-17 09:10:20 +0200251 spin_unlock_irqrestore(&spmi_controller->lock, flags);
252
253 if (rc)
YueHaibing4c6491a2020-09-01 11:57:22 +0800254 dev_err(&ctrl->dev, "spmi write wait timeout op:0x%x slave_id:%d slave_addr:0x%x bc:%zu\n",
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200255 opc, slave_id, slave_addr, bc);
Mauro Carvalho Chehab6af36452020-08-17 09:10:26 +0200256 else
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200257 dev_dbg(&ctrl->dev, "%s: id:%d slave_addr:0x%x, wrote value: %*ph\n",
258 __func__, slave_id, slave_addr, (int)bc, __buf);
Mayulong70f59c92020-08-17 09:10:20 +0200259
260 return rc;
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200261}
262
Mayulong70f59c92020-08-17 09:10:20 +0200263static int spmi_controller_probe(struct platform_device *pdev)
264{
265 struct spmi_controller_dev *spmi_controller;
266 struct spmi_controller *ctrl;
267 struct resource *iores;
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200268 int ret;
Mauro Carvalho Chehab6af36452020-08-17 09:10:26 +0200269
Mayulong70f59c92020-08-17 09:10:20 +0200270 ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*spmi_controller));
271 if (!ctrl) {
272 dev_err(&pdev->dev, "can not allocate spmi_controller data\n");
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200273 return -ENOMEM;
Mayulong70f59c92020-08-17 09:10:20 +0200274 }
275 spmi_controller = spmi_controller_get_drvdata(ctrl);
276 spmi_controller->controller = ctrl;
277
Mayulong70f59c92020-08-17 09:10:20 +0200278 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
279 if (!iores) {
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200280 dev_err(&pdev->dev, "can not get resource!\n");
Christophe JAILLET12b38ea2020-12-13 16:11:05 +0100281 ret = -EINVAL;
282 goto err_put_controller;
Mayulong70f59c92020-08-17 09:10:20 +0200283 }
284
Dan Carpenterdbbc8fd2020-09-18 17:33:38 +0300285 spmi_controller->base = devm_ioremap(&pdev->dev, iores->start,
286 resource_size(iores));
Mayulong70f59c92020-08-17 09:10:20 +0200287 if (!spmi_controller->base) {
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200288 dev_err(&pdev->dev, "can not remap base addr!\n");
Christophe JAILLET12b38ea2020-12-13 16:11:05 +0100289 ret = -EADDRNOTAVAIL;
290 goto err_put_controller;
Mayulong70f59c92020-08-17 09:10:20 +0200291 }
Mayulong70f59c92020-08-17 09:10:20 +0200292
Mauro Carvalho Chehabfcc84fe2021-06-24 16:01:31 +0200293 ret = of_property_read_u32(pdev->dev.of_node, "hisilicon,spmi-channel",
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200294 &spmi_controller->channel);
Mayulong70f59c92020-08-17 09:10:20 +0200295 if (ret) {
Mauro Carvalho Chehab61963312020-08-17 09:10:23 +0200296 dev_err(&pdev->dev, "can not get channel\n");
Christophe JAILLET12b38ea2020-12-13 16:11:05 +0100297 ret = -ENODEV;
298 goto err_put_controller;
Mayulong70f59c92020-08-17 09:10:20 +0200299 }
300
301 platform_set_drvdata(pdev, spmi_controller);
302 dev_set_drvdata(&ctrl->dev, spmi_controller);
303
304 spin_lock_init(&spmi_controller->lock);
305
306 ctrl->nr = spmi_controller->channel;
307 ctrl->dev.parent = pdev->dev.parent;
308 ctrl->dev.of_node = of_node_get(pdev->dev.of_node);
309
310 /* Callbacks */
311 ctrl->read_cmd = spmi_read_cmd;
312 ctrl->write_cmd = spmi_write_cmd;
313
314 ret = spmi_controller_add(ctrl);
Christophe JAILLET12b38ea2020-12-13 16:11:05 +0100315 if (ret) {
316 dev_err(&pdev->dev, "spmi_controller_add failed with error %d!\n", ret);
317 goto err_put_controller;
318 }
Mauro Carvalho Chehab85eb5342020-08-17 09:10:22 +0200319
Christophe JAILLET12b38ea2020-12-13 16:11:05 +0100320 return 0;
321
322err_put_controller:
323 spmi_controller_put(ctrl);
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200324 return ret;
Mayulong70f59c92020-08-17 09:10:20 +0200325}
326
327static int spmi_del_controller(struct platform_device *pdev)
328{
329 struct spmi_controller *ctrl = platform_get_drvdata(pdev);
330
Mayulong70f59c92020-08-17 09:10:20 +0200331 spmi_controller_remove(ctrl);
Christophe JAILLET12b38ea2020-12-13 16:11:05 +0100332 spmi_controller_put(ctrl);
Mayulong70f59c92020-08-17 09:10:20 +0200333 return 0;
334}
335
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200336static const struct of_device_id spmi_controller_match_table[] = {
Mauro Carvalho Chehabde1a93b2020-08-18 16:58:55 +0200337 {
338 .compatible = "hisilicon,kirin970-spmi-controller",
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200339 },
340 {}
Mayulong70f59c92020-08-17 09:10:20 +0200341};
Mauro Carvalho Chehab85eb5342020-08-17 09:10:22 +0200342MODULE_DEVICE_TABLE(of, spmi_controller_match_table);
Mayulong70f59c92020-08-17 09:10:20 +0200343
344static struct platform_driver spmi_controller_driver = {
345 .probe = spmi_controller_probe,
346 .remove = spmi_del_controller,
347 .driver = {
Mauro Carvalho Chehab7f3ac6c2020-08-17 09:10:29 +0200348 .name = "hisi_spmi_controller",
Mayulong70f59c92020-08-17 09:10:20 +0200349 .of_match_table = spmi_controller_match_table,
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200350 },
351};
352
Mayulong70f59c92020-08-17 09:10:20 +0200353static int __init spmi_controller_init(void)
354{
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200355 return platform_driver_register(&spmi_controller_driver);
Mayulong70f59c92020-08-17 09:10:20 +0200356}
357postcore_initcall(spmi_controller_init);
358
359static void __exit spmi_controller_exit(void)
360{
361 platform_driver_unregister(&spmi_controller_driver);
362}
363module_exit(spmi_controller_exit);
Mayulong70f59c92020-08-17 09:10:20 +0200364
Mauro Carvalho Chehab2ea3f6a2020-08-17 09:10:21 +0200365MODULE_LICENSE("GPL v2");
366MODULE_VERSION("1.0");
Colin Ian Kinge4cebca2020-08-20 08:51:36 +0100367MODULE_ALIAS("platform:spmi_controller");