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