summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/gv11b/fifo_gv11b.c136
-rw-r--r--drivers/gpu/nvgpu/gv11b/platform_gv11b_tegra.c38
2 files changed, 173 insertions, 1 deletions
diff --git a/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c b/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c
index a153de7c..4b4c97b4 100644
--- a/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c
+++ b/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c
@@ -14,11 +14,17 @@
14 */ 14 */
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/types.h> 16#include <linux/types.h>
17#ifdef CONFIG_TEGRA_GK20A_NVHOST
18#include <linux/nvhost.h>
19#include <linux/nvhost_t194.h>
20#endif
17 21
18#include <nvgpu/semaphore.h> 22#include <nvgpu/semaphore.h>
19#include <nvgpu/timers.h> 23#include <nvgpu/timers.h>
20#include <nvgpu/log.h> 24#include <nvgpu/log.h>
21 25#include <nvgpu/dma.h>
26#include <nvgpu/nvgpu_mem.h>
27#include <nvgpu/gmmu.h>
22 28
23#include "gk20a/gk20a.h" 29#include "gk20a/gk20a.h"
24#include "gk20a/fifo_gk20a.h" 30#include "gk20a/fifo_gk20a.h"
@@ -1411,6 +1417,123 @@ static unsigned int gv11b_fifo_handle_pbdma_intr_0(struct gk20a *g,
1411 return rc_type; 1417 return rc_type;
1412} 1418}
1413 1419
1420#ifdef CONFIG_TEGRA_GK20A_NVHOST
1421static int gv11b_fifo_alloc_syncpt_buf(struct channel_gk20a *c,
1422 u32 syncpt_id, struct nvgpu_mem *syncpt_buf)
1423{
1424 struct page **pages;
1425 u32 nr_pages;
1426 u32 i;
1427 int err = 0;
1428 struct gk20a *g = c->g;
1429
1430 /*
1431 * Add rw mapping for entire syncpt shim for current channel vm
1432 * TODO : This needs to replaced with a new mecahnism where
1433 * only current syncpoint range will be rw and other sync
1434 * points range is read only for current channel vm. Also share
1435 * these mapping accross channels if they share same vm
1436 */
1437 nr_pages = DIV_ROUND_UP(g->syncpt_unit_size, PAGE_SIZE);
1438 pages = nvgpu_kzalloc(g, sizeof(struct page *) * nr_pages);
1439 for (i = 0; i < nr_pages; i++)
1440 pages[i] = phys_to_page(g->syncpt_unit_base +
1441 PAGE_SIZE * i);
1442 __nvgpu_mem_create_from_pages(g, syncpt_buf, pages, nr_pages);
1443 nvgpu_kfree(g, pages);
1444 syncpt_buf->gpu_va = nvgpu_gmmu_map(c->vm, syncpt_buf,
1445 g->syncpt_unit_size, 0, gk20a_mem_flag_none,
1446 false, APERTURE_SYSMEM);
1447
1448 if (!syncpt_buf->gpu_va) {
1449 nvgpu_err(c->g, "failed to map syncpt buffer");
1450 nvgpu_dma_free(c->g, syncpt_buf);
1451 err = -ENOMEM;
1452 }
1453 return err;
1454}
1455
1456static void gv11b_fifo_free_syncpt_buf(struct channel_gk20a *c,
1457 struct nvgpu_mem *syncpt_buf)
1458{
1459 nvgpu_gmmu_unmap(c->vm, syncpt_buf, syncpt_buf->gpu_va);
1460 nvgpu_dma_free(c->g, syncpt_buf);
1461}
1462
1463static void gv11b_fifo_add_syncpt_wait_cmd(struct gk20a *g,
1464 struct priv_cmd_entry *cmd, u32 off,
1465 u32 id, u32 thresh, u64 gpu_va_base)
1466{
1467 u64 gpu_va = gpu_va_base +
1468 nvhost_syncpt_unit_interface_get_byte_offset(id);
1469
1470 gk20a_dbg_fn("");
1471
1472 off = cmd->off + off;
1473
1474 /* semaphore_a */
1475 nvgpu_mem_wr32(g, cmd->mem, off++, 0x20010004);
1476 nvgpu_mem_wr32(g, cmd->mem, off++,
1477 (gpu_va >> 32) & 0xff);
1478 /* semaphore_b */
1479 nvgpu_mem_wr32(g, cmd->mem, off++, 0x20010005);
1480 /* offset */
1481 nvgpu_mem_wr32(g, cmd->mem, off++, gpu_va & 0xffffffff);
1482
1483 /* semaphore_c */
1484 nvgpu_mem_wr32(g, cmd->mem, off++, 0x20010006);
1485 /* payload */
1486 nvgpu_mem_wr32(g, cmd->mem, off++, 0x0);
1487 /* semaphore_d */
1488 nvgpu_mem_wr32(g, cmd->mem, off++, 0x20010007);
1489 /* operation: acq_geq, switch_en */
1490 nvgpu_mem_wr32(g, cmd->mem, off++, 0x4 | (0x1 << 12));
1491}
1492
1493static u32 gv11b_fifo_get_syncpt_wait_cmd_size(void)
1494{
1495 return 8;
1496}
1497
1498static void gv11b_fifo_add_syncpt_incr_cmd(struct gk20a *g,
1499 bool wfi_cmd, struct priv_cmd_entry *cmd,
1500 u32 id, u64 gpu_va_base)
1501{
1502 u32 off = cmd->off;
1503 u64 gpu_va = gpu_va_base +
1504 nvhost_syncpt_unit_interface_get_byte_offset(id);
1505
1506 gk20a_dbg_fn("");
1507
1508 /* semaphore_a */
1509 nvgpu_mem_wr32(g, cmd->mem, off++, 0x20010004);
1510 nvgpu_mem_wr32(g, cmd->mem, off++,
1511 (gpu_va >> 32) & 0xff);
1512 /* semaphore_b */
1513 nvgpu_mem_wr32(g, cmd->mem, off++, 0x20010005);
1514 /* offset */
1515 nvgpu_mem_wr32(g, cmd->mem, off++, gpu_va & 0xffffffff);
1516
1517 /* semaphore_c */
1518 nvgpu_mem_wr32(g, cmd->mem, off++, 0x20010006);
1519 /* payload */
1520 nvgpu_mem_wr32(g, cmd->mem, off++, 0x0);
1521 /* semaphore_d */
1522 nvgpu_mem_wr32(g, cmd->mem, off++, 0x20010007);
1523
1524 /* operation: release, wfi */
1525 nvgpu_mem_wr32(g, cmd->mem, off++,
1526 0x2 | ((wfi_cmd ? 0x0 : 0x1) << 20));
1527 /* ignored */
1528 nvgpu_mem_wr32(g, cmd->mem, off++, 0);
1529}
1530
1531static u32 gv11b_fifo_get_syncpt_incr_cmd_size(bool wfi_cmd)
1532{
1533 return 9;
1534}
1535#endif /* CONFIG_TEGRA_GK20A_NVHOST */
1536
1414void gv11b_init_fifo(struct gpu_ops *gops) 1537void gv11b_init_fifo(struct gpu_ops *gops)
1415{ 1538{
1416 gp10b_init_fifo(gops); 1539 gp10b_init_fifo(gops);
@@ -1446,4 +1569,15 @@ void gv11b_init_fifo(struct gpu_ops *gops)
1446 gops->fifo.handle_ctxsw_timeout = gv11b_fifo_handle_ctxsw_timeout; 1569 gops->fifo.handle_ctxsw_timeout = gv11b_fifo_handle_ctxsw_timeout;
1447 gops->fifo.handle_pbdma_intr_0 = 1570 gops->fifo.handle_pbdma_intr_0 =
1448 gv11b_fifo_handle_pbdma_intr_0; 1571 gv11b_fifo_handle_pbdma_intr_0;
1572#ifdef CONFIG_TEGRA_GK20A_NVHOST
1573 gops->fifo.alloc_syncpt_buf = gv11b_fifo_alloc_syncpt_buf;
1574 gops->fifo.free_syncpt_buf = gv11b_fifo_free_syncpt_buf;
1575 gops->fifo.add_syncpt_wait_cmd = gv11b_fifo_add_syncpt_wait_cmd;
1576 gops->fifo.get_syncpt_wait_cmd_size =
1577 gv11b_fifo_get_syncpt_wait_cmd_size;
1578 gops->fifo.add_syncpt_incr_cmd = gv11b_fifo_add_syncpt_incr_cmd;
1579 gops->fifo.get_syncpt_incr_cmd_size =
1580 gv11b_fifo_get_syncpt_incr_cmd_size;
1581#endif
1582
1449} 1583}
diff --git a/drivers/gpu/nvgpu/gv11b/platform_gv11b_tegra.c b/drivers/gpu/nvgpu/gv11b/platform_gv11b_tegra.c
index 1cfa2ef2..8733cae9 100644
--- a/drivers/gpu/nvgpu/gv11b/platform_gv11b_tegra.c
+++ b/drivers/gpu/nvgpu/gv11b/platform_gv11b_tegra.c
@@ -19,6 +19,9 @@
19#include <linux/nvmap.h> 19#include <linux/nvmap.h>
20#include <linux/reset.h> 20#include <linux/reset.h>
21#include <linux/hashtable.h> 21#include <linux/hashtable.h>
22#ifdef CONFIG_TEGRA_GK20A_NVHOST
23#include <linux/nvhost_t194.h>
24#endif
22 25
23#include <uapi/linux/nvgpu.h> 26#include <uapi/linux/nvgpu.h>
24 27
@@ -37,7 +40,42 @@ static void gr_gv11b_remove_sysfs(struct device *dev);
37 40
38static int gv11b_tegra_probe(struct device *dev) 41static int gv11b_tegra_probe(struct device *dev)
39{ 42{
43 int err = 0;
40 struct gk20a_platform *platform = dev_get_drvdata(dev); 44 struct gk20a_platform *platform = dev_get_drvdata(dev);
45 struct gk20a *g = platform->g;
46 struct device_node *np = dev->of_node;
47 struct device_node *host1x_node;
48 struct platform_device *host1x_pdev;
49 const __be32 *host1x_ptr;
50
51#ifdef CONFIG_TEGRA_GK20A_NVHOST
52 host1x_ptr = of_get_property(np, "nvidia,host1x", NULL);
53 if (!host1x_ptr) {
54 dev_err(dev, "host1x device not available");
55 return -ENOSYS;
56 }
57
58 host1x_node = of_find_node_by_phandle(be32_to_cpup(host1x_ptr));
59 host1x_pdev = of_find_device_by_node(host1x_node);
60 if (!host1x_pdev) {
61 dev_err(dev, "host1x device not available");
62 return -ENOSYS;
63 }
64
65 platform->g->host1x_dev = host1x_pdev;
66 err = nvhost_syncpt_unit_interface_get_aperture(
67 g->host1x_dev,
68 &g->syncpt_unit_base,
69 &g->syncpt_unit_size);
70 if (err) {
71 dev_err(dev, "Failed to get syncpt interface");
72 return -ENOSYS;
73 }
74 g->syncpt_size = nvhost_syncpt_unit_interface_get_byte_offset(1);
75 gk20a_dbg_info("syncpt_unit_base %llx syncpt_unit_size %zx size %x\n",
76 g->syncpt_unit_base, g->syncpt_unit_size,
77 g->syncpt_size);
78#endif
41 79
42 platform->bypass_smmu = !device_is_iommuable(dev); 80 platform->bypass_smmu = !device_is_iommuable(dev);
43 platform->disable_bigpage = platform->bypass_smmu; 81 platform->disable_bigpage = platform->bypass_smmu;