From 7878824093972a6b8805dd8c00f1838e24a61ec0 Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Wed, 18 Jun 2014 14:39:25 +0300 Subject: 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 Reviewed-on: http://git-master/r/424768 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit --- drivers/gpu/nvgpu/gk20a/gk20a.c | 6 ++ drivers/gpu/nvgpu/gk20a/gk20a.h | 2 +- drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 157 ++++++++++++++++++++---------------- drivers/gpu/nvgpu/gm20b/acr_gm20b.c | 151 +--------------------------------- 4 files changed, 94 insertions(+), 222 deletions(-) (limited to 'drivers/gpu') 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) goto done; } + err = g->ops.pmu.prepare_ucode(g); + if (err) { + gk20a_err(dev, "failed to init pmu ucode"); + goto done; + } + err = gk20a_init_pmu_support(g); if (err) { 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 { u32 num_pages, u32 pgsz_idx); } mm; struct { - int (*pmu_setup_sw)(struct gk20a *g); + int (*prepare_ucode)(struct gk20a *g); int (*pmu_setup_hw_and_bootstrap)(struct gk20a *g); } pmu; }; 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) return 0; } +static int gk20a_prepare_ucode(struct gk20a *g) +{ + struct pmu_gk20a *pmu = &g->pmu; + int i, err = 0; + struct sg_table *sgt_pmu_ucode; + dma_addr_t iova; + struct device *d = dev_from_gk20a(g); + struct mm_gk20a *mm = &g->mm; + struct vm_gk20a *vm = &mm->pmu.vm; + void *ucode_ptr; + DEFINE_DMA_ATTRS(attrs); + + if (!g->pmu_fw) { + g->pmu_fw = gk20a_request_firmware(g, GK20A_PMU_UCODE_IMAGE); + if (!g->pmu_fw) { + gk20a_err(d, "failed to load pmu ucode!!"); + return err; + } + } + + gk20a_dbg_fn("firmware loaded"); + + pmu->desc = (struct pmu_ucode_desc *)g->pmu_fw->data; + pmu->ucode_image = (u32 *)((u8 *)pmu->desc + + pmu->desc->descriptor_size); + + dma_set_attr(DMA_ATTR_READ_ONLY, &attrs); + pmu->ucode.cpuva = dma_alloc_attrs(d, GK20A_PMU_UCODE_SIZE_MAX, + &iova, + GFP_KERNEL, + &attrs); + if (!pmu->ucode.cpuva) { + gk20a_err(d, "failed to allocate memory\n"); + err = -ENOMEM; + goto err_release_fw; + } + + pmu->ucode.iova = iova; + + err = gk20a_get_sgtable(d, &sgt_pmu_ucode, + pmu->ucode.cpuva, + pmu->ucode.iova, + GK20A_PMU_UCODE_SIZE_MAX); + if (err) { + gk20a_err(d, "failed to allocate sg table\n"); + goto err_free_pmu_ucode; + } + + pmu->ucode.pmu_va = gk20a_gmmu_map(vm, &sgt_pmu_ucode, + GK20A_PMU_UCODE_SIZE_MAX, + 0, /* flags */ + gk20a_mem_flag_read_only); + if (!pmu->ucode.pmu_va) { + gk20a_err(d, "failed to map pmu ucode memory!!"); + goto err_free_ucode_sgt; + } + + ucode_ptr = pmu->ucode.cpuva; + + for (i = 0; i < (pmu->desc->app_start_offset + + pmu->desc->app_size) >> 2; i++) + gk20a_mem_wr32(ucode_ptr, i, pmu->ucode_image[i]); + + gk20a_free_sgtable(&sgt_pmu_ucode); + + gk20a_init_pmu(pmu); + + return 0; + + err_free_ucode_sgt: + gk20a_free_sgtable(&sgt_pmu_ucode); + err_free_pmu_ucode: + dma_free_attrs(d, GK20A_PMU_UCODE_SIZE_MAX, + pmu->ucode.cpuva, pmu->ucode.iova, &attrs); + pmu->ucode.cpuva = NULL; + pmu->ucode.iova = 0; + err_release_fw: + release_firmware(g->pmu_fw); + + return err; +} + int gk20a_init_pmu_setup_sw(struct gk20a *g) { struct pmu_gk20a *pmu = &g->pmu; @@ -1527,10 +1609,7 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g) struct device *d = dev_from_gk20a(g); int i, err = 0; u8 *ptr; - void *ucode_ptr; - struct sg_table *sgt_pmu_ucode; struct sg_table *sgt_seq_buf; - DEFINE_DMA_ATTRS(attrs); dma_addr_t iova; gk20a_dbg_fn(""); @@ -1575,71 +1654,26 @@ int gk20a_init_pmu_setup_sw(struct gk20a *g) pmu_seq_init(pmu); - if (!g->pmu_fw) { - g->pmu_fw = gk20a_request_firmware(g, GK20A_PMU_UCODE_IMAGE); - if (!g->pmu_fw) { - gk20a_err(d, "failed to load pmu ucode!!"); - err = -ENOENT; - goto err_free_seq; - } - } - - gk20a_dbg_fn("firmware loaded"); - - pmu->desc = (struct pmu_ucode_desc *)g->pmu_fw->data; - pmu->ucode_image = (u32 *)((u8 *)pmu->desc + - pmu->desc->descriptor_size); - INIT_WORK(&pmu->pg_init, pmu_setup_hw); - dma_set_attr(DMA_ATTR_READ_ONLY, &attrs); - pmu->ucode.cpuva = dma_alloc_attrs(d, GK20A_PMU_UCODE_SIZE_MAX, - &iova, - GFP_KERNEL, - &attrs); - if (!pmu->ucode.cpuva) { - gk20a_err(d, "failed to allocate memory\n"); - err = -ENOMEM; - goto err_release_fw; - } - - pmu->ucode.iova = iova; pmu->seq_buf.cpuva = dma_alloc_coherent(d, GK20A_PMU_SEQ_BUF_SIZE, &iova, GFP_KERNEL); if (!pmu->seq_buf.cpuva) { gk20a_err(d, "failed to allocate memory\n"); err = -ENOMEM; - goto err_free_pmu_ucode; + goto err_free_seq; } pmu->seq_buf.iova = iova; - err = gk20a_get_sgtable(d, &sgt_pmu_ucode, - pmu->ucode.cpuva, - pmu->ucode.iova, - GK20A_PMU_UCODE_SIZE_MAX); - if (err) { - gk20a_err(d, "failed to allocate sg table\n"); - goto err_free_seq_buf; - } - - pmu->ucode.pmu_va = gk20a_gmmu_map(vm, &sgt_pmu_ucode, - GK20A_PMU_UCODE_SIZE_MAX, - 0, /* flags */ - gk20a_mem_flag_read_only); - if (!pmu->ucode.pmu_va) { - gk20a_err(d, "failed to map pmu ucode memory!!"); - goto err_free_ucode_sgt; - } - err = gk20a_get_sgtable(d, &sgt_seq_buf, pmu->seq_buf.cpuva, pmu->seq_buf.iova, GK20A_PMU_SEQ_BUF_SIZE); if (err) { gk20a_err(d, "failed to allocate sg table\n"); - goto err_unmap_ucode; + goto err_free_seq_buf; } 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) pmu->seq_buf.size = GK20A_PMU_SEQ_BUF_SIZE; - ucode_ptr = pmu->ucode.cpuva; - - for (i = 0; i < (pmu->desc->app_start_offset + - pmu->desc->app_size) >> 2; i++) - gk20a_mem_wr32(ucode_ptr, i, pmu->ucode_image[i]); - - gk20a_free_sgtable(&sgt_pmu_ucode); gk20a_free_sgtable(&sgt_seq_buf); pmu->sw_ready = true; @@ -1700,23 +1727,11 @@ skip_init: GK20A_PMU_SEQ_BUF_SIZE, gk20a_mem_flag_none); err_free_seq_buf_sgt: gk20a_free_sgtable(&sgt_seq_buf); - err_unmap_ucode: - gk20a_gmmu_unmap(vm, pmu->ucode.pmu_va, - GK20A_PMU_UCODE_SIZE_MAX, gk20a_mem_flag_none); - err_free_ucode_sgt: - gk20a_free_sgtable(&sgt_pmu_ucode); err_free_seq_buf: dma_free_coherent(d, GK20A_PMU_SEQ_BUF_SIZE, pmu->seq_buf.cpuva, pmu->seq_buf.iova); pmu->seq_buf.cpuva = NULL; pmu->seq_buf.iova = 0; - err_free_pmu_ucode: - dma_free_attrs(d, GK20A_PMU_UCODE_SIZE_MAX, - pmu->ucode.cpuva, pmu->ucode.iova, &attrs); - pmu->ucode.cpuva = NULL; - pmu->ucode.iova = 0; - err_release_fw: - release_firmware(g->pmu_fw); err_free_seq: kfree(pmu->seq); err_free_mutex: @@ -1977,7 +1992,7 @@ static void pmu_setup_hw_enable_elpg(struct gk20a *g) void gk20a_init_pmu_ops(struct gpu_ops *gops) { - gops->pmu.pmu_setup_sw = gk20a_init_pmu_setup_sw; + gops->pmu.prepare_ucode = gk20a_prepare_ucode; gops->pmu.pmu_setup_hw_and_bootstrap = gk20a_init_pmu_setup_hw1; } @@ -1996,7 +2011,7 @@ int gk20a_init_pmu_support(struct gk20a *g) return err; if (support_gk20a_pmu()) { - err = g->ops.pmu.pmu_setup_sw(g); + err = gk20a_init_pmu_setup_sw(g); if (err) return err; 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) void gm20b_init_secure_pmu(struct gpu_ops *gops) { - gops->pmu.pmu_setup_sw = gm20b_pmu_setup_sw; + gops->pmu.prepare_ucode = prepare_ucode_blob; gops->pmu.pmu_setup_hw_and_bootstrap = gm20b_bootstrap_hs_flcn; } @@ -77,155 +77,6 @@ static void free_blob_res(struct gk20a *g) /*TODO */ } -int gm20b_pmu_setup_sw(struct gk20a *g) -{ - /*from pmu_gk20a.c*/ - struct pmu_gk20a *pmu = &g->pmu; - struct mm_gk20a *mm = &g->mm; - struct vm_gk20a *vm = &mm->pmu.vm; - struct device *d = dev_from_gk20a(g); - int i, err = 0; - u8 *ptr; - struct sg_table *sgt_seq_buf; - dma_addr_t iova; - - gk20a_dbg_fn(""); - /* Make any ACR structure settings here if ever need be*/ - - if (pmu->sw_ready) { - for (i = 0; i < pmu->mutex_cnt; i++) { - pmu->mutex[i].id = i; - pmu->mutex[i].index = i; - } - pmu_seq_init(pmu); - - mutex_init(&pmu->elpg_mutex); - mutex_init(&pmu->isr_mutex); - mutex_init(&pmu->pmu_copy_lock); - mutex_init(&pmu->pmu_seq_lock); - gk20a_dbg_fn("skip init"); - goto skip_init; - } - gm20b_dbg_pmu("gk20a_init_pmu_setup_sw 2\n"); - - /* TBD: sysmon subtask */ - - if (IS_ENABLED(CONFIG_TEGRA_GK20A_PERFMON)) - pmu->perfmon_sampling_enabled = true; - - pmu->mutex_cnt = pwr_pmu_mutex__size_1_v(); - pmu->mutex = kzalloc(pmu->mutex_cnt * - sizeof(struct pmu_mutex), GFP_KERNEL); - if (!pmu->mutex) { - err = -ENOMEM; - goto err; - } - - for (i = 0; i < pmu->mutex_cnt; i++) { - pmu->mutex[i].id = i; - pmu->mutex[i].index = i; - } - gm20b_dbg_pmu("gk20a_init_pmu_setup_sw 3\n"); - - pmu->seq = kzalloc(PMU_MAX_NUM_SEQUENCES * - sizeof(struct pmu_sequence), GFP_KERNEL); - if (!pmu->seq) { - err = -ENOMEM; - goto err_free_mutex; - } - - pmu_seq_init(pmu); - mutex_init(&pmu->elpg_mutex); - mutex_init(&pmu->isr_mutex); - mutex_init(&pmu->pmu_copy_lock); - mutex_init(&pmu->pmu_seq_lock); - - err = prepare_ucode_blob(g); - if (err) - goto err_free_seq; - INIT_WORK(&pmu->pg_init, pmu_setup_hw); - pmu->seq_buf.cpuva = dma_alloc_coherent(d, GK20A_PMU_SEQ_BUF_SIZE, - &iova, - GFP_KERNEL); - if (!pmu->seq_buf.cpuva) { - gk20a_err(d, "failed to allocate memory\n"); - err = -ENOMEM; - goto err_free_blob_res; - } - - pmu->seq_buf.iova = iova; - err = gk20a_get_sgtable(d, &sgt_seq_buf, - pmu->seq_buf.cpuva, - pmu->seq_buf.iova, - GK20A_PMU_SEQ_BUF_SIZE); - if (err) { - gk20a_err(d, "failed to allocate sg table\n"); - goto err_free_seq_buf; - } - - pmu->seq_buf.pmu_va = gk20a_gmmu_map(vm, &sgt_seq_buf, - GK20A_PMU_SEQ_BUF_SIZE, - 0, /* flags */ - gk20a_mem_flag_none); - if (!pmu->seq_buf.pmu_va) { - gk20a_err(d, "failed to map pmu ucode memory!!"); - goto err_free_seq_buf_sgt; - } - - ptr = (u8 *)pmu->seq_buf.cpuva; - if (!ptr) { - gk20a_err(d, "failed to map cpu ptr for zbc buffer"); - goto err_unmap_seq_buf; - } - - /* TBD: remove this if ZBC save/restore is handled by PMU - * end an empty ZBC sequence for now */ - ptr[0] = 0x16; /* opcode EXIT */ - ptr[1] = 0; ptr[2] = 1; ptr[3] = 0; - ptr[4] = 0; ptr[5] = 0; ptr[6] = 0; ptr[7] = 0; - - pmu->seq_buf.size = GK20A_PMU_SEQ_BUF_SIZE; - - gk20a_dbg_fn("done"); - gk20a_free_sgtable(&sgt_seq_buf); - - pmu->sw_ready = true; - -skip_init: - pmu->perfmon_counter.index = 3; /* GR & CE2 */ - pmu->perfmon_counter.group_id = PMU_DOMAIN_GROUP_PSTATE; - - pmu->remove_support = gk20a_remove_pmu_support; - err = gk20a_init_pmu(pmu); - if (err) { - gk20a_err(d, "failed to set function pointers\n"); - goto err_unmap_seq_buf; - } - - gk20a_dbg_fn("done"); - return 0; - - err_unmap_seq_buf: - gk20a_gmmu_unmap(vm, pmu->seq_buf.pmu_va, - GK20A_PMU_SEQ_BUF_SIZE, gk20a_mem_flag_none); - err_free_seq_buf_sgt: - gk20a_free_sgtable(&sgt_seq_buf); - err_free_seq_buf: - dma_free_coherent(d, GK20A_PMU_SEQ_BUF_SIZE, - pmu->seq_buf.cpuva, pmu->seq_buf.iova); - pmu->seq_buf.cpuva = NULL; - pmu->seq_buf.iova = 0; - err_free_blob_res: - free_blob_res(g); - err_free_seq: - kfree(pmu->seq); - err_free_mutex: - kfree(pmu->mutex); - err: - gk20a_dbg_fn("fail"); - return err; -} - int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) { const struct firmware *pmu_fw; -- cgit v1.2.2