GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / spmi / spmi-mtk-pmif.c
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");