]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/remoteproc/qcom_tz_pil.c
6de08442f57f7089a63b544d4379374239183020
[karo-tx-linux.git] / drivers / remoteproc / qcom_tz_pil.c
1 /*
2  * Qualcomm Peripheral Image Loader
3  *
4  * Copyright (C) 2014 Sony Mobile Communications AB
5  * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/dma-mapping.h>
21 #include <linux/firmware.h>
22 #include <linux/remoteproc.h>
23 #include <linux/interrupt.h>
24 #include <linux/memblock.h>
25 #include <linux/gpio/consumer.h>
26 #include <linux/of.h>
27 #include <linux/elf.h>
28 #include <linux/clk.h>
29 #include <linux/slab.h>
30 #include <linux/regulator/consumer.h>
31 #include <linux/qcom_scm.h>
32 #include <linux/soc/qcom/smem.h>
33 #include <linux/of.h>
34 #include <linux/of_address.h>
35 #include <linux/delay.h>
36 #include <linux/soc/qcom/smd.h>
37
38 #include "remoteproc_internal.h"
39
40 #define PAS_INIT_IMAGE_CMD      1
41 #define PAS_MEM_SETUP_CMD       2
42 #define PAS_AUTH_AND_RESET_CMD  5
43 #define PAS_SHUTDOWN_CMD        6
44 #define PAS_IS_SUPPORTED_CMD    7
45
46 struct qproc {
47         struct device *dev;
48         struct rproc *rproc;
49
50         int pas_id;
51
52         int wdog_irq;
53         int fatal_irq;
54         int ready_irq;
55         int handover_irq;
56         int stop_ack_irq;
57
58         struct gpio_desc *stop_gpio;
59
60         const char *name;
61         struct regulator *pll;
62
63         unsigned proxy_clk_count;
64         bool    no_scm_clks;
65         struct clk *scm_core_clk;
66         struct clk *scm_iface_clk;
67         struct clk *scm_bus_clk;
68         struct clk *scm_src_clk;
69
70         struct clk **proxy_clks;
71
72         struct completion start_done;
73         struct completion stop_done;
74
75         unsigned crash_reason;
76         struct device_node *smd_edge_node;
77
78         phys_addr_t reloc_phys;
79         size_t reloc_size;
80 };
81
82 static int qproc_scm_clk_enable(struct qproc *qproc)
83 {
84         int ret;
85
86         if (qproc->no_scm_clks)
87                 return 0;
88
89         ret = clk_prepare_enable(qproc->scm_core_clk);
90         if (ret)
91                 goto bail;
92         ret = clk_prepare_enable(qproc->scm_iface_clk);
93         if (ret)
94                 goto disable_core;
95         ret = clk_prepare_enable(qproc->scm_bus_clk);
96         if (ret)
97                 goto disable_iface;
98
99         ret = clk_prepare_enable(qproc->scm_src_clk);
100         if (ret)
101                 goto disable_bus;
102
103         return 0;
104
105 disable_bus:
106         clk_disable_unprepare(qproc->scm_bus_clk);
107 disable_iface:
108         clk_disable_unprepare(qproc->scm_iface_clk);
109 disable_core:
110         clk_disable_unprepare(qproc->scm_core_clk);
111 bail:
112         return ret;
113 }
114
115 static void qproc_scm_clk_disable(struct qproc *qproc)
116 {
117         if (qproc->no_scm_clks)
118                 return;
119
120         clk_disable_unprepare(qproc->scm_core_clk);
121         clk_disable_unprepare(qproc->scm_iface_clk);
122         clk_disable_unprepare(qproc->scm_bus_clk);
123         clk_disable_unprepare(qproc->scm_src_clk);
124 }
125
126 /**
127  * struct pil_mdt - Representation of <name>.mdt file in memory
128  * @hdr: ELF32 header
129  * @phdr: ELF32 program headers
130  */
131 struct mdt_hdr {
132         struct elf32_hdr hdr;
133         struct elf32_phdr phdr[];
134 };
135
136 #define segment_is_hash(flag) (((flag) & (0x7 << 24)) == (0x2 << 24))
137
138 static int segment_is_loadable(const struct elf32_phdr *p)
139 {
140         return (p->p_type == PT_LOAD) &&
141                !segment_is_hash(p->p_flags) &&
142                p->p_memsz;
143 }
144
145 static bool segment_is_relocatable(const struct elf32_phdr *p)
146 {
147         return !!(p->p_flags & BIT(27));
148 }
149
150 /**
151  * rproc_mdt_sanity_check() - sanity check mdt firmware header
152  * @rproc: the remote processor handle
153  * @fw: the mdt header firmware image
154  */
155 static int qproc_sanity_check(struct rproc *rproc,
156                                   const struct firmware *fw)
157 {
158         struct elf32_hdr *ehdr;
159         struct mdt_hdr *mdt;
160
161         if (!fw) {
162                 dev_err(&rproc->dev, "failed to load %s\n", rproc->name);
163                 return -EINVAL;
164         }
165
166         if (fw->size < sizeof(struct elf32_hdr)) {
167                 dev_err(&rproc->dev, "image is too small\n");
168                 return -EINVAL;
169         }
170
171         mdt = (struct mdt_hdr *)fw->data;
172         ehdr = &mdt->hdr;
173
174         if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
175                 dev_err(&rproc->dev, "image is corrupted (bad magic)\n");
176                 return -EINVAL;
177         }
178
179         if (ehdr->e_phnum == 0) {
180                 dev_err(&rproc->dev, "no loadable segments\n");
181                 return -EINVAL;
182         }
183
184         if (sizeof(struct elf32_phdr) * ehdr->e_phnum +
185             sizeof(struct elf32_hdr) > fw->size) {
186                 dev_err(&rproc->dev, "firmware size is too small\n");
187                 return -EINVAL;
188         }
189
190         return 0;
191 }
192
193 static struct resource_table * qproc_find_rsc_table(struct rproc *rproc,
194                                                     const struct firmware *fw,
195                                                     int *tablesz)
196 {
197         static struct resource_table table = { .ver = 1, };
198
199         *tablesz = sizeof(table);
200         return &table;
201 }
202
203 static int qproc_load_segment(struct rproc *rproc, const char *fw_name,
204                                 const struct elf32_phdr *phdr, phys_addr_t paddr)
205 {
206         const struct firmware *fw;
207         void *ptr;
208         int ret = 0;
209
210         ptr = ioremap_nocache(paddr, phdr->p_memsz);
211         if (!ptr) {
212                 dev_err(&rproc->dev, "failed to ioremap segment area (%pa+0x%x)\n", &paddr, phdr->p_memsz);
213                 return -EBUSY;
214         }
215
216         if (phdr->p_filesz) {
217                 ret = request_firmware(&fw, fw_name, &rproc->dev);
218                 if (ret) {
219                         dev_err(&rproc->dev, "failed to load %s\n", fw_name);
220                         goto out;
221                 }
222
223                 memcpy_toio(ptr, fw->data, fw->size);
224
225                 release_firmware(fw);
226         }
227
228         if (phdr->p_memsz > phdr->p_filesz)
229                 memset_io(ptr + phdr->p_filesz, 0,
230                           phdr->p_memsz - phdr->p_filesz);
231
232 out:
233         iounmap(ptr);
234         return ret;
235 }
236
237 static int qproc_load(struct rproc *rproc, const struct firmware *fw)
238 {
239         const struct elf32_phdr *phdr;
240         const struct elf32_hdr *ehdr;
241         const struct mdt_hdr *mdt;
242         phys_addr_t min_addr = (phys_addr_t)ULLONG_MAX;
243         phys_addr_t max_addr = 0;
244         phys_addr_t diff_addr;
245         struct qproc *qproc = rproc->priv;
246         char *fw_name;
247         int ret;
248         int i;
249         size_t align = 0;
250         bool relocatable = false;
251         phys_addr_t paddr;
252
253         ret = qproc_scm_clk_enable(qproc);
254         if (ret)
255                 return ret;
256
257         mdt = (struct mdt_hdr *)fw->data;
258         ehdr = &mdt->hdr;
259
260         for (i = 0; i < ehdr->e_phnum; i++) {
261                 phdr = &mdt->phdr[i];
262
263                 if (!segment_is_loadable(phdr))
264                         continue;
265
266                 if (phdr->p_paddr < min_addr) {
267                         min_addr = phdr->p_paddr;
268
269                         if (segment_is_relocatable(phdr)) {
270                                 align = phdr->p_align;
271                                 relocatable = true;
272                         }
273                 }
274
275                 if (phdr->p_paddr + phdr->p_memsz > max_addr)
276                         max_addr = round_up(phdr->p_paddr + phdr->p_memsz, SZ_4K);
277         }
278
279         ret = qcom_scm_pas_init_image(qproc->pas_id, fw->data, fw->size);
280         if (ret) {
281                 dev_err(qproc->dev, "Invalid firmware metadata\n");
282                 return -EINVAL;
283         }
284
285         diff_addr = max_addr - min_addr;
286         dev_dbg(qproc->dev, "pas_mem_setup %pa, %pa\n", &min_addr, &diff_addr);
287
288         ret = qcom_scm_pas_mem_setup(qproc->pas_id,
289                 relocatable ? qproc->reloc_phys : min_addr, max_addr - min_addr);
290         if (ret) {
291                 dev_err(qproc->dev, "unable to setup memory for image\n");
292                 return -EINVAL;
293         }
294
295         fw_name = kzalloc(strlen(qproc->name) + 5, GFP_KERNEL);
296         if (!fw_name)
297                 return -ENOMEM;
298
299         for (i = 0; i < ehdr->e_phnum; i++) {
300                 phdr = &mdt->phdr[i];
301
302                 if (!segment_is_loadable(phdr))
303                         continue;
304
305                 paddr = relocatable ?
306                                 (phdr->p_paddr - min_addr + qproc->reloc_phys) :
307                                 phdr->p_paddr;
308                 sprintf(fw_name, "%s.b%02d", qproc->name, i);
309                 ret = qproc_load_segment(rproc, fw_name, phdr, paddr);
310                 if (ret)
311                         break;
312         }
313
314         kfree(fw_name);
315
316         qproc_scm_clk_disable(qproc);
317
318         return 0;
319 }
320
321 const struct rproc_fw_ops qproc_fw_ops = {
322         .find_rsc_table = qproc_find_rsc_table,
323         .load = qproc_load,
324         .sanity_check = qproc_sanity_check,
325 };
326
327 static int qproc_start(struct rproc *rproc)
328 {
329         struct qproc *qproc = (struct qproc *)rproc->priv;
330         int ret;
331
332         ret = regulator_enable(qproc->pll);
333         if (ret) {
334                 dev_err(qproc->dev, "failed to enable pll supply\n");
335                 return ret;
336         }
337
338         ret = qproc_scm_clk_enable(qproc);
339         if (ret)
340                 goto disable_regulator;
341
342         ret = qcom_scm_pas_auth_and_reset(qproc->pas_id);
343         if (ret) {
344                 dev_err(qproc->dev,
345                                 "failed to authenticate image and release reset\n");
346                 goto unroll_clocks;
347         }
348
349         /* if ready irq not provided skip waiting */
350         if (qproc->ready_irq < 0)
351                 goto done;
352
353         ret = wait_for_completion_timeout(&qproc->start_done, msecs_to_jiffies(10000));
354         if (ret == 0) {
355                 dev_err(qproc->dev, "start timed out\n");
356
357                 qcom_scm_pas_shutdown(qproc->pas_id);
358                 goto unroll_clocks;
359         }
360
361 done:
362         dev_info(qproc->dev, "start successful\n");
363
364         return 0;
365
366 unroll_clocks:
367         qproc_scm_clk_disable(qproc);
368
369 disable_regulator:
370         regulator_disable(qproc->pll);
371
372         return ret;
373 }
374
375 static int qproc_stop(struct rproc *rproc)
376 {
377         return 0;
378 }
379
380 static const struct rproc_ops qproc_ops = {
381         .start = qproc_start,
382         .stop = qproc_stop,
383 };
384
385 static irqreturn_t qproc_wdog_interrupt(int irq, void *dev)
386 {
387         struct qproc *qproc = dev;
388
389         rproc_report_crash(qproc->rproc, RPROC_WATCHDOG);
390         return IRQ_HANDLED;
391 }
392
393 static irqreturn_t qproc_fatal_interrupt(int irq, void *dev)
394 {
395         struct qproc *qproc = dev;
396         size_t len;
397         char *msg;
398         int ret;
399
400         msg = qcom_smem_get(-1, qproc->crash_reason, &len);
401         if (IS_ERR(msg) && len > 0 && msg[0])
402                 dev_err(qproc->dev, "fatal error received: %s\n", msg);
403
404         rproc_report_crash(qproc->rproc, RPROC_FATAL_ERROR);
405
406         if (!ret)
407                 msg[0] = '\0';
408
409         return IRQ_HANDLED;
410 }
411
412 static irqreturn_t qproc_ready_interrupt(int irq, void *dev)
413 {
414         struct qproc *qproc = dev;
415
416         complete(&qproc->start_done);
417
418         return IRQ_HANDLED;
419 }
420
421 static irqreturn_t qproc_handover_interrupt(int irq, void *dev)
422 {
423         struct qproc *qproc = dev;
424
425         qproc_scm_clk_disable(qproc);
426         regulator_disable(qproc->pll);
427         return IRQ_HANDLED;
428 }
429
430 static irqreturn_t qproc_stop_ack_interrupt(int irq, void *dev)
431 {
432         struct qproc *qproc = dev;
433
434         complete(&qproc->stop_done);
435         return IRQ_HANDLED;
436 }
437
438 static ssize_t qproc_boot_store(struct device *dev,
439                                 struct device_attribute *attr,
440                                 const char *buf, size_t size)
441 {
442         struct qproc *qproc = dev_get_drvdata(dev);
443         int ret;
444
445         ret = rproc_boot(qproc->rproc);
446         return ret ? : size;
447 }
448
449 static ssize_t qproc_shutdown_store(struct device *dev,
450                                     struct device_attribute *attr,
451                                     const char *buf, size_t size)
452 {
453         struct qproc *qproc = dev_get_drvdata(dev);
454
455         rproc_shutdown(qproc->rproc);
456         return size;
457 }
458
459 static const struct device_attribute qproc_attrs[] = {
460         __ATTR(boot, S_IWUSR, 0, qproc_boot_store),
461         __ATTR(shutdown, S_IWUSR, 0, qproc_shutdown_store),
462 };
463
464 static int qproc_init_pas(struct qproc *qproc)
465 {
466         char *key;
467         int ret;
468
469         key = "qcom,pas-id";
470         ret = of_property_read_u32(qproc->dev->of_node, key, &qproc->pas_id);
471         if (ret) {
472                 dev_err(qproc->dev, "Missing or incorrect %s\n", key);
473                 return -EINVAL;
474         }
475
476         if (!qcom_scm_pas_supported(qproc->pas_id)) {
477                 dev_err(qproc->dev, "PAS is not available for %d\n", qproc->pas_id);
478                 return -EIO;
479         }
480
481         return 0;
482 }
483
484 static int qproc_init_clocks(struct qproc *qproc)
485 {
486         long rate;
487         int ret;
488
489         if (qproc->no_scm_clks)
490                 return 0;
491
492         qproc->scm_core_clk = devm_clk_get(qproc->dev, "scm_core_clk");
493         if (IS_ERR(qproc->scm_core_clk)) {
494                 if (PTR_ERR(qproc->scm_core_clk) != -EPROBE_DEFER)
495                         dev_err(qproc->dev, "failed to acquire scm_core_clk\n");
496                 return PTR_ERR(qproc->scm_core_clk);
497         }
498
499         qproc->scm_iface_clk = devm_clk_get(qproc->dev, "scm_iface_clk");
500         if (IS_ERR(qproc->scm_iface_clk)) {
501                 if (PTR_ERR(qproc->scm_iface_clk) != -EPROBE_DEFER)
502                         dev_err(qproc->dev, "failed to acquire scm_iface_clk\n");
503                 return PTR_ERR(qproc->scm_iface_clk);
504         }
505
506         qproc->scm_bus_clk = devm_clk_get(qproc->dev, "scm_bus_clk");
507         if (IS_ERR(qproc->scm_bus_clk)) {
508                 if (PTR_ERR(qproc->scm_bus_clk) != -EPROBE_DEFER)
509                         dev_err(qproc->dev, "failed to acquire scm_bus_clk\n");
510                 return PTR_ERR(qproc->scm_bus_clk);
511         }
512
513         qproc->scm_src_clk = devm_clk_get(qproc->dev, "scm_src_clk");
514         if (IS_ERR(qproc->scm_src_clk)) {
515                 if (PTR_ERR(qproc->scm_src_clk) != -EPROBE_DEFER)
516                         dev_err(qproc->dev, "failed to acquire scm_src_clk\n");
517                 return PTR_ERR(qproc->scm_src_clk);
518         }
519
520         ret = clk_set_rate(qproc->scm_core_clk,
521 clk_round_rate(qproc->scm_core_clk, 19200000));
522         ret = clk_set_rate(qproc->scm_bus_clk,
523 clk_round_rate(qproc->scm_bus_clk, 19200000));
524         ret = clk_set_rate(qproc->scm_iface_clk,
525 clk_round_rate(qproc->scm_iface_clk, 19200000));
526         rate = clk_round_rate(qproc->scm_core_clk, 80000000);
527         ret = clk_set_rate(qproc->scm_src_clk, rate);
528         if (ret) {
529                 dev_err(qproc->dev, "failed to set rate of scm_core_clk\n");
530                 return ret;
531         }
532
533         return 0;
534 }
535
536 static int qproc_init_regulators(struct qproc *qproc)
537 {
538         int ret;
539         u32 uA;
540         u32 uV;
541
542         qproc->pll = devm_regulator_get(qproc->dev, "qcom,pll");
543         if (IS_ERR(qproc->pll)) {
544                 if (PTR_ERR(qproc->pll) != -EPROBE_DEFER)
545                         dev_err(qproc->dev, "failed to aquire regulator\n");
546                 return PTR_ERR(qproc->pll);
547         }
548
549         ret = of_property_read_u32(qproc->dev->of_node, "qcom,pll-uV", &uV);
550         if (ret)
551                 dev_warn(qproc->dev, "failed to read qcom,pll_uV, skipping\n");
552         else
553                 regulator_set_voltage(qproc->pll, uV, uV);
554
555         ret = of_property_read_u32(qproc->dev->of_node, "qcom,pll-uA", &uA);
556         if (ret)
557                 dev_warn(qproc->dev, "failed to read qcom,pll_uA, skipping\n");
558         else
559                 regulator_set_load(qproc->pll, uA);
560
561         return 0;
562 }
563
564 static int qproc_request_irq(struct qproc *qproc, struct platform_device *pdev, const char *name, irq_handler_t thread_fn)
565 {
566         int ret;
567
568         ret = platform_get_irq_byname(pdev, name);
569         if (ret < 0) {
570                 dev_err(&pdev->dev, "no %s IRQ defined\n", name);
571                 return ret;
572         }
573
574         ret = devm_request_threaded_irq(&pdev->dev, ret,
575                                         NULL, thread_fn,
576                                         IRQF_TRIGGER_RISING | IRQF_ONESHOT,
577                                         "qproc", qproc);
578         if (ret)
579                 dev_err(&pdev->dev, "request %s IRQ failed\n", name);
580         return ret;
581 }
582
583 static int qproc_probe(struct platform_device *pdev)
584 {
585         struct qproc *qproc;
586         struct rproc *rproc;
587         char *fw_name;
588         const char *name;
589         const char *key;
590         int ret;
591         int i;
592         struct device_node *np;
593         struct resource r;
594
595
596         key = "qcom,firmware-name";
597         ret = of_property_read_string(pdev->dev.of_node, key, &name);
598         if (ret) {
599                 dev_err(&pdev->dev, "missing or incorrect %s\n", key);
600                 return -EINVAL;
601         }
602
603         fw_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s.mdt", name);
604         if (!fw_name)
605                 return -ENOMEM;
606
607         rproc = rproc_alloc(&pdev->dev, pdev->name, &qproc_ops,
608                             fw_name, sizeof(*qproc));
609         if (!rproc) {
610                 dev_err(&pdev->dev, "unable to allocate remoteproc\n");
611                 return -ENOMEM;
612         }
613
614         rproc->fw_ops = &qproc_fw_ops;
615
616         qproc = (struct qproc *)rproc->priv;
617         qproc->dev = &pdev->dev;
618         qproc->rproc = rproc;
619         qproc->name = name;
620         platform_set_drvdata(pdev, qproc);
621
622         init_completion(&qproc->start_done);
623         init_completion(&qproc->stop_done);
624
625         ret = of_property_read_u32(pdev->dev.of_node, "qcom,crash-reason",
626                                    &qproc->crash_reason);
627         if (ret)
628                 dev_info(&pdev->dev, "no crash reason id\n");
629
630         qproc->smd_edge_node = of_parse_phandle(pdev->dev.of_node,
631                                                 "qcom,smd-edges", 0);
632
633         qproc->no_scm_clks = of_device_is_compatible(pdev->dev.of_node,
634                                                      "qcom,apq8064-tz-pil");
635
636         ret = qproc_init_pas(qproc);
637         if (ret)
638                 goto free_rproc;
639
640         ret = qproc_init_clocks(qproc);
641         if (ret)
642                 goto free_rproc;
643
644         ret = qproc_init_regulators(qproc);
645         if (ret)
646                 goto free_rproc;
647
648         ret = qproc_request_irq(qproc, pdev, "wdog", qproc_wdog_interrupt);
649         qproc->wdog_irq = ret;
650
651         ret = qproc_request_irq(qproc, pdev, "fatal", qproc_fatal_interrupt);
652         qproc->fatal_irq = ret;
653
654         ret = qproc_request_irq(qproc, pdev, "ready", qproc_ready_interrupt);
655         qproc->ready_irq = ret;
656
657         ret = qproc_request_irq(qproc, pdev, "handover", qproc_handover_interrupt);
658         qproc->handover_irq = ret;
659
660         ret = qproc_request_irq(qproc, pdev, "stop-ack", qproc_stop_ack_interrupt);
661         qproc->stop_ack_irq = ret;
662
663         for (i = 0; i < ARRAY_SIZE(qproc_attrs); i++) {
664                 ret = device_create_file(&pdev->dev, &qproc_attrs[i]);
665                 if (ret) {
666                         dev_err(&pdev->dev, "unable to create sysfs file\n");
667                         goto remove_device_files;
668                 }
669         }
670
671         np = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
672         if (!np) {
673                 dev_err(&pdev->dev, "No memory region specified\n");
674         } else {
675
676                 ret = of_address_to_resource(np, 0, &r);
677                 of_node_put(np);
678                 if (ret)
679                         return ret;
680
681                 qproc->reloc_phys = r.start;
682                 qproc->reloc_size = resource_size(&r);
683
684                 dev_info(&pdev->dev, "Found relocation area %lu@%pad\n",
685                                 qproc->reloc_size, &qproc->reloc_phys);
686         }
687
688         ret = rproc_add(rproc);
689         if (ret)
690                 goto remove_device_files;
691
692         return 0;
693
694 remove_device_files:
695         for (i--; i >= 0; i--)
696                 device_remove_file(&pdev->dev, &qproc_attrs[i]);
697
698 free_rproc:
699         rproc_put(rproc);
700
701         return ret;
702 }
703
704 static int qproc_remove(struct platform_device *pdev)
705 {
706         struct qproc *qproc = platform_get_drvdata(pdev);
707         int i;
708
709         for (i = 0; i < ARRAY_SIZE(qproc_attrs); i++)
710                 device_remove_file(&pdev->dev, &qproc_attrs[i]);
711
712         rproc_put(qproc->rproc);
713
714         return 0;
715 }
716
717 static const struct of_device_id qproc_of_match[] = {
718         { .compatible = "qcom,tz-pil", },
719         { },
720 };
721
722 static struct platform_driver qproc_driver = {
723         .probe = qproc_probe,
724         .remove = qproc_remove,
725         .driver = {
726                 .name = "qcom-tz-pil",
727                 .of_match_table = qproc_of_match,
728         },
729 };
730
731 module_platform_driver(qproc_driver);