xref: /linux/drivers/spmi/spmi-mtk-pmif.c (revision 1553a1c48281243359a9529a10ddb551f3b967ab)
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Copyright (c) 2021 MediaTek Inc.
4 
5 #include <linux/clk.h>
6 #include <linux/iopoll.h>
7 #include <linux/module.h>
8 #include <linux/of.h>
9 #include <linux/platform_device.h>
10 #include <linux/property.h>
11 #include <linux/spmi.h>
12 
13 #define SWINF_IDLE	0x00
14 #define SWINF_WFVLDCLR	0x06
15 
16 #define GET_SWINF(x)	(((x) >> 1) & 0x7)
17 
18 #define PMIF_CMD_REG_0		0
19 #define PMIF_CMD_REG		1
20 #define PMIF_CMD_EXT_REG	2
21 #define PMIF_CMD_EXT_REG_LONG	3
22 
23 #define PMIF_DELAY_US   10
24 #define PMIF_TIMEOUT_US (10 * 1000)
25 
26 #define PMIF_CHAN_OFFSET 0x5
27 
28 #define PMIF_MAX_CLKS	3
29 
30 #define SPMI_OP_ST_BUSY 1
31 
32 struct ch_reg {
33 	u32 ch_sta;
34 	u32 wdata;
35 	u32 rdata;
36 	u32 ch_send;
37 	u32 ch_rdy;
38 };
39 
40 struct pmif_data {
41 	const u32	*regs;
42 	const u32	*spmimst_regs;
43 	u32	soc_chan;
44 };
45 
46 struct pmif {
47 	void __iomem	*base;
48 	void __iomem	*spmimst_base;
49 	struct ch_reg	chan;
50 	struct clk_bulk_data clks[PMIF_MAX_CLKS];
51 	size_t nclks;
52 	const struct pmif_data *data;
53 	raw_spinlock_t lock;
54 };
55 
56 static const char * const pmif_clock_names[] = {
57 	"pmif_sys_ck", "pmif_tmr_ck", "spmimst_clk_mux",
58 };
59 
60 enum pmif_regs {
61 	PMIF_INIT_DONE,
62 	PMIF_INF_EN,
63 	PMIF_ARB_EN,
64 	PMIF_CMDISSUE_EN,
65 	PMIF_TIMER_CTRL,
66 	PMIF_SPI_MODE_CTRL,
67 	PMIF_IRQ_EVENT_EN_0,
68 	PMIF_IRQ_FLAG_0,
69 	PMIF_IRQ_CLR_0,
70 	PMIF_IRQ_EVENT_EN_1,
71 	PMIF_IRQ_FLAG_1,
72 	PMIF_IRQ_CLR_1,
73 	PMIF_IRQ_EVENT_EN_2,
74 	PMIF_IRQ_FLAG_2,
75 	PMIF_IRQ_CLR_2,
76 	PMIF_IRQ_EVENT_EN_3,
77 	PMIF_IRQ_FLAG_3,
78 	PMIF_IRQ_CLR_3,
79 	PMIF_IRQ_EVENT_EN_4,
80 	PMIF_IRQ_FLAG_4,
81 	PMIF_IRQ_CLR_4,
82 	PMIF_WDT_EVENT_EN_0,
83 	PMIF_WDT_FLAG_0,
84 	PMIF_WDT_EVENT_EN_1,
85 	PMIF_WDT_FLAG_1,
86 	PMIF_SWINF_0_STA,
87 	PMIF_SWINF_0_WDATA_31_0,
88 	PMIF_SWINF_0_RDATA_31_0,
89 	PMIF_SWINF_0_ACC,
90 	PMIF_SWINF_0_VLD_CLR,
91 	PMIF_SWINF_1_STA,
92 	PMIF_SWINF_1_WDATA_31_0,
93 	PMIF_SWINF_1_RDATA_31_0,
94 	PMIF_SWINF_1_ACC,
95 	PMIF_SWINF_1_VLD_CLR,
96 	PMIF_SWINF_2_STA,
97 	PMIF_SWINF_2_WDATA_31_0,
98 	PMIF_SWINF_2_RDATA_31_0,
99 	PMIF_SWINF_2_ACC,
100 	PMIF_SWINF_2_VLD_CLR,
101 	PMIF_SWINF_3_STA,
102 	PMIF_SWINF_3_WDATA_31_0,
103 	PMIF_SWINF_3_RDATA_31_0,
104 	PMIF_SWINF_3_ACC,
105 	PMIF_SWINF_3_VLD_CLR,
106 };
107 
108 static const u32 mt6873_regs[] = {
109 	[PMIF_INIT_DONE] = 0x0000,
110 	[PMIF_INF_EN] = 0x0024,
111 	[PMIF_ARB_EN] = 0x0150,
112 	[PMIF_CMDISSUE_EN] = 0x03B4,
113 	[PMIF_TIMER_CTRL] = 0x03E0,
114 	[PMIF_SPI_MODE_CTRL] = 0x0400,
115 	[PMIF_IRQ_EVENT_EN_0] = 0x0418,
116 	[PMIF_IRQ_FLAG_0] = 0x0420,
117 	[PMIF_IRQ_CLR_0] = 0x0424,
118 	[PMIF_IRQ_EVENT_EN_1] = 0x0428,
119 	[PMIF_IRQ_FLAG_1] = 0x0430,
120 	[PMIF_IRQ_CLR_1] = 0x0434,
121 	[PMIF_IRQ_EVENT_EN_2] = 0x0438,
122 	[PMIF_IRQ_FLAG_2] = 0x0440,
123 	[PMIF_IRQ_CLR_2] = 0x0444,
124 	[PMIF_IRQ_EVENT_EN_3] = 0x0448,
125 	[PMIF_IRQ_FLAG_3] = 0x0450,
126 	[PMIF_IRQ_CLR_3] = 0x0454,
127 	[PMIF_IRQ_EVENT_EN_4] = 0x0458,
128 	[PMIF_IRQ_FLAG_4] = 0x0460,
129 	[PMIF_IRQ_CLR_4] = 0x0464,
130 	[PMIF_WDT_EVENT_EN_0] = 0x046C,
131 	[PMIF_WDT_FLAG_0] = 0x0470,
132 	[PMIF_WDT_EVENT_EN_1] = 0x0474,
133 	[PMIF_WDT_FLAG_1] = 0x0478,
134 	[PMIF_SWINF_0_ACC] = 0x0C00,
135 	[PMIF_SWINF_0_WDATA_31_0] = 0x0C04,
136 	[PMIF_SWINF_0_RDATA_31_0] = 0x0C14,
137 	[PMIF_SWINF_0_VLD_CLR] = 0x0C24,
138 	[PMIF_SWINF_0_STA] = 0x0C28,
139 	[PMIF_SWINF_1_ACC] = 0x0C40,
140 	[PMIF_SWINF_1_WDATA_31_0] = 0x0C44,
141 	[PMIF_SWINF_1_RDATA_31_0] = 0x0C54,
142 	[PMIF_SWINF_1_VLD_CLR] = 0x0C64,
143 	[PMIF_SWINF_1_STA] = 0x0C68,
144 	[PMIF_SWINF_2_ACC] = 0x0C80,
145 	[PMIF_SWINF_2_WDATA_31_0] = 0x0C84,
146 	[PMIF_SWINF_2_RDATA_31_0] = 0x0C94,
147 	[PMIF_SWINF_2_VLD_CLR] = 0x0CA4,
148 	[PMIF_SWINF_2_STA] = 0x0CA8,
149 	[PMIF_SWINF_3_ACC] = 0x0CC0,
150 	[PMIF_SWINF_3_WDATA_31_0] = 0x0CC4,
151 	[PMIF_SWINF_3_RDATA_31_0] = 0x0CD4,
152 	[PMIF_SWINF_3_VLD_CLR] = 0x0CE4,
153 	[PMIF_SWINF_3_STA] = 0x0CE8,
154 };
155 
156 static const u32 mt8195_regs[] = {
157 	[PMIF_INIT_DONE] = 0x0000,
158 	[PMIF_INF_EN] = 0x0024,
159 	[PMIF_ARB_EN] = 0x0150,
160 	[PMIF_CMDISSUE_EN] = 0x03B8,
161 	[PMIF_TIMER_CTRL] = 0x03E4,
162 	[PMIF_SPI_MODE_CTRL] = 0x0408,
163 	[PMIF_IRQ_EVENT_EN_0] = 0x0420,
164 	[PMIF_IRQ_FLAG_0] = 0x0428,
165 	[PMIF_IRQ_CLR_0] = 0x042C,
166 	[PMIF_IRQ_EVENT_EN_1] = 0x0430,
167 	[PMIF_IRQ_FLAG_1] = 0x0438,
168 	[PMIF_IRQ_CLR_1] = 0x043C,
169 	[PMIF_IRQ_EVENT_EN_2] = 0x0440,
170 	[PMIF_IRQ_FLAG_2] = 0x0448,
171 	[PMIF_IRQ_CLR_2] = 0x044C,
172 	[PMIF_IRQ_EVENT_EN_3] = 0x0450,
173 	[PMIF_IRQ_FLAG_3] = 0x0458,
174 	[PMIF_IRQ_CLR_3] = 0x045C,
175 	[PMIF_IRQ_EVENT_EN_4] = 0x0460,
176 	[PMIF_IRQ_FLAG_4] = 0x0468,
177 	[PMIF_IRQ_CLR_4] = 0x046C,
178 	[PMIF_WDT_EVENT_EN_0] = 0x0474,
179 	[PMIF_WDT_FLAG_0] = 0x0478,
180 	[PMIF_WDT_EVENT_EN_1] = 0x047C,
181 	[PMIF_WDT_FLAG_1] = 0x0480,
182 	[PMIF_SWINF_0_ACC] = 0x0800,
183 	[PMIF_SWINF_0_WDATA_31_0] = 0x0804,
184 	[PMIF_SWINF_0_RDATA_31_0] = 0x0814,
185 	[PMIF_SWINF_0_VLD_CLR] = 0x0824,
186 	[PMIF_SWINF_0_STA] = 0x0828,
187 	[PMIF_SWINF_1_ACC] = 0x0840,
188 	[PMIF_SWINF_1_WDATA_31_0] = 0x0844,
189 	[PMIF_SWINF_1_RDATA_31_0] = 0x0854,
190 	[PMIF_SWINF_1_VLD_CLR] = 0x0864,
191 	[PMIF_SWINF_1_STA] = 0x0868,
192 	[PMIF_SWINF_2_ACC] = 0x0880,
193 	[PMIF_SWINF_2_WDATA_31_0] = 0x0884,
194 	[PMIF_SWINF_2_RDATA_31_0] = 0x0894,
195 	[PMIF_SWINF_2_VLD_CLR] = 0x08A4,
196 	[PMIF_SWINF_2_STA] = 0x08A8,
197 	[PMIF_SWINF_3_ACC] = 0x08C0,
198 	[PMIF_SWINF_3_WDATA_31_0] = 0x08C4,
199 	[PMIF_SWINF_3_RDATA_31_0] = 0x08D4,
200 	[PMIF_SWINF_3_VLD_CLR] = 0x08E4,
201 	[PMIF_SWINF_3_STA] = 0x08E8,
202 };
203 
204 enum spmi_regs {
205 	SPMI_OP_ST_CTRL,
206 	SPMI_GRP_ID_EN,
207 	SPMI_OP_ST_STA,
208 	SPMI_MST_SAMPL,
209 	SPMI_MST_REQ_EN,
210 	SPMI_REC_CTRL,
211 	SPMI_REC0,
212 	SPMI_REC1,
213 	SPMI_REC2,
214 	SPMI_REC3,
215 	SPMI_REC4,
216 	SPMI_MST_DBG,
217 
218 	/* MT8195 spmi regs */
219 	SPMI_MST_RCS_CTRL,
220 	SPMI_SLV_3_0_EINT,
221 	SPMI_SLV_7_4_EINT,
222 	SPMI_SLV_B_8_EINT,
223 	SPMI_SLV_F_C_EINT,
224 	SPMI_REC_CMD_DEC,
225 	SPMI_DEC_DBG,
226 };
227 
228 static const u32 mt6873_spmi_regs[] = {
229 	[SPMI_OP_ST_CTRL] = 0x0000,
230 	[SPMI_GRP_ID_EN] = 0x0004,
231 	[SPMI_OP_ST_STA] = 0x0008,
232 	[SPMI_MST_SAMPL] = 0x000c,
233 	[SPMI_MST_REQ_EN] = 0x0010,
234 	[SPMI_REC_CTRL] = 0x0040,
235 	[SPMI_REC0] = 0x0044,
236 	[SPMI_REC1] = 0x0048,
237 	[SPMI_REC2] = 0x004c,
238 	[SPMI_REC3] = 0x0050,
239 	[SPMI_REC4] = 0x0054,
240 	[SPMI_MST_DBG] = 0x00fc,
241 };
242 
243 static const u32 mt8195_spmi_regs[] = {
244 	[SPMI_OP_ST_CTRL] = 0x0000,
245 	[SPMI_GRP_ID_EN] = 0x0004,
246 	[SPMI_OP_ST_STA] = 0x0008,
247 	[SPMI_MST_SAMPL] = 0x000C,
248 	[SPMI_MST_REQ_EN] = 0x0010,
249 	[SPMI_MST_RCS_CTRL] = 0x0014,
250 	[SPMI_SLV_3_0_EINT] = 0x0020,
251 	[SPMI_SLV_7_4_EINT] = 0x0024,
252 	[SPMI_SLV_B_8_EINT] = 0x0028,
253 	[SPMI_SLV_F_C_EINT] = 0x002C,
254 	[SPMI_REC_CTRL] = 0x0040,
255 	[SPMI_REC0] = 0x0044,
256 	[SPMI_REC1] = 0x0048,
257 	[SPMI_REC2] = 0x004C,
258 	[SPMI_REC3] = 0x0050,
259 	[SPMI_REC4] = 0x0054,
260 	[SPMI_REC_CMD_DEC] = 0x005C,
261 	[SPMI_DEC_DBG] = 0x00F8,
262 	[SPMI_MST_DBG] = 0x00FC,
263 };
264 
265 static u32 pmif_readl(struct pmif *arb, enum pmif_regs reg)
266 {
267 	return readl(arb->base + arb->data->regs[reg]);
268 }
269 
270 static void pmif_writel(struct pmif *arb, u32 val, enum pmif_regs reg)
271 {
272 	writel(val, arb->base + arb->data->regs[reg]);
273 }
274 
275 static void mtk_spmi_writel(struct pmif *arb, u32 val, enum spmi_regs reg)
276 {
277 	writel(val, arb->spmimst_base + arb->data->spmimst_regs[reg]);
278 }
279 
280 static bool pmif_is_fsm_vldclr(struct pmif *arb)
281 {
282 	u32 reg_rdata;
283 
284 	reg_rdata = pmif_readl(arb, arb->chan.ch_sta);
285 
286 	return GET_SWINF(reg_rdata) == SWINF_WFVLDCLR;
287 }
288 
289 static int pmif_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
290 {
291 	struct pmif *arb = spmi_controller_get_drvdata(ctrl);
292 	u32 rdata, cmd;
293 	int ret;
294 
295 	/* Check the opcode */
296 	if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP)
297 		return -EINVAL;
298 
299 	cmd = opc - SPMI_CMD_RESET;
300 
301 	mtk_spmi_writel(arb, (cmd << 0x4) | sid, SPMI_OP_ST_CTRL);
302 	ret = readl_poll_timeout_atomic(arb->spmimst_base + arb->data->spmimst_regs[SPMI_OP_ST_STA],
303 					rdata, (rdata & SPMI_OP_ST_BUSY) == SPMI_OP_ST_BUSY,
304 					PMIF_DELAY_US, PMIF_TIMEOUT_US);
305 	if (ret < 0)
306 		dev_err(&ctrl->dev, "timeout, err = %d\n", ret);
307 
308 	return ret;
309 }
310 
311 static int pmif_spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
312 			      u16 addr, u8 *buf, size_t len)
313 {
314 	struct pmif *arb = spmi_controller_get_drvdata(ctrl);
315 	struct ch_reg *inf_reg;
316 	int ret;
317 	u32 data, cmd;
318 	unsigned long flags;
319 
320 	/* Check for argument validation. */
321 	if (sid & ~0xf) {
322 		dev_err(&ctrl->dev, "exceed the max slv id\n");
323 		return -EINVAL;
324 	}
325 
326 	if (len > 4) {
327 		dev_err(&ctrl->dev, "pmif supports 1..4 bytes per trans, but:%zu requested", len);
328 
329 		return -EINVAL;
330 	}
331 
332 	if (opc >= 0x60 && opc <= 0x7f)
333 		opc = PMIF_CMD_REG;
334 	else if ((opc >= 0x20 && opc <= 0x2f) || (opc >= 0x38 && opc <= 0x3f))
335 		opc = PMIF_CMD_EXT_REG_LONG;
336 	else
337 		return -EINVAL;
338 
339 	raw_spin_lock_irqsave(&arb->lock, flags);
340 	/* Wait for Software Interface FSM state to be IDLE. */
341 	inf_reg = &arb->chan;
342 	ret = readl_poll_timeout_atomic(arb->base + arb->data->regs[inf_reg->ch_sta],
343 					data, GET_SWINF(data) == SWINF_IDLE,
344 					PMIF_DELAY_US, PMIF_TIMEOUT_US);
345 	if (ret < 0) {
346 		/* set channel ready if the data has transferred */
347 		if (pmif_is_fsm_vldclr(arb))
348 			pmif_writel(arb, 1, inf_reg->ch_rdy);
349 		raw_spin_unlock_irqrestore(&arb->lock, flags);
350 		dev_err(&ctrl->dev, "failed to wait for SWINF_IDLE\n");
351 		return ret;
352 	}
353 
354 	/* Send the command. */
355 	cmd = (opc << 30) | (sid << 24) | ((len - 1) << 16) | addr;
356 	pmif_writel(arb, cmd, inf_reg->ch_send);
357 	raw_spin_unlock_irqrestore(&arb->lock, flags);
358 
359 	/*
360 	 * Wait for Software Interface FSM state to be WFVLDCLR,
361 	 * read the data and clear the valid flag.
362 	 */
363 	ret = readl_poll_timeout_atomic(arb->base + arb->data->regs[inf_reg->ch_sta],
364 					data, GET_SWINF(data) == SWINF_WFVLDCLR,
365 					PMIF_DELAY_US, PMIF_TIMEOUT_US);
366 	if (ret < 0) {
367 		dev_err(&ctrl->dev, "failed to wait for SWINF_WFVLDCLR\n");
368 		return ret;
369 	}
370 
371 	data = pmif_readl(arb, inf_reg->rdata);
372 	memcpy(buf, &data, len);
373 	pmif_writel(arb, 1, inf_reg->ch_rdy);
374 
375 	return 0;
376 }
377 
378 static int pmif_spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
379 			       u16 addr, const u8 *buf, size_t len)
380 {
381 	struct pmif *arb = spmi_controller_get_drvdata(ctrl);
382 	struct ch_reg *inf_reg;
383 	int ret;
384 	u32 data, wdata, cmd;
385 	unsigned long flags;
386 
387 	/* Check for argument validation. */
388 	if (unlikely(sid & ~0xf)) {
389 		dev_err(&ctrl->dev, "exceed the max slv id\n");
390 		return -EINVAL;
391 	}
392 
393 	if (len > 4) {
394 		dev_err(&ctrl->dev, "pmif supports 1..4 bytes per trans, but:%zu requested", len);
395 
396 		return -EINVAL;
397 	}
398 
399 	/* Check the opcode */
400 	if (opc >= 0x40 && opc <= 0x5F)
401 		opc = PMIF_CMD_REG;
402 	else if ((opc <= 0xF) || (opc >= 0x30 && opc <= 0x37))
403 		opc = PMIF_CMD_EXT_REG_LONG;
404 	else if (opc >= 0x80)
405 		opc = PMIF_CMD_REG_0;
406 	else
407 		return -EINVAL;
408 
409 	/* Set the write data. */
410 	memcpy(&wdata, buf, len);
411 
412 	raw_spin_lock_irqsave(&arb->lock, flags);
413 	/* Wait for Software Interface FSM state to be IDLE. */
414 	inf_reg = &arb->chan;
415 	ret = readl_poll_timeout_atomic(arb->base + arb->data->regs[inf_reg->ch_sta],
416 					data, GET_SWINF(data) == SWINF_IDLE,
417 					PMIF_DELAY_US, PMIF_TIMEOUT_US);
418 	if (ret < 0) {
419 		/* set channel ready if the data has transferred */
420 		if (pmif_is_fsm_vldclr(arb))
421 			pmif_writel(arb, 1, inf_reg->ch_rdy);
422 		raw_spin_unlock_irqrestore(&arb->lock, flags);
423 		dev_err(&ctrl->dev, "failed to wait for SWINF_IDLE\n");
424 		return ret;
425 	}
426 
427 	pmif_writel(arb, wdata, inf_reg->wdata);
428 
429 	/* Send the command. */
430 	cmd = (opc << 30) | BIT(29) | (sid << 24) | ((len - 1) << 16) | addr;
431 	pmif_writel(arb, cmd, inf_reg->ch_send);
432 	raw_spin_unlock_irqrestore(&arb->lock, flags);
433 
434 	return 0;
435 }
436 
437 static const struct pmif_data mt6873_pmif_arb = {
438 	.regs = mt6873_regs,
439 	.spmimst_regs = mt6873_spmi_regs,
440 	.soc_chan = 2,
441 };
442 
443 static const struct pmif_data mt8195_pmif_arb = {
444 	.regs = mt8195_regs,
445 	.spmimst_regs = mt8195_spmi_regs,
446 	.soc_chan = 2,
447 };
448 
449 static int mtk_spmi_probe(struct platform_device *pdev)
450 {
451 	struct pmif *arb;
452 	struct spmi_controller *ctrl;
453 	int err, i;
454 	u32 chan_offset;
455 
456 	ctrl = devm_spmi_controller_alloc(&pdev->dev, sizeof(*arb));
457 	if (IS_ERR(ctrl))
458 		return PTR_ERR(ctrl);
459 
460 	arb = spmi_controller_get_drvdata(ctrl);
461 	arb->data = device_get_match_data(&pdev->dev);
462 	if (!arb->data) {
463 		dev_err(&pdev->dev, "Cannot get drv_data\n");
464 		return -EINVAL;
465 	}
466 
467 	arb->base = devm_platform_ioremap_resource_byname(pdev, "pmif");
468 	if (IS_ERR(arb->base))
469 		return PTR_ERR(arb->base);
470 
471 	arb->spmimst_base = devm_platform_ioremap_resource_byname(pdev, "spmimst");
472 	if (IS_ERR(arb->spmimst_base))
473 		return PTR_ERR(arb->spmimst_base);
474 
475 	arb->nclks = ARRAY_SIZE(pmif_clock_names);
476 	for (i = 0; i < arb->nclks; i++)
477 		arb->clks[i].id = pmif_clock_names[i];
478 
479 	err = clk_bulk_get(&pdev->dev, arb->nclks, arb->clks);
480 	if (err) {
481 		dev_err(&pdev->dev, "Failed to get clocks: %d\n", err);
482 		return err;
483 	}
484 
485 	err = clk_bulk_prepare_enable(arb->nclks, arb->clks);
486 	if (err) {
487 		dev_err(&pdev->dev, "Failed to enable clocks: %d\n", err);
488 		goto err_put_clks;
489 	}
490 
491 	ctrl->cmd = pmif_arb_cmd;
492 	ctrl->read_cmd = pmif_spmi_read_cmd;
493 	ctrl->write_cmd = pmif_spmi_write_cmd;
494 
495 	chan_offset = PMIF_CHAN_OFFSET * arb->data->soc_chan;
496 	arb->chan.ch_sta = PMIF_SWINF_0_STA + chan_offset;
497 	arb->chan.wdata = PMIF_SWINF_0_WDATA_31_0 + chan_offset;
498 	arb->chan.rdata = PMIF_SWINF_0_RDATA_31_0 + chan_offset;
499 	arb->chan.ch_send = PMIF_SWINF_0_ACC + chan_offset;
500 	arb->chan.ch_rdy = PMIF_SWINF_0_VLD_CLR + chan_offset;
501 
502 	raw_spin_lock_init(&arb->lock);
503 
504 	platform_set_drvdata(pdev, ctrl);
505 
506 	err = spmi_controller_add(ctrl);
507 	if (err)
508 		goto err_domain_remove;
509 
510 	return 0;
511 
512 err_domain_remove:
513 	clk_bulk_disable_unprepare(arb->nclks, arb->clks);
514 err_put_clks:
515 	clk_bulk_put(arb->nclks, arb->clks);
516 	return err;
517 }
518 
519 static void mtk_spmi_remove(struct platform_device *pdev)
520 {
521 	struct spmi_controller *ctrl = platform_get_drvdata(pdev);
522 	struct pmif *arb = spmi_controller_get_drvdata(ctrl);
523 
524 	spmi_controller_remove(ctrl);
525 	clk_bulk_disable_unprepare(arb->nclks, arb->clks);
526 	clk_bulk_put(arb->nclks, arb->clks);
527 }
528 
529 static const struct of_device_id mtk_spmi_match_table[] = {
530 	{
531 		.compatible = "mediatek,mt6873-spmi",
532 		.data = &mt6873_pmif_arb,
533 	}, {
534 		.compatible = "mediatek,mt8195-spmi",
535 		.data = &mt8195_pmif_arb,
536 	}, {
537 		/* sentinel */
538 	},
539 };
540 MODULE_DEVICE_TABLE(of, mtk_spmi_match_table);
541 
542 static struct platform_driver mtk_spmi_driver = {
543 	.driver		= {
544 		.name	= "spmi-mtk",
545 		.of_match_table = mtk_spmi_match_table,
546 	},
547 	.probe		= mtk_spmi_probe,
548 	.remove_new	= mtk_spmi_remove,
549 };
550 module_platform_driver(mtk_spmi_driver);
551 
552 MODULE_AUTHOR("Hsin-Hsiung Wang <hsin-hsiung.wang@mediatek.com>");
553 MODULE_DESCRIPTION("MediaTek SPMI Driver");
554 MODULE_LICENSE("GPL");
555