4b7cb4cc7638f0bf540b2f4e7d7a857c56d7795f
[linux-3.10.git] / drivers / video / tegra / host / tsec / tsec.c
1 /*
2  * drivers/video/tegra/host/tsec/tsec.c
3  *
4  * Tegra TSEC Module Support
5  *
6  * Copyright (c) 2012-2013, NVIDIA CORPORATION.  All rights reserved.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms and conditions of the GNU General Public License,
10  * version 2, as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <linux/slab.h>         /* for kzalloc */
22 #include <linux/firmware.h>
23 #include <linux/module.h>
24 #include <linux/pm_runtime.h>
25 #include <mach/clk.h>
26 #include <asm/byteorder.h>      /* for parsing ucode image wrt endianness */
27 #include <linux/delay.h>        /* for udelay */
28 #include <linux/scatterlist.h>
29 #include <linux/stop_machine.h>
30 #include <linux/of.h>
31 #include <linux/of_device.h>
32 #include <linux/of_platform.h>
33
34 #include <mach/pm_domains.h>
35
36 #include "dev.h"
37 #include "tsec.h"
38 #include "hw_tsec.h"
39 #include "bus_client.h"
40 #include "nvhost_acm.h"
41 #include "chip_support.h"
42 #include "nvhost_memmgr.h"
43 #include "nvhost_intr.h"
44 #include "t114/t114.h"
45 #include "t148/t148.h"
46
47 #define TSEC_IDLE_TIMEOUT_DEFAULT       10000   /* 10 milliseconds */
48 #define TSEC_IDLE_CHECK_PERIOD          10      /* 10 usec */
49 #define TSEC_KEY_LENGTH                 16
50 #define TSEC_RESERVE                    256
51 #define TSEC_KEY_OFFSET                 (TSEC_RESERVE - TSEC_KEY_LENGTH)
52 #define TSEC_HOST1X_STATUS_OFFSET       (TSEC_KEY_OFFSET - 4)
53
54 #define TSEC_OS_START_OFFSET    256
55
56 #define get_tsec(ndev) ((struct tsec *)(ndev)->dev.platform_data)
57 #define set_tsec(ndev, f) ((ndev)->dev.platform_data = f)
58
59 /* The key value in ascii hex */
60 static u8 otf_key[TSEC_KEY_LENGTH];
61
62 /* Pointer to this device */
63 struct platform_device *tsec;
64
65 static u32 *host1x_status_offset(struct tsec *m)
66 {
67         return (u32 *)
68                 &(m->mapped[m->os.reserved_offset + TSEC_HOST1X_STATUS_OFFSET]);
69 }
70
71 static u32 tsec_get_host1x_state(void)
72 {
73         struct tsec *m = get_tsec(tsec);
74         u32 ret;
75
76         /* We have dedicated memory byte  */
77         ret = *host1x_status_offset(m);
78         rmb();
79         return ret;
80 }
81
82 static void tsec_set_host1x_state(int state)
83 {
84         struct tsec *m = get_tsec(tsec);
85
86         *host1x_status_offset(m) = state;
87         wmb();
88 }
89
90 static int stop_machine_fn(void *priv)
91 {
92         int timeout = 10000;
93
94         tsec_set_host1x_state(tsec_host1x_access_granted);
95
96         while (tsec_get_host1x_state() != tsec_host1x_release_access
97                         && timeout)
98                 timeout--;
99
100         if (!timeout)
101                 pr_err("TSEC didn't release access");
102
103         tsec_set_host1x_state(tsec_host1x_none);
104
105         return 0;
106 }
107
108 static void disable_tsec_irq(struct platform_device *pdev)
109 {
110         nvhost_intr_disable_general_irq(&nvhost_get_host(pdev)->intr, 20);
111 }
112
113 static void enable_tsec_irq(struct platform_device *pdev)
114 {
115         /* Clear interrupt */
116         nvhost_device_writel(pdev, tsec_irqsclr_r(), 0xffffff);
117         nvhost_device_writel(pdev, tsec_thi_int_status_r(), 0x1);
118         nvhost_intr_enable_general_irq(&nvhost_get_host(pdev)->intr, 20,
119                         nvhost_tsec_isr, nvhost_tsec_isr_thread);
120 }
121
122 void nvhost_tsec_isr(void)
123 {
124         disable_tsec_irq(tsec);
125 }
126
127 void nvhost_tsec_isr_thread(void)
128 {
129         if (tsec_get_host1x_state() == tsec_host1x_request_access)
130                 stop_machine(stop_machine_fn, NULL, NULL);
131         enable_tsec_irq(tsec);
132 }
133
134 /* caller is responsible for freeing */
135 static char *tsec_get_fw_name(struct platform_device *dev)
136 {
137         char *fw_name;
138         u8 maj, min;
139         struct nvhost_device_data *pdata = platform_get_drvdata(dev);
140
141         /* note size here is a little over...*/
142         fw_name = kzalloc(32, GFP_KERNEL);
143         if (!fw_name)
144                 return NULL;
145
146         decode_tsec_ver(pdata->version, &maj, &min);
147         if (maj == 1) {
148                 /* there are no minor versions so far for maj==1 */
149                 sprintf(fw_name, "nvhost_tsec.fw");
150         } else {
151                 kfree(fw_name);
152                 return NULL;
153         }
154
155         dev_info(&dev->dev, "fw name:%s\n", fw_name);
156
157         return fw_name;
158 }
159
160 static int tsec_dma_wait_idle(struct platform_device *dev, u32 *timeout)
161 {
162         if (!*timeout)
163                 *timeout = TSEC_IDLE_TIMEOUT_DEFAULT;
164
165         do {
166                 u32 check = min_t(u32, TSEC_IDLE_CHECK_PERIOD, *timeout);
167                 u32 dmatrfcmd = nvhost_device_readl(dev, tsec_dmatrfcmd_r());
168                 u32 idle_v = tsec_dmatrfcmd_idle_v(dmatrfcmd);
169
170                 if (tsec_dmatrfcmd_idle_true_v() == idle_v)
171                         return 0;
172
173                 udelay(TSEC_IDLE_CHECK_PERIOD);
174                 *timeout -= check;
175         } while (*timeout);
176
177         dev_err(&dev->dev, "dma idle timeout");
178
179         return -1;
180 }
181
182 static int tsec_dma_pa_to_internal_256b(struct platform_device *dev,
183                 u32 offset, u32 internal_offset, bool imem)
184 {
185         u32 cmd = tsec_dmatrfcmd_size_256b_f();
186         u32 pa_offset =  tsec_dmatrffboffs_offs_f(offset);
187         u32 i_offset = tsec_dmatrfmoffs_offs_f(internal_offset);
188         u32 timeout = 0; /* default*/
189
190         if (imem)
191                 cmd |= tsec_dmatrfcmd_imem_true_f();
192
193         nvhost_device_writel(dev, tsec_dmatrfmoffs_r(), i_offset);
194         nvhost_device_writel(dev, tsec_dmatrffboffs_r(), pa_offset);
195         nvhost_device_writel(dev, tsec_dmatrfcmd_r(), cmd);
196
197         return tsec_dma_wait_idle(dev, &timeout);
198
199 }
200
201 static int tsec_wait_idle(struct platform_device *dev, u32 *timeout)
202 {
203         if (!*timeout)
204                 *timeout = TSEC_IDLE_TIMEOUT_DEFAULT;
205
206         do {
207                 u32 check = min_t(u32, TSEC_IDLE_CHECK_PERIOD, *timeout);
208                 u32 w = nvhost_device_readl(dev, tsec_idlestate_r());
209
210                 if (!w)
211                         return 0;
212                 udelay(TSEC_IDLE_CHECK_PERIOD);
213                 *timeout -= check;
214         } while (*timeout);
215
216         return -1;
217 }
218
219 static int tsec_load_kfuse(struct platform_device *pdev)
220 {
221         u32 val;
222         u32 timeout;
223
224         val = nvhost_device_readl(pdev, tsec_tegra_ctl_r());
225         val &= ~tsec_tegra_ctl_tkfi_kfuse_m();
226         nvhost_device_writel(pdev, tsec_tegra_ctl_r(), val);
227
228         val = nvhost_device_readl(pdev, tsec_scp_ctl_pkey_r());
229         val |= tsec_scp_ctl_pkey_request_reload_s();
230         nvhost_device_writel(pdev, tsec_scp_ctl_pkey_r(), val);
231
232         timeout = TSEC_IDLE_TIMEOUT_DEFAULT;
233
234         do {
235                 u32 check = min_t(u32, TSEC_IDLE_CHECK_PERIOD, timeout);
236                 u32 w = nvhost_device_readl(pdev, tsec_scp_ctl_pkey_r());
237
238                 if (w & tsec_scp_ctl_pkey_loaded_m())
239                         break;
240                 udelay(TSEC_IDLE_CHECK_PERIOD);
241                 timeout -= check;
242         } while (timeout);
243
244         val = nvhost_device_readl(pdev, tsec_tegra_ctl_r());
245         val |= tsec_tegra_ctl_tkfi_kfuse_m();
246         nvhost_device_writel(pdev, tsec_tegra_ctl_r(), val);
247
248         if (timeout)
249                 return 0;
250         else
251                 return -1;
252 }
253
254 int tsec_boot(struct platform_device *dev)
255 {
256         u32 timeout;
257         u32 offset;
258         int err = 0;
259         struct tsec *m = get_tsec(dev);
260
261         nvhost_device_writel(dev, tsec_dmactl_r(), 0);
262         nvhost_device_writel(dev, tsec_dmatrfbase_r(),
263                 (sg_dma_address(m->pa->sgl) + m->os.bin_data_offset) >> 8);
264
265         for (offset = 0; offset < m->os.data_size; offset += 256)
266                 tsec_dma_pa_to_internal_256b(dev,
267                                            m->os.data_offset + offset,
268                                            offset, false);
269
270         tsec_dma_pa_to_internal_256b(dev,
271                                      m->os.code_offset+TSEC_OS_START_OFFSET,
272                                      TSEC_OS_START_OFFSET, true);
273
274
275         /* boot tsec */
276         nvhost_device_writel(dev, tsec_bootvec_r(),
277                              tsec_bootvec_vec_f(TSEC_OS_START_OFFSET));
278         nvhost_device_writel(dev, tsec_cpuctl_r(),
279                         tsec_cpuctl_startcpu_true_f());
280
281         timeout = 0; /* default */
282
283         err = tsec_wait_idle(dev, &timeout);
284         if (err != 0) {
285                 dev_err(&dev->dev, "boot failed due to timeout");
286                 return err;
287         }
288
289         /* setup tsec interrupts and enable interface */
290         nvhost_device_writel(dev, tsec_irqmset_r(),
291                         (tsec_irqmset_ext_f(0xff) |
292                                 tsec_irqmset_swgen1_set_f() |
293                                 tsec_irqmset_swgen0_set_f() |
294                                 tsec_irqmset_exterr_set_f() |
295                                 tsec_irqmset_halt_set_f()   |
296                                 tsec_irqmset_wdtmr_set_f()));
297
298         nvhost_device_writel(dev, tsec_itfen_r(),
299                         (tsec_itfen_mthden_enable_f() |
300                                 tsec_itfen_ctxen_enable_f()));
301
302         return tsec_load_kfuse(dev);
303 }
304
305 static int tsec_setup_ucode_image(struct platform_device *dev,
306                 u32 *ucode_ptr,
307                 const struct firmware *ucode_fw)
308 {
309         struct tsec *m = get_tsec(dev);
310         /* image data is little endian. */
311         struct tsec_ucode_v1 ucode;
312         int w;
313         u32 reserved_offset;
314         u32 tsec_key_offset;
315
316         /* copy the whole thing taking into account endianness */
317         for (w = 0; w < ucode_fw->size / sizeof(u32); w++)
318                 ucode_ptr[w] = le32_to_cpu(((u32 *)ucode_fw->data)[w]);
319
320         ucode.bin_header = (struct tsec_ucode_bin_header_v1 *)ucode_ptr;
321         /* endian problems would show up right here */
322         if (ucode.bin_header->bin_magic != 0x10de) {
323                 dev_err(&dev->dev,
324                            "failed to get firmware magic");
325                 return -EINVAL;
326         }
327         if (ucode.bin_header->bin_ver != 1) {
328                 dev_err(&dev->dev,
329                            "unsupported firmware version");
330                 return -ENOENT;
331         }
332         /* shouldn't be bigger than what firmware thinks */
333         if (ucode.bin_header->bin_size > ucode_fw->size) {
334                 dev_err(&dev->dev,
335                            "ucode image size inconsistency");
336                 return -EINVAL;
337         }
338
339         dev_dbg(&dev->dev,
340                 "ucode bin header: magic:0x%x ver:%d size:%d\n",
341                 ucode.bin_header->bin_magic,
342                 ucode.bin_header->bin_ver,
343                 ucode.bin_header->bin_size);
344         dev_dbg(&dev->dev,
345                 "ucode bin header: os bin (header,data) offset size: 0x%x, 0x%x %d\n",
346                 ucode.bin_header->os_bin_header_offset,
347                 ucode.bin_header->os_bin_data_offset,
348                 ucode.bin_header->os_bin_size);
349         ucode.os_header = (struct tsec_ucode_os_header_v1 *)
350                 (((void *)ucode_ptr) + ucode.bin_header->os_bin_header_offset);
351
352         dev_dbg(&dev->dev,
353                 "os ucode header: os code (offset,size): 0x%x, 0x%x\n",
354                 ucode.os_header->os_code_offset,
355                 ucode.os_header->os_code_size);
356         dev_dbg(&dev->dev,
357                 "os ucode header: os data (offset,size): 0x%x, 0x%x\n",
358                 ucode.os_header->os_data_offset,
359                 ucode.os_header->os_data_size);
360         dev_dbg(&dev->dev,
361                 "os ucode header: num apps: %d\n",
362                 ucode.os_header->num_apps);
363
364         /* make space for reserved area - we need 20 bytes, but we move 256
365          * bytes because firmware needs to be 256 byte aligned */
366         reserved_offset = ucode.bin_header->os_bin_data_offset;
367         memmove(((void *)ucode_ptr) + reserved_offset + TSEC_RESERVE,
368                         ((void *)ucode_ptr) + reserved_offset,
369                         ucode.bin_header->os_bin_size);
370         ucode.bin_header->os_bin_data_offset += TSEC_RESERVE;
371
372         /*  clear 256 bytes before ucode os code */
373         memset(((void *)ucode_ptr) + reserved_offset, 0, TSEC_RESERVE);
374
375         /* Copy key to be the 16 bytes before the firmware */
376         tsec_key_offset = reserved_offset + TSEC_KEY_OFFSET;
377         memcpy(((void *)ucode_ptr) + tsec_key_offset, otf_key, TSEC_KEY_LENGTH);
378
379         m->os.size = ucode.bin_header->os_bin_size;
380         m->os.reserved_offset = reserved_offset;
381         m->os.bin_data_offset = ucode.bin_header->os_bin_data_offset;
382         m->os.code_offset = ucode.os_header->os_code_offset;
383         m->os.data_offset = ucode.os_header->os_data_offset;
384         m->os.data_size   = ucode.os_header->os_data_size;
385
386         return 0;
387 }
388
389 int tsec_read_ucode(struct platform_device *dev)
390 {
391         struct tsec *m = get_tsec(dev);
392         const struct firmware *ucode_fw;
393         int err;
394
395         ucode_fw = nvhost_client_request_firmware(dev, TSEC_FIRMWARE_NAME);
396         if (!ucode_fw) {
397                 dev_err(&dev->dev, "failed to get tsec firmware\n");
398                 err = -ENOENT;
399                 return err;
400         }
401
402         /* allocate pages for ucode */
403         m->mem_r = nvhost_memmgr_alloc(nvhost_get_host(dev)->memmgr,
404                              roundup(ucode_fw->size+256, PAGE_SIZE),
405                              PAGE_SIZE, mem_mgr_flag_uncacheable, 0);
406         if (IS_ERR(m->mem_r)) {
407                 dev_err(&dev->dev, "nvmap alloc failed");
408                 err = PTR_ERR(m->mem_r);
409                 m->mem_r = NULL;
410                 goto clean_up;
411         }
412
413         m->pa = nvhost_memmgr_pin(nvhost_get_host(dev)->memmgr, m->mem_r,
414                         &dev->dev);
415         if (IS_ERR(m->pa)) {
416                 dev_err(&dev->dev, "nvmap pin failed for ucode");
417                 err = PTR_ERR(m->pa);
418                 m->pa = 0;
419                 goto clean_up;
420         }
421
422         m->mapped = nvhost_memmgr_mmap(m->mem_r);
423         if (!m->mapped) {
424                 dev_err(&dev->dev, "nvmap mmap failed");
425                 err = -ENOMEM;
426                 goto clean_up;
427         }
428
429         err = tsec_setup_ucode_image(dev, (u32 *)m->mapped, ucode_fw);
430         if (err) {
431                 dev_err(&dev->dev, "failed to parse firmware image\n");
432                 return err;
433         }
434
435         m->valid = true;
436
437         release_firmware(ucode_fw);
438
439         return 0;
440
441 clean_up:
442         if (m->mapped) {
443                 nvhost_memmgr_munmap(m->mem_r, m->mapped);
444                 m->mapped = NULL;
445         }
446         if (m->pa) {
447                 nvhost_memmgr_unpin(nvhost_get_host(dev)->memmgr, m->mem_r,
448                                 &dev->dev, m->pa);
449                 m->pa = NULL;
450         }
451         if (m->mem_r) {
452                 nvhost_memmgr_put(nvhost_get_host(dev)->memmgr, m->mem_r);
453                 m->mem_r = NULL;
454         }
455         release_firmware(ucode_fw);
456         return err;
457 }
458
459 void nvhost_tsec_init(struct platform_device *dev)
460 {
461         int err = 0;
462         struct tsec *m;
463         char *fw_name;
464
465         fw_name = tsec_get_fw_name(dev);
466         if (!fw_name) {
467                 dev_err(&dev->dev, "couldn't determine firmware name");
468                 return;
469         }
470
471         m = kzalloc(sizeof(struct tsec), GFP_KERNEL);
472         if (!m) {
473                 dev_err(&dev->dev, "couldn't alloc ucode");
474                 kfree(fw_name);
475                 return;
476         }
477         set_tsec(dev, m);
478
479         err = tsec_read_ucode(dev);
480         kfree(fw_name);
481         fw_name = 0;
482
483         if (err || !m->valid) {
484                 dev_err(&dev->dev, "ucode not valid");
485                 goto clean_up;
486         }
487
488         nvhost_module_busy(dev);
489
490         tsec_boot(dev);
491         enable_tsec_irq(dev);
492         nvhost_module_idle(dev);
493         return;
494
495 clean_up:
496         dev_err(&dev->dev, "failed");
497 }
498
499 void nvhost_tsec_deinit(struct platform_device *dev)
500 {
501         struct tsec *m = get_tsec(dev);
502
503         disable_tsec_irq(dev);
504
505         /* unpin, free ucode memory */
506         if (m->mem_r) {
507                 if (m->mapped)
508                         nvhost_memmgr_munmap(m->mem_r, m->mapped);
509                 if (m->pa)
510                         nvhost_memmgr_unpin(nvhost_get_host(dev)->memmgr,
511                                         m->mem_r, &dev->dev, m->pa);
512                 if (m->mem_r)
513                         nvhost_memmgr_put(nvhost_get_host(dev)->memmgr,
514                                         m->mem_r);
515                 m->mem_r = 0;
516         }
517         kfree(m);
518         set_tsec(dev, NULL);
519 }
520
521 void nvhost_tsec_finalize_poweron(struct platform_device *dev)
522 {
523         tsec_boot(dev);
524 }
525
526 static struct of_device_id tegra_tsec_of_match[] = {
527         { .compatible = "nvidia,tegra114-tsec",
528                 .data = (struct nvhost_device_data *)&t11_tsec_info },
529         { .compatible = "nvidia,tegra148-tsec",
530                 .data = (struct nvhost_device_data *)&t14_tsec_info },
531         { },
532 };
533
534 static int tsec_probe(struct platform_device *dev)
535 {
536         int err;
537         struct nvhost_device_data *pdata = NULL;
538
539         if (dev->dev.of_node) {
540                 const struct of_device_id *match;
541
542                 match = of_match_device(tegra_tsec_of_match, &dev->dev);
543                 if (match)
544                         pdata = (struct nvhost_device_data *)match->data;
545         } else
546                 pdata = (struct nvhost_device_data *)dev->dev.platform_data;
547
548         WARN_ON(!pdata);
549         if (!pdata) {
550                 dev_info(&dev->dev, "no platform data\n");
551                 return -ENODATA;
552         }
553
554         pdata->pdev = dev;
555         pdata->init = nvhost_tsec_init;
556         pdata->deinit = nvhost_tsec_deinit;
557
558         mutex_init(&pdata->lock);
559
560         platform_set_drvdata(dev, pdata);
561         nvhost_module_init(dev);
562
563         err = nvhost_client_device_get_resources(dev);
564         if (err)
565                 return err;
566
567         tsec = dev;
568
569         tegra_pd_add_device(&dev->dev);
570         if (pdata->clockgate_delay) {
571                 pm_runtime_set_autosuspend_delay(&dev->dev,
572                         pdata->clockgate_delay);
573                 pm_runtime_use_autosuspend(&dev->dev);
574         }
575         pm_runtime_enable(&dev->dev);
576
577         pm_runtime_get_sync(&dev->dev);
578
579         err = nvhost_client_device_init(dev);
580         if (err)
581                 return err;
582
583         /* Reset TSEC at boot-up. Otherwise it starts sending interrupts. */
584         tegra_periph_reset_assert(pdata->clk[0]);
585         udelay(10);
586         tegra_periph_reset_deassert(pdata->clk[0]);
587
588         if (pdata->clockgate_delay)
589                 pm_runtime_put_sync_autosuspend(&dev->dev);
590         else
591                 pm_runtime_put(&dev->dev);
592
593         return err;
594 }
595
596 static int __exit tsec_remove(struct platform_device *dev)
597 {
598         struct nvhost_master *host = nvhost_get_host(dev);
599
600         /* Add clean-up */
601         host->intr.generic_isr[20] = NULL;
602         host->intr.generic_isr_thread[20] = NULL;
603         return 0;
604 }
605
606 #ifdef CONFIG_PM
607 static const struct dev_pm_ops tsec_pm_ops = {
608         .suspend = nvhost_client_device_suspend,
609         .resume = nvhost_client_device_resume,
610 #ifdef CONFIG_PM_RUNTIME
611         .runtime_suspend = nvhost_module_disable_clk,
612         .runtime_resume = nvhost_module_enable_clk,
613 #endif
614 };
615 #endif
616
617 static struct platform_driver tsec_driver = {
618         .probe = tsec_probe,
619         .remove = __exit_p(tsec_remove),
620         .driver = {
621                 .owner = THIS_MODULE,
622                 .name = "tsec",
623 #ifdef CONFIG_PM
624                 .pm = &tsec_pm_ops,
625 #endif
626 #ifdef CONFIG_OF
627                 .of_match_table = tegra_tsec_of_match,
628 #endif
629         }
630 };
631
632 static int __init tsec_key_setup(char *line)
633 {
634         int i;
635         u8 tmp[] = {0,0,0};
636         pr_debug("tsec otf key: %s\n", line);
637
638         if (strlen(line) != TSEC_KEY_LENGTH*2) {
639                 pr_warn("invalid tsec key: %s\n", line);
640                 return 0;
641         }
642
643         for (i = 0; i < TSEC_KEY_LENGTH; i++) {
644                 int err;
645                 memcpy(tmp, &line[i*2], 2);
646                 err = kstrtou8(tmp, 16, &otf_key[i]);
647                 if (err) {
648                         pr_warn("cannot read tsec otf key: %d", err);
649                         break;
650                 }
651         }
652         return 0;
653 }
654 __setup("otf_key=", tsec_key_setup);
655
656 static int __init tsec_init(void)
657 {
658         return platform_driver_register(&tsec_driver);
659 }
660
661 static void __exit tsec_exit(void)
662 {
663         platform_driver_unregister(&tsec_driver);
664 }
665
666 module_init(tsec_init);
667 module_exit(tsec_exit);