diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2014-06-18 07:39:25 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:10:17 -0400 |
commit | 7878824093972a6b8805dd8c00f1838e24a61ec0 (patch) | |
tree | efbef295366773abb59c53aa26c3768a6619c3ad | |
parent | 7ed71374e90f8e5c8554cb7d2f14aa8e9a807862 (diff) |
gpu: nvgpu: Separate PMU firmware load from init
Separate the code to load PMU firmware from the software init. This
allows folding ACR and non-ACR PMU software initialization sequences.
Bug 200006956
Change-Id: I74b289747852167e8ebf1be63036c790ae634da4
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/424768
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 6 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 157 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/acr_gm20b.c | 151 |
4 files changed, 94 insertions, 222 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index 790b366c..5305f612 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -897,6 +897,12 @@ static int gk20a_pm_finalize_poweron(struct device *dev) | |||
897 | goto done; | 897 | goto done; |
898 | } | 898 | } |
899 | 899 | ||
900 | err = g->ops.pmu.prepare_ucode(g); | ||
901 | if (err) { | ||
902 | gk20a_err(dev, "failed to init pmu ucode"); | ||
903 | goto done; | ||
904 | } | ||
905 | |||
900 | err = gk20a_init_pmu_support(g); | 906 | err = gk20a_init_pmu_support(g); |
901 | if (err) { | 907 | if (err) { |
902 | gk20a_err(dev, "failed to init gk20a pmu"); | 908 | gk20a_err(dev, "failed to init gk20a pmu"); |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 127cb85c..07826675 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -220,7 +220,7 @@ struct gpu_ops { | |||
220 | u32 num_pages, u32 pgsz_idx); | 220 | u32 num_pages, u32 pgsz_idx); |
221 | } mm; | 221 | } mm; |
222 | struct { | 222 | struct { |
223 | int (*pmu_setup_sw)(struct gk20a *g); | 223 | int (*prepare_ucode)(struct gk20a *g); |
224 | int (*pmu_setup_hw_and_bootstrap)(struct gk20a *g); | 224 | int (*pmu_setup_hw_and_bootstrap)(struct gk20a *g); |
225 | } pmu; | 225 | } pmu; |
226 | }; | 226 | }; |
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index e8acf503..ac66dbef 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | |||
@@ -1519,6 +1519,88 @@ int gk20a_init_pmu_reset_enable_hw(struct gk20a *g) | |||
1519 | return 0; | 1519 | return 0; |
1520 | } | 1520 | } |
1521 | 1521 | ||
1522 | static int gk20a_prepare_ucode(struct gk20a *g) | ||
1523 | { | ||
1524 | struct pmu_gk20a *pmu = &g->pmu; | ||
1525 | int i, err = 0; | ||
1526 | struct sg_table *sgt_pmu_ucode; | ||
1527 | dma_addr_t iova; | ||
1528 | struct device *d = dev_from_gk20a(g); | ||
1529 | struct mm_gk20a *mm = &g->mm; | ||
1530 | struct vm_gk20a *vm = &mm->pmu.vm; | ||
1531 | void *ucode_ptr; | ||
1532 | DEFINE_DMA_ATTRS(attrs); | ||
1533 | |||
1534 | if (!g->pmu_fw) { | ||
1535 | g->pmu_fw = gk20a_request_firmware(g, GK20A_PMU_UCODE_IMAGE); | ||
1536 | if (!g->pmu_fw) { | ||
1537 | gk20a_err(d, "failed to load pmu ucode!!"); | ||
1538 | return err; | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1542 | gk20a_dbg_fn("firmware loaded"); | ||
1543 | |||
1544 | pmu->desc = (struct pmu_ucode_desc *)g->pmu_fw->data; | ||
1545 | pmu->ucode_image = (u32 *)((u8 *)pmu->desc + | ||
1546 | pmu->desc->descriptor_size); | ||
1547 | |||
1548 | dma_set_attr(DMA_ATTR_READ_ONLY, &attrs); | ||
1549 | pmu->ucode.cpuva = dma_alloc_attrs(d, GK20A_PMU_UCODE_SIZE_MAX, | ||
1550 | &iova, | ||
1551 | GFP_KERNEL, | ||
1552 | &attrs); | ||
1553 | if (!pmu->ucode.cpuva) { | ||
1554 | gk20a_err(d, "failed to allocate memory\n"); | ||
1555 | err = -ENOMEM; | ||
1556 | goto err_release_fw; | ||
1557 | } | ||
1558 | |||
1559 | pmu->ucode.iova = iova; | ||
1560 | |||
1561 | err = gk20a_get_sgtable(d, &sgt_pmu_ucode, | ||
1562 | pmu->ucode.cpuva, | ||
1563 | pmu->ucode.iova, | ||
1564 | GK20A_PMU_UCODE_SIZE_MAX); | ||
1565 | if (err) { | ||
1566 | gk20a_err(d, "failed to allocate sg table\n"); | ||
1567 | goto err_free_pmu_ucode; | ||
1568 | } | ||
1569 | |||
1570 | pmu->ucode.pmu_va = gk20a_gmmu_map(vm, &sgt_pmu_ucode, | ||
1571 | GK20A_PMU_UCODE_SIZE_MAX, | ||
1572 | 0, /* flags */ | ||
1573 | gk20a_mem_flag_read_only); | ||
1574 | if (!pmu->ucode.pmu_va) { | ||
1575 | gk20a_err(d, "failed to map pmu ucode memory!!"); | ||
1576 | goto err_free_ucode_sgt; | ||
1577 | } | ||
1578 | |||
1579 | ucode_ptr = pmu->ucode.cpuva; | ||
1580 | |||
1581 | for (i = 0; i < (pmu->desc->app_start_offset + | ||
1582 | pmu->desc->app_size) >> 2; i++) | ||
1583 | gk20a_mem_wr32(ucode_ptr, i, pmu->ucode_image[i]); | ||
1584 | |||
1585 | gk20a_free_sgtable(&sgt_pmu_ucode); | ||
1586 | |||
1587 | gk20a_init_pmu(pmu); | ||
1588 | |||
1589 | return 0; | ||
1590 | |||
1591 | err_free_ucode_sgt: | ||
1592 | gk20a_free_sgtable(&sgt_pmu_ucode); | ||
1593 | err_free_pmu_ucode: | ||
1594 | dma_free_attrs(d, GK20A_PMU_UCODE_SIZE_MAX, | ||
1595 | pmu->ucode.cpuva, pmu->ucode.iova, &attrs); | ||
1596 | pmu->ucode.cpuva = NULL; | ||
1597 | pmu->ucode.iova = 0; | ||
1598 | err_release_fw: | ||
1599 | release_firmware(g->pmu_fw); | ||
1600 | |||
1601 | return err; | ||
1602 | } | ||
1603 | |||
1522 | int gk20a_init_pmu_setup_sw(struct gk20a *g) | 1604 | int gk20a_init_pmu_setup_sw(struct gk20a *g) |
1523 | { | 1605 | { |
1524 | struct pmu_gk20a *pmu = &g->pmu; | 1606 | struct pmu_gk20a *pmu = &g->pmu; |
@@ -1527,10 +1609,7 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g) | |||
1527 | struct device *d = dev_from_gk20a(g); | 1609 | struct device *d = dev_from_gk20a(g); |
1528 | int i, err = 0; | 1610 | int i, err = 0; |
1529 | u8 *ptr; | 1611 | u8 *ptr; |
1530 | void *ucode_ptr; | ||
1531 | struct sg_table *sgt_pmu_ucode; | ||
1532 | struct sg_table *sgt_seq_buf; | 1612 | struct sg_table *sgt_seq_buf; |
1533 | DEFINE_DMA_ATTRS(attrs); | ||
1534 | dma_addr_t iova; | 1613 | dma_addr_t iova; |
1535 | 1614 | ||
1536 | gk20a_dbg_fn(""); | 1615 | gk20a_dbg_fn(""); |
@@ -1575,71 +1654,26 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g) | |||
1575 | 1654 | ||
1576 | pmu_seq_init(pmu); | 1655 | pmu_seq_init(pmu); |
1577 | 1656 | ||
1578 | if (!g->pmu_fw) { | ||
1579 | g->pmu_fw = gk20a_request_firmware(g, GK20A_PMU_UCODE_IMAGE); | ||
1580 | if (!g->pmu_fw) { | ||
1581 | gk20a_err(d, "failed to load pmu ucode!!"); | ||
1582 | err = -ENOENT; | ||
1583 | goto err_free_seq; | ||
1584 | } | ||
1585 | } | ||
1586 | |||
1587 | gk20a_dbg_fn("firmware loaded"); | ||
1588 | |||
1589 | pmu->desc = (struct pmu_ucode_desc *)g->pmu_fw->data; | ||
1590 | pmu->ucode_image = (u32 *)((u8 *)pmu->desc + | ||
1591 | pmu->desc->descriptor_size); | ||
1592 | |||
1593 | INIT_WORK(&pmu->pg_init, pmu_setup_hw); | 1657 | INIT_WORK(&pmu->pg_init, pmu_setup_hw); |
1594 | 1658 | ||
1595 | dma_set_attr(DMA_ATTR_READ_ONLY, &attrs); | ||
1596 | pmu->ucode.cpuva = dma_alloc_attrs(d, GK20A_PMU_UCODE_SIZE_MAX, | ||
1597 | &iova, | ||
1598 | GFP_KERNEL, | ||
1599 | &attrs); | ||
1600 | if (!pmu->ucode.cpuva) { | ||
1601 | gk20a_err(d, "failed to allocate memory\n"); | ||
1602 | err = -ENOMEM; | ||
1603 | goto err_release_fw; | ||
1604 | } | ||
1605 | |||
1606 | pmu->ucode.iova = iova; | ||
1607 | pmu->seq_buf.cpuva = dma_alloc_coherent(d, GK20A_PMU_SEQ_BUF_SIZE, | 1659 | pmu->seq_buf.cpuva = dma_alloc_coherent(d, GK20A_PMU_SEQ_BUF_SIZE, |
1608 | &iova, | 1660 | &iova, |
1609 | GFP_KERNEL); | 1661 | GFP_KERNEL); |
1610 | if (!pmu->seq_buf.cpuva) { | 1662 | if (!pmu->seq_buf.cpuva) { |
1611 | gk20a_err(d, "failed to allocate memory\n"); | 1663 | gk20a_err(d, "failed to allocate memory\n"); |
1612 | err = -ENOMEM; | 1664 | err = -ENOMEM; |
1613 | goto err_free_pmu_ucode; | 1665 | goto err_free_seq; |
1614 | } | 1666 | } |
1615 | 1667 | ||
1616 | pmu->seq_buf.iova = iova; | 1668 | pmu->seq_buf.iova = iova; |
1617 | 1669 | ||
1618 | err = gk20a_get_sgtable(d, &sgt_pmu_ucode, | ||
1619 | pmu->ucode.cpuva, | ||
1620 | pmu->ucode.iova, | ||
1621 | GK20A_PMU_UCODE_SIZE_MAX); | ||
1622 | if (err) { | ||
1623 | gk20a_err(d, "failed to allocate sg table\n"); | ||
1624 | goto err_free_seq_buf; | ||
1625 | } | ||
1626 | |||
1627 | pmu->ucode.pmu_va = gk20a_gmmu_map(vm, &sgt_pmu_ucode, | ||
1628 | GK20A_PMU_UCODE_SIZE_MAX, | ||
1629 | 0, /* flags */ | ||
1630 | gk20a_mem_flag_read_only); | ||
1631 | if (!pmu->ucode.pmu_va) { | ||
1632 | gk20a_err(d, "failed to map pmu ucode memory!!"); | ||
1633 | goto err_free_ucode_sgt; | ||
1634 | } | ||
1635 | |||
1636 | err = gk20a_get_sgtable(d, &sgt_seq_buf, | 1670 | err = gk20a_get_sgtable(d, &sgt_seq_buf, |
1637 | pmu->seq_buf.cpuva, | 1671 | pmu->seq_buf.cpuva, |
1638 | pmu->seq_buf.iova, | 1672 | pmu->seq_buf.iova, |
1639 | GK20A_PMU_SEQ_BUF_SIZE); | 1673 | GK20A_PMU_SEQ_BUF_SIZE); |
1640 | if (err) { | 1674 | if (err) { |
1641 | gk20a_err(d, "failed to allocate sg table\n"); | 1675 | gk20a_err(d, "failed to allocate sg table\n"); |
1642 | goto err_unmap_ucode; | 1676 | goto err_free_seq_buf; |
1643 | } | 1677 | } |
1644 | 1678 | ||
1645 | pmu->seq_buf.pmu_va = gk20a_gmmu_map(vm, &sgt_seq_buf, | 1679 | pmu->seq_buf.pmu_va = gk20a_gmmu_map(vm, &sgt_seq_buf, |
@@ -1665,13 +1699,6 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g) | |||
1665 | 1699 | ||
1666 | pmu->seq_buf.size = GK20A_PMU_SEQ_BUF_SIZE; | 1700 | pmu->seq_buf.size = GK20A_PMU_SEQ_BUF_SIZE; |
1667 | 1701 | ||
1668 | ucode_ptr = pmu->ucode.cpuva; | ||
1669 | |||
1670 | for (i = 0; i < (pmu->desc->app_start_offset + | ||
1671 | pmu->desc->app_size) >> 2; i++) | ||
1672 | gk20a_mem_wr32(ucode_ptr, i, pmu->ucode_image[i]); | ||
1673 | |||
1674 | gk20a_free_sgtable(&sgt_pmu_ucode); | ||
1675 | gk20a_free_sgtable(&sgt_seq_buf); | 1702 | gk20a_free_sgtable(&sgt_seq_buf); |
1676 | 1703 | ||
1677 | pmu->sw_ready = true; | 1704 | pmu->sw_ready = true; |
@@ -1700,23 +1727,11 @@ skip_init: | |||
1700 | GK20A_PMU_SEQ_BUF_SIZE, gk20a_mem_flag_none); | 1727 | GK20A_PMU_SEQ_BUF_SIZE, gk20a_mem_flag_none); |
1701 | err_free_seq_buf_sgt: | 1728 | err_free_seq_buf_sgt: |
1702 | gk20a_free_sgtable(&sgt_seq_buf); | 1729 | gk20a_free_sgtable(&sgt_seq_buf); |
1703 | err_unmap_ucode: | ||
1704 | gk20a_gmmu_unmap(vm, pmu->ucode.pmu_va, | ||
1705 | GK20A_PMU_UCODE_SIZE_MAX, gk20a_mem_flag_none); | ||
1706 | err_free_ucode_sgt: | ||
1707 | gk20a_free_sgtable(&sgt_pmu_ucode); | ||
1708 | err_free_seq_buf: | 1730 | err_free_seq_buf: |
1709 | dma_free_coherent(d, GK20A_PMU_SEQ_BUF_SIZE, | 1731 | dma_free_coherent(d, GK20A_PMU_SEQ_BUF_SIZE, |
1710 | pmu->seq_buf.cpuva, pmu->seq_buf.iova); | 1732 | pmu->seq_buf.cpuva, pmu->seq_buf.iova); |
1711 | pmu->seq_buf.cpuva = NULL; | 1733 | pmu->seq_buf.cpuva = NULL; |
1712 | pmu->seq_buf.iova = 0; | 1734 | pmu->seq_buf.iova = 0; |
1713 | err_free_pmu_ucode: | ||
1714 | dma_free_attrs(d, GK20A_PMU_UCODE_SIZE_MAX, | ||
1715 | pmu->ucode.cpuva, pmu->ucode.iova, &attrs); | ||
1716 | pmu->ucode.cpuva = NULL; | ||
1717 | pmu->ucode.iova = 0; | ||
1718 | err_release_fw: | ||
1719 | release_firmware(g->pmu_fw); | ||
1720 | err_free_seq: | 1735 | err_free_seq: |
1721 | kfree(pmu->seq); | 1736 | kfree(pmu->seq); |
1722 | err_free_mutex: | 1737 | err_free_mutex: |
@@ -1977,7 +1992,7 @@ static void pmu_setup_hw_enable_elpg(struct gk20a *g) | |||
1977 | 1992 | ||
1978 | void gk20a_init_pmu_ops(struct gpu_ops *gops) | 1993 | void gk20a_init_pmu_ops(struct gpu_ops *gops) |
1979 | { | 1994 | { |
1980 | gops->pmu.pmu_setup_sw = gk20a_init_pmu_setup_sw; | 1995 | gops->pmu.prepare_ucode = gk20a_prepare_ucode; |
1981 | gops->pmu.pmu_setup_hw_and_bootstrap = gk20a_init_pmu_setup_hw1; | 1996 | gops->pmu.pmu_setup_hw_and_bootstrap = gk20a_init_pmu_setup_hw1; |
1982 | } | 1997 | } |
1983 | 1998 | ||
@@ -1996,7 +2011,7 @@ int gk20a_init_pmu_support(struct gk20a *g) | |||
1996 | return err; | 2011 | return err; |
1997 | 2012 | ||
1998 | if (support_gk20a_pmu()) { | 2013 | if (support_gk20a_pmu()) { |
1999 | err = g->ops.pmu.pmu_setup_sw(g); | 2014 | err = gk20a_init_pmu_setup_sw(g); |
2000 | if (err) | 2015 | if (err) |
2001 | return err; | 2016 | return err; |
2002 | err = g->ops.pmu.pmu_setup_hw_and_bootstrap(g); | 2017 | err = g->ops.pmu.pmu_setup_hw_and_bootstrap(g); |
diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c index 1a136cdb..2b7be4f7 100644 --- a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c | |||
@@ -68,7 +68,7 @@ void start_gm20b_pmu(struct gk20a *g) | |||
68 | 68 | ||
69 | void gm20b_init_secure_pmu(struct gpu_ops *gops) | 69 | void gm20b_init_secure_pmu(struct gpu_ops *gops) |
70 | { | 70 | { |
71 | gops->pmu.pmu_setup_sw = gm20b_pmu_setup_sw; | 71 | gops->pmu.prepare_ucode = prepare_ucode_blob; |
72 | gops->pmu.pmu_setup_hw_and_bootstrap = gm20b_bootstrap_hs_flcn; | 72 | gops->pmu.pmu_setup_hw_and_bootstrap = gm20b_bootstrap_hs_flcn; |
73 | } | 73 | } |
74 | 74 | ||
@@ -77,155 +77,6 @@ static void free_blob_res(struct gk20a *g) | |||
77 | /*TODO */ | 77 | /*TODO */ |
78 | } | 78 | } |
79 | 79 | ||
80 | int gm20b_pmu_setup_sw(struct gk20a *g) | ||
81 | { | ||
82 | /*from pmu_gk20a.c*/ | ||
83 | struct pmu_gk20a *pmu = &g->pmu; | ||
84 | struct mm_gk20a *mm = &g->mm; | ||
85 | struct vm_gk20a *vm = &mm->pmu.vm; | ||
86 | struct device *d = dev_from_gk20a(g); | ||
87 | int i, err = 0; | ||
88 | u8 *ptr; | ||
89 | struct sg_table *sgt_seq_buf; | ||
90 | dma_addr_t iova; | ||
91 | |||
92 | gk20a_dbg_fn(""); | ||
93 | /* Make any ACR structure settings here if ever need be*/ | ||
94 | |||
95 | if (pmu->sw_ready) { | ||
96 | for (i = 0; i < pmu->mutex_cnt; i++) { | ||
97 | pmu->mutex[i].id = i; | ||
98 | pmu->mutex[i].index = i; | ||
99 | } | ||
100 | pmu_seq_init(pmu); | ||
101 | |||
102 | mutex_init(&pmu->elpg_mutex); | ||
103 | mutex_init(&pmu->isr_mutex); | ||
104 | mutex_init(&pmu->pmu_copy_lock); | ||
105 | mutex_init(&pmu->pmu_seq_lock); | ||
106 | gk20a_dbg_fn("skip init"); | ||
107 | goto skip_init; | ||
108 | } | ||
109 | gm20b_dbg_pmu("gk20a_init_pmu_setup_sw 2\n"); | ||
110 | |||
111 | /* TBD: sysmon subtask */ | ||
112 | |||
113 | if (IS_ENABLED(CONFIG_TEGRA_GK20A_PERFMON)) | ||
114 | pmu->perfmon_sampling_enabled = true; | ||
115 | |||
116 | pmu->mutex_cnt = pwr_pmu_mutex__size_1_v(); | ||
117 | pmu->mutex = kzalloc(pmu->mutex_cnt * | ||
118 | sizeof(struct pmu_mutex), GFP_KERNEL); | ||
119 | if (!pmu->mutex) { | ||
120 | err = -ENOMEM; | ||
121 | goto err; | ||
122 | } | ||
123 | |||
124 | for (i = 0; i < pmu->mutex_cnt; i++) { | ||
125 | pmu->mutex[i].id = i; | ||
126 | pmu->mutex[i].index = i; | ||
127 | } | ||
128 | gm20b_dbg_pmu("gk20a_init_pmu_setup_sw 3\n"); | ||
129 | |||
130 | pmu->seq = kzalloc(PMU_MAX_NUM_SEQUENCES * | ||
131 | sizeof(struct pmu_sequence), GFP_KERNEL); | ||
132 | if (!pmu->seq) { | ||
133 | err = -ENOMEM; | ||
134 | goto err_free_mutex; | ||
135 | } | ||
136 | |||
137 | pmu_seq_init(pmu); | ||
138 | mutex_init(&pmu->elpg_mutex); | ||
139 | mutex_init(&pmu->isr_mutex); | ||
140 | mutex_init(&pmu->pmu_copy_lock); | ||
141 | mutex_init(&pmu->pmu_seq_lock); | ||
142 | |||
143 | err = prepare_ucode_blob(g); | ||
144 | if (err) | ||
145 | goto err_free_seq; | ||
146 | INIT_WORK(&pmu->pg_init, pmu_setup_hw); | ||
147 | pmu->seq_buf.cpuva = dma_alloc_coherent(d, GK20A_PMU_SEQ_BUF_SIZE, | ||
148 | &iova, | ||
149 | GFP_KERNEL); | ||
150 | if (!pmu->seq_buf.cpuva) { | ||
151 | gk20a_err(d, "failed to allocate memory\n"); | ||
152 | err = -ENOMEM; | ||
153 | goto err_free_blob_res; | ||
154 | } | ||
155 | |||
156 | pmu->seq_buf.iova = iova; | ||
157 | err = gk20a_get_sgtable(d, &sgt_seq_buf, | ||
158 | pmu->seq_buf.cpuva, | ||
159 | pmu->seq_buf.iova, | ||
160 | GK20A_PMU_SEQ_BUF_SIZE); | ||
161 | if (err) { | ||
162 | gk20a_err(d, "failed to allocate sg table\n"); | ||
163 | goto err_free_seq_buf; | ||
164 | } | ||
165 | |||
166 | pmu->seq_buf.pmu_va = gk20a_gmmu_map(vm, &sgt_seq_buf, | ||
167 | GK20A_PMU_SEQ_BUF_SIZE, | ||
168 | 0, /* flags */ | ||
169 | gk20a_mem_flag_none); | ||
170 | if (!pmu->seq_buf.pmu_va) { | ||
171 | gk20a_err(d, "failed to map pmu ucode memory!!"); | ||
172 | goto err_free_seq_buf_sgt; | ||
173 | } | ||
174 | |||
175 | ptr = (u8 *)pmu->seq_buf.cpuva; | ||
176 | if (!ptr) { | ||
177 | gk20a_err(d, "failed to map cpu ptr for zbc buffer"); | ||
178 | goto err_unmap_seq_buf; | ||
179 | } | ||
180 | |||
181 | /* TBD: remove this if ZBC save/restore is handled by PMU | ||
182 | * end an empty ZBC sequence for now */ | ||
183 | ptr[0] = 0x16; /* opcode EXIT */ | ||
184 | ptr[1] = 0; ptr[2] = 1; ptr[3] = 0; | ||
185 | ptr[4] = 0; ptr[5] = 0; ptr[6] = 0; ptr[7] = 0; | ||
186 | |||
187 | pmu->seq_buf.size = GK20A_PMU_SEQ_BUF_SIZE; | ||
188 | |||
189 | gk20a_dbg_fn("done"); | ||
190 | gk20a_free_sgtable(&sgt_seq_buf); | ||
191 | |||
192 | pmu->sw_ready = true; | ||
193 | |||
194 | skip_init: | ||
195 | pmu->perfmon_counter.index = 3; /* GR & CE2 */ | ||
196 | pmu->perfmon_counter.group_id = PMU_DOMAIN_GROUP_PSTATE; | ||
197 | |||
198 | pmu->remove_support = gk20a_remove_pmu_support; | ||
199 | err = gk20a_init_pmu(pmu); | ||
200 | if (err) { | ||
201 | gk20a_err(d, "failed to set function pointers\n"); | ||
202 | goto err_unmap_seq_buf; | ||
203 | } | ||
204 | |||
205 | gk20a_dbg_fn("done"); | ||
206 | return 0; | ||
207 | |||
208 | err_unmap_seq_buf: | ||
209 | gk20a_gmmu_unmap(vm, pmu->seq_buf.pmu_va, | ||
210 | GK20A_PMU_SEQ_BUF_SIZE, gk20a_mem_flag_none); | ||
211 | err_free_seq_buf_sgt: | ||
212 | gk20a_free_sgtable(&sgt_seq_buf); | ||
213 | err_free_seq_buf: | ||
214 | dma_free_coherent(d, GK20A_PMU_SEQ_BUF_SIZE, | ||
215 | pmu->seq_buf.cpuva, pmu->seq_buf.iova); | ||
216 | pmu->seq_buf.cpuva = NULL; | ||
217 | pmu->seq_buf.iova = 0; | ||
218 | err_free_blob_res: | ||
219 | free_blob_res(g); | ||
220 | err_free_seq: | ||
221 | kfree(pmu->seq); | ||
222 | err_free_mutex: | ||
223 | kfree(pmu->mutex); | ||
224 | err: | ||
225 | gk20a_dbg_fn("fail"); | ||
226 | return err; | ||
227 | } | ||
228 | |||
229 | int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) | 80 | int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) |
230 | { | 81 | { |
231 | const struct firmware *pmu_fw; | 82 | const struct firmware *pmu_fw; |