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 /drivers/gpu/nvgpu/gk20a | |
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
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-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 |
3 files changed, 93 insertions, 72 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); |