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