diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/acr_gm20b.c | 370 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/acr_gm20b.h | 7 |
2 files changed, 222 insertions, 155 deletions
diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c index e5a3e2cd..92a89f00 100644 --- a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c | |||
@@ -52,6 +52,7 @@ static int acr_ucode_patch_sig(struct gk20a *g, | |||
52 | unsigned int *p_dbg_sig, | 52 | unsigned int *p_dbg_sig, |
53 | unsigned int *p_patch_loc, | 53 | unsigned int *p_patch_loc, |
54 | unsigned int *p_patch_ind); | 54 | unsigned int *p_patch_ind); |
55 | static void free_acr_resources(struct gk20a *g, struct ls_flcn_mgr *plsfm); | ||
55 | 56 | ||
56 | /*Globals*/ | 57 | /*Globals*/ |
57 | static void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE); | 58 | static void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE); |
@@ -72,11 +73,7 @@ void gm20b_init_secure_pmu(struct gpu_ops *gops) | |||
72 | gops->pmu.prepare_ucode = prepare_ucode_blob; | 73 | gops->pmu.prepare_ucode = prepare_ucode_blob; |
73 | gops->pmu.pmu_setup_hw_and_bootstrap = gm20b_bootstrap_hs_flcn; | 74 | gops->pmu.pmu_setup_hw_and_bootstrap = gm20b_bootstrap_hs_flcn; |
74 | } | 75 | } |
75 | 76 | /* TODO - check if any free blob res needed*/ | |
76 | static void free_blob_res(struct gk20a *g) | ||
77 | { | ||
78 | /*TODO */ | ||
79 | } | ||
80 | 77 | ||
81 | int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) | 78 | int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) |
82 | { | 79 | { |
@@ -91,6 +88,7 @@ int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) | |||
91 | gm20b_dbg_pmu("requesting PMU ucode in GM20B failed\n"); | 88 | gm20b_dbg_pmu("requesting PMU ucode in GM20B failed\n"); |
92 | return -ENOENT; | 89 | return -ENOENT; |
93 | } | 90 | } |
91 | g->acr.pmu_fw = pmu_fw; | ||
94 | gm20b_dbg_pmu("Loaded PMU ucode in for blob preparation"); | 92 | gm20b_dbg_pmu("Loaded PMU ucode in for blob preparation"); |
95 | 93 | ||
96 | gm20b_dbg_pmu("requesting PMU ucode desc in GM20B\n"); | 94 | gm20b_dbg_pmu("requesting PMU ucode desc in GM20B\n"); |
@@ -103,6 +101,7 @@ int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) | |||
103 | } | 101 | } |
104 | pmu->desc = (struct pmu_ucode_desc *)pmu_desc->data; | 102 | pmu->desc = (struct pmu_ucode_desc *)pmu_desc->data; |
105 | pmu->ucode_image = (u32 *)pmu_fw->data; | 103 | pmu->ucode_image = (u32 *)pmu_fw->data; |
104 | g->acr.pmu_desc = pmu_desc; | ||
106 | 105 | ||
107 | err = gk20a_init_pmu(pmu); | 106 | err = gk20a_init_pmu(pmu); |
108 | if (err) { | 107 | if (err) { |
@@ -134,7 +133,6 @@ release_img_fw: | |||
134 | 133 | ||
135 | int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) | 134 | int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) |
136 | { | 135 | { |
137 | int err = 0; | ||
138 | struct lsf_ucode_desc *lsf_desc; | 136 | struct lsf_ucode_desc *lsf_desc; |
139 | 137 | ||
140 | lsf_desc = kzalloc(sizeof(struct lsf_ucode_desc), GFP_KERNEL); | 138 | lsf_desc = kzalloc(sizeof(struct lsf_ucode_desc), GFP_KERNEL); |
@@ -190,10 +188,18 @@ int prepare_ucode_blob(struct gk20a *g) | |||
190 | u32 status; | 188 | u32 status; |
191 | void *nonwpr_addr; | 189 | void *nonwpr_addr; |
192 | struct ls_flcn_mgr lsfm_l, *plsfm; | 190 | struct ls_flcn_mgr lsfm_l, *plsfm; |
193 | struct sg_table *sgt_nonwpr; | 191 | struct pmu_gk20a *pmu = &g->pmu; |
194 | struct mm_gk20a *mm = &g->mm; | ||
195 | struct vm_gk20a *vm = &mm->pmu.vm; | ||
196 | 192 | ||
193 | if (g->acr.ucode_blob_start) { | ||
194 | /*Recovery case, we do not need to form | ||
195 | non WPR blob of ucodes*/ | ||
196 | status = gk20a_init_pmu(pmu); | ||
197 | if (status) { | ||
198 | gm20b_dbg_pmu("failed to set function pointers\n"); | ||
199 | return status; | ||
200 | } | ||
201 | return 0; | ||
202 | } | ||
197 | plsfm = &lsfm_l; | 203 | plsfm = &lsfm_l; |
198 | memset((void *)plsfm, 0, sizeof(struct ls_flcn_mgr)); | 204 | memset((void *)plsfm, 0, sizeof(struct ls_flcn_mgr)); |
199 | gm20b_dbg_pmu("fetching GMMU regs\n"); | 205 | gm20b_dbg_pmu("fetching GMMU regs\n"); |
@@ -231,6 +237,7 @@ int prepare_ucode_blob(struct gk20a *g) | |||
231 | gm20b_dbg_pmu("LSFM is managing no falcons.\n"); | 237 | gm20b_dbg_pmu("LSFM is managing no falcons.\n"); |
232 | } | 238 | } |
233 | gm20b_dbg_pmu("prepare ucode blob return 0\n"); | 239 | gm20b_dbg_pmu("prepare ucode blob return 0\n"); |
240 | free_acr_resources(g, plsfm); | ||
234 | return 0; | 241 | return 0; |
235 | } | 242 | } |
236 | 243 | ||
@@ -257,7 +264,7 @@ static int lsfm_discover_ucode_images(struct gk20a *g, | |||
257 | if (status == 0) { | 264 | if (status == 0) { |
258 | if (ucode_img.lsf_desc != NULL) { | 265 | if (ucode_img.lsf_desc != NULL) { |
259 | /* The falon_id is formed by grabbing the static base | 266 | /* The falon_id is formed by grabbing the static base |
260 | * falonId from the image and adding the | 267 | * falon_id from the image and adding the |
261 | * engine-designated falcon instance.*/ | 268 | * engine-designated falcon instance.*/ |
262 | pmu->pmu_mode |= PMU_SECURE_MODE; | 269 | pmu->pmu_mode |= PMU_SECURE_MODE; |
263 | falcon_id = ucode_img.lsf_desc->falcon_id + | 270 | falcon_id = ucode_img.lsf_desc->falcon_id + |
@@ -288,7 +295,7 @@ static int lsfm_discover_ucode_images(struct gk20a *g, | |||
288 | 295 | ||
289 | /*0th index is always PMU which is already handled in earlier | 296 | /*0th index is always PMU which is already handled in earlier |
290 | if condition*/ | 297 | if condition*/ |
291 | for (i = 1; i < MAX_SUPPORTED_LSFM; i++) { | 298 | for (i = 1; i < (MAX_SUPPORTED_LSFM); i++) { |
292 | memset(&ucode_img, 0, sizeof(ucode_img)); | 299 | memset(&ucode_img, 0, sizeof(ucode_img)); |
293 | if (pmu_acr_supp_ucode_list[i](g, &ucode_img) == 0) { | 300 | if (pmu_acr_supp_ucode_list[i](g, &ucode_img) == 0) { |
294 | if (ucode_img.lsf_desc != NULL) { | 301 | if (ucode_img.lsf_desc != NULL) { |
@@ -729,6 +736,23 @@ static void lsfm_free_nonpmu_ucode_img_res(struct flcn_ucode_img *p_img) | |||
729 | } | 736 | } |
730 | } | 737 | } |
731 | 738 | ||
739 | static void free_acr_resources(struct gk20a *g, struct ls_flcn_mgr *plsfm) | ||
740 | { | ||
741 | u32 cnt = plsfm->managed_flcn_cnt; | ||
742 | struct lsfm_managed_ucode_img *mg_ucode_img; | ||
743 | while (cnt) { | ||
744 | mg_ucode_img = plsfm->ucode_img_list; | ||
745 | if (mg_ucode_img->ucode_img.lsf_desc->falcon_id == | ||
746 | LSF_FALCON_ID_PMU) | ||
747 | lsfm_free_ucode_img_res(&mg_ucode_img->ucode_img); | ||
748 | else | ||
749 | lsfm_free_nonpmu_ucode_img_res( | ||
750 | &mg_ucode_img->ucode_img); | ||
751 | plsfm->ucode_img_list = mg_ucode_img->next; | ||
752 | kfree(mg_ucode_img); | ||
753 | cnt--; | ||
754 | } | ||
755 | } | ||
732 | 756 | ||
733 | /* Generate WPR requirements for ACR allocation request */ | 757 | /* Generate WPR requirements for ACR allocation request */ |
734 | static int lsf_gen_wpr_requirements(struct gk20a *g, struct ls_flcn_mgr *plsfm) | 758 | static int lsf_gen_wpr_requirements(struct gk20a *g, struct ls_flcn_mgr *plsfm) |
@@ -811,102 +835,120 @@ int gm20b_bootstrap_hs_flcn(struct gk20a *g) | |||
811 | dma_addr_t iova; | 835 | dma_addr_t iova; |
812 | u64 *pacr_ucode_cpuva = NULL, pacr_ucode_pmu_va, *acr_dmem; | 836 | u64 *pacr_ucode_cpuva = NULL, pacr_ucode_pmu_va, *acr_dmem; |
813 | u32 img_size_in_bytes; | 837 | u32 img_size_in_bytes; |
814 | struct flcn_bl_dmem_desc bl_dmem_desc; | ||
815 | u32 status, size; | 838 | u32 status, size; |
816 | u64 start; | 839 | u64 start; |
817 | const struct firmware *acr_fw; | ||
818 | struct acr_gm20b *acr = &g->acr; | 840 | struct acr_gm20b *acr = &g->acr; |
841 | const struct firmware *acr_fw = acr->acr_fw; | ||
842 | struct flcn_bl_dmem_desc *bl_dmem_desc = &acr->bl_dmem_desc; | ||
819 | u32 *acr_ucode_header_t210_load; | 843 | u32 *acr_ucode_header_t210_load; |
820 | u32 *acr_ucode_data_t210_load; | 844 | u32 *acr_ucode_data_t210_load; |
821 | 845 | ||
822 | start = g->acr.ucode_blob_start; | 846 | start = acr->ucode_blob_start; |
823 | size = g->acr.ucode_blob_size; | 847 | size = acr->ucode_blob_size; |
824 | 848 | ||
825 | gm20b_dbg_pmu(""); | 849 | gm20b_dbg_pmu(""); |
826 | 850 | ||
827 | acr_fw = gk20a_request_firmware(g, GM20B_HSBIN_PMU_UCODE_IMAGE); | ||
828 | if (!acr_fw) { | 851 | if (!acr_fw) { |
829 | gk20a_err(dev_from_gk20a(g), "failed to load pmu ucode!!"); | 852 | /*First time init case*/ |
830 | return -ENOENT; | 853 | acr_fw = gk20a_request_firmware(g, GM20B_HSBIN_PMU_UCODE_IMAGE); |
831 | } | 854 | if (!acr_fw) { |
832 | acr->hsbin_hdr = (struct bin_hdr *)acr_fw->data; | 855 | gk20a_err(dev_from_gk20a(g), "pmu ucode get fail"); |
833 | acr->fw_hdr = (struct acr_fw_header *)(acr_fw->data + | 856 | return -ENOENT; |
834 | acr->hsbin_hdr->header_offset); | 857 | } |
835 | acr_ucode_data_t210_load = (u32 *)(acr_fw->data + | 858 | acr->acr_fw = acr_fw; |
836 | acr->hsbin_hdr->data_offset); | 859 | acr->hsbin_hdr = (struct bin_hdr *)acr_fw->data; |
837 | acr_ucode_header_t210_load = (u32 *)(acr_fw->data + | 860 | acr->fw_hdr = (struct acr_fw_header *)(acr_fw->data + |
838 | acr->fw_hdr->hdr_offset); | 861 | acr->hsbin_hdr->header_offset); |
839 | img_size_in_bytes = ALIGN((acr->hsbin_hdr->data_size), 256); | 862 | acr_ucode_data_t210_load = (u32 *)(acr_fw->data + |
840 | 863 | acr->hsbin_hdr->data_offset); | |
841 | /* Lets patch the signatures first.. */ | 864 | acr_ucode_header_t210_load = (u32 *)(acr_fw->data + |
842 | if (acr_ucode_patch_sig(g, acr_ucode_data_t210_load, | 865 | acr->fw_hdr->hdr_offset); |
843 | (u32 *)(acr_fw->data + acr->fw_hdr->sig_prod_offset), | 866 | img_size_in_bytes = ALIGN((acr->hsbin_hdr->data_size), 256); |
844 | (u32 *)(acr_fw->data + acr->fw_hdr->sig_dbg_offset), | 867 | |
845 | (u32 *)(acr_fw->data + acr->fw_hdr->patch_loc), | 868 | /* Lets patch the signatures first.. */ |
846 | (u32 *)(acr_fw->data + acr->fw_hdr->patch_sig)) < 0) | 869 | if (acr_ucode_patch_sig(g, acr_ucode_data_t210_load, |
847 | return -1; | 870 | (u32 *)(acr_fw->data + |
848 | pacr_ucode_cpuva = dma_alloc_coherent(d, img_size_in_bytes, &iova, | 871 | acr->fw_hdr->sig_prod_offset), |
849 | GFP_KERNEL); | 872 | (u32 *)(acr_fw->data + |
850 | if (!pacr_ucode_cpuva) | 873 | acr->fw_hdr->sig_dbg_offset), |
851 | return -ENOMEM; | 874 | (u32 *)(acr_fw->data + |
875 | acr->fw_hdr->patch_loc), | ||
876 | (u32 *)(acr_fw->data + | ||
877 | acr->fw_hdr->patch_sig)) < 0) { | ||
878 | gk20a_err(dev_from_gk20a(g), "patch signatures fail"); | ||
879 | err = -1; | ||
880 | goto err_release_acr_fw; | ||
881 | } | ||
882 | pacr_ucode_cpuva = dma_alloc_coherent(d, img_size_in_bytes, | ||
883 | &iova, GFP_KERNEL); | ||
884 | if (!pacr_ucode_cpuva) { | ||
885 | err = -ENOMEM; | ||
886 | goto err_release_acr_fw; | ||
887 | } | ||
852 | 888 | ||
853 | err = gk20a_get_sgtable(d, &sgt_pmu_ucode, | 889 | err = gk20a_get_sgtable(d, &sgt_pmu_ucode, |
854 | pacr_ucode_cpuva, | 890 | pacr_ucode_cpuva, |
855 | iova, | 891 | iova, |
856 | img_size_in_bytes); | 892 | img_size_in_bytes); |
857 | if (err) { | 893 | if (err) { |
858 | gk20a_err(d, "failed to allocate sg table\n"); | 894 | gk20a_err(d, "failed to allocate sg table\n"); |
859 | err = -ENOMEM; | 895 | err = -ENOMEM; |
860 | goto err_free_acr_buf; | 896 | goto err_free_acr_buf; |
861 | } | 897 | } |
862 | pacr_ucode_pmu_va = gk20a_gmmu_map(vm, &sgt_pmu_ucode, | 898 | pacr_ucode_pmu_va = gk20a_gmmu_map(vm, &sgt_pmu_ucode, |
863 | img_size_in_bytes, | 899 | img_size_in_bytes, |
864 | 0, /* flags */ | 900 | 0, /* flags */ |
865 | gk20a_mem_flag_read_only); | 901 | gk20a_mem_flag_read_only); |
866 | if (!pacr_ucode_pmu_va) { | 902 | if (!pacr_ucode_pmu_va) { |
867 | gk20a_err(d, "failed to map pmu ucode memory!!"); | 903 | gk20a_err(d, "failed to map pmu ucode memory!!"); |
868 | err = -ENOMEM; | 904 | err = -ENOMEM; |
869 | goto err_free_ucode_sgt; | 905 | goto err_free_ucode_sgt; |
870 | } | 906 | } |
871 | acr_dmem = (u64 *) | 907 | acr_dmem = (u64 *) |
872 | &(((u8 *)acr_ucode_data_t210_load)[ | 908 | &(((u8 *)acr_ucode_data_t210_load)[ |
873 | acr_ucode_header_t210_load[2]]); | 909 | acr_ucode_header_t210_load[2]]); |
874 | ((struct flcn_acr_desc *)acr_dmem)->nonwpr_ucode_blob_start = | 910 | ((struct flcn_acr_desc *)acr_dmem)->nonwpr_ucode_blob_start = |
875 | start; | 911 | start; |
876 | ((struct flcn_acr_desc *)acr_dmem)->nonwpr_ucode_blob_size = | 912 | ((struct flcn_acr_desc *)acr_dmem)->nonwpr_ucode_blob_size = |
877 | size; | 913 | size; |
878 | ((struct flcn_acr_desc *)acr_dmem)->regions.no_regions = 2; | 914 | ((struct flcn_acr_desc *)acr_dmem)->regions.no_regions = 2; |
879 | ((struct flcn_acr_desc *)acr_dmem)->wpr_offset = 0; | 915 | ((struct flcn_acr_desc *)acr_dmem)->wpr_offset = 0; |
880 | 916 | ||
881 | for (i = 0; i < (img_size_in_bytes/4); i++) { | 917 | for (i = 0; i < (img_size_in_bytes/4); i++) { |
882 | gk20a_mem_wr32(pacr_ucode_cpuva, i, | 918 | gk20a_mem_wr32(pacr_ucode_cpuva, i, |
883 | acr_ucode_data_t210_load[i]); | 919 | acr_ucode_data_t210_load[i]); |
884 | } | 920 | } |
885 | /* | 921 | acr->acr_ucode.cpuva = pacr_ucode_cpuva; |
886 | * In order to execute this binary, we will be using PMU HAL to run | 922 | acr->acr_ucode.iova = iova; |
887 | * a bootloader which will load this image into PMU IMEM/DMEM. | 923 | acr->acr_ucode.pmu_va = pacr_ucode_pmu_va; |
888 | * Fill up the bootloader descriptor for PMU HAL to use.. | 924 | acr->acr_ucode.size = img_size_in_bytes; |
889 | * TODO: Use standard descriptor which the generic bootloader is | 925 | /* |
890 | * checked in. | 926 | * In order to execute this binary, we will be using |
891 | */ | 927 | * a bootloader which will load this image into PMU IMEM/DMEM. |
928 | * Fill up the bootloader descriptor for PMU HAL to use.. | ||
929 | * TODO: Use standard descriptor which the generic bootloader is | ||
930 | * checked in. | ||
931 | */ | ||
892 | 932 | ||
893 | bl_dmem_desc.signature[0] = 0; | 933 | bl_dmem_desc->signature[0] = 0; |
894 | bl_dmem_desc.signature[1] = 0; | 934 | bl_dmem_desc->signature[1] = 0; |
895 | bl_dmem_desc.signature[2] = 0; | 935 | bl_dmem_desc->signature[2] = 0; |
896 | bl_dmem_desc.signature[3] = 0; | 936 | bl_dmem_desc->signature[3] = 0; |
897 | bl_dmem_desc.ctx_dma = GK20A_PMU_DMAIDX_VIRT; | 937 | bl_dmem_desc->ctx_dma = GK20A_PMU_DMAIDX_VIRT; |
898 | bl_dmem_desc.code_dma_base = | 938 | bl_dmem_desc->code_dma_base = |
899 | (unsigned int)(((u64)pacr_ucode_pmu_va >> 8)); | 939 | (unsigned int)(((u64)pacr_ucode_pmu_va >> 8)); |
900 | bl_dmem_desc.non_sec_code_off = acr_ucode_header_t210_load[0]; | 940 | bl_dmem_desc->non_sec_code_off = acr_ucode_header_t210_load[0]; |
901 | bl_dmem_desc.non_sec_code_size = acr_ucode_header_t210_load[1]; | 941 | bl_dmem_desc->non_sec_code_size = acr_ucode_header_t210_load[1]; |
902 | bl_dmem_desc.sec_code_off = acr_ucode_header_t210_load[5]; | 942 | bl_dmem_desc->sec_code_off = acr_ucode_header_t210_load[5]; |
903 | bl_dmem_desc.sec_code_size = acr_ucode_header_t210_load[6]; | 943 | bl_dmem_desc->sec_code_size = acr_ucode_header_t210_load[6]; |
904 | bl_dmem_desc.code_entry_point = 0; /* Start at 0th offset */ | 944 | bl_dmem_desc->code_entry_point = 0; /* Start at 0th offset */ |
905 | bl_dmem_desc.data_dma_base = | 945 | bl_dmem_desc->data_dma_base = |
906 | bl_dmem_desc.code_dma_base + | 946 | bl_dmem_desc->code_dma_base + |
907 | ((acr_ucode_header_t210_load[2]) >> 8); | 947 | ((acr_ucode_header_t210_load[2]) >> 8); |
908 | bl_dmem_desc.data_size = acr_ucode_header_t210_load[3]; | 948 | bl_dmem_desc->data_size = acr_ucode_header_t210_load[3]; |
909 | status = pmu_exec_gen_bl(g, &bl_dmem_desc, 1); | 949 | gk20a_free_sgtable(&sgt_pmu_ucode); |
950 | } | ||
951 | status = pmu_exec_gen_bl(g, bl_dmem_desc, 1); | ||
910 | if (status != 0) { | 952 | if (status != 0) { |
911 | err = status; | 953 | err = status; |
912 | goto err_free_ucode_map; | 954 | goto err_free_ucode_map; |
@@ -915,11 +957,17 @@ int gm20b_bootstrap_hs_flcn(struct gk20a *g) | |||
915 | err_free_ucode_map: | 957 | err_free_ucode_map: |
916 | gk20a_gmmu_unmap(vm, pacr_ucode_pmu_va, | 958 | gk20a_gmmu_unmap(vm, pacr_ucode_pmu_va, |
917 | img_size_in_bytes, gk20a_mem_flag_none); | 959 | img_size_in_bytes, gk20a_mem_flag_none); |
960 | acr->acr_ucode.pmu_va = 0; | ||
918 | err_free_ucode_sgt: | 961 | err_free_ucode_sgt: |
919 | gk20a_free_sgtable(&sgt_pmu_ucode); | 962 | gk20a_free_sgtable(&sgt_pmu_ucode); |
920 | err_free_acr_buf: | 963 | err_free_acr_buf: |
921 | dma_free_coherent(d, img_size_in_bytes, | 964 | dma_free_coherent(d, img_size_in_bytes, |
922 | pacr_ucode_cpuva, iova); | 965 | pacr_ucode_cpuva, iova); |
966 | acr->acr_ucode.cpuva = NULL; | ||
967 | acr->acr_ucode.iova = 0; | ||
968 | err_release_acr_fw: | ||
969 | release_firmware(acr_fw); | ||
970 | acr->acr_fw = NULL; | ||
923 | return err; | 971 | return err; |
924 | } | 972 | } |
925 | 973 | ||
@@ -927,7 +975,7 @@ u8 pmu_is_debug_mode_en(struct gk20a *g) | |||
927 | { | 975 | { |
928 | int ctl_stat = gk20a_readl(g, pwr_pmu_scpctl_stat_r()); | 976 | int ctl_stat = gk20a_readl(g, pwr_pmu_scpctl_stat_r()); |
929 | return 1; | 977 | return 1; |
930 | /*TODO return (ctl_stat & pwr_pmu_scpctl_stat_debug_mode_m());*/ | 978 | /*TODO return (ctl_stat & pwr_pmu_scpctl_stat_debug_mode_m());*/ |
931 | } | 979 | } |
932 | 980 | ||
933 | /* | 981 | /* |
@@ -966,8 +1014,8 @@ static int bl_bootstrap(struct pmu_gk20a *pmu, | |||
966 | struct flcn_bl_dmem_desc *pbl_desc, u32 bl_sz) | 1014 | struct flcn_bl_dmem_desc *pbl_desc, u32 bl_sz) |
967 | { | 1015 | { |
968 | struct gk20a *g = gk20a_from_pmu(pmu); | 1016 | struct gk20a *g = gk20a_from_pmu(pmu); |
1017 | struct acr_gm20b *acr = &g->acr; | ||
969 | struct mm_gk20a *mm = &g->mm; | 1018 | struct mm_gk20a *mm = &g->mm; |
970 | struct pmu_ucode_desc *desc = pmu->desc; | ||
971 | u32 imem_dst_blk = 0; | 1019 | u32 imem_dst_blk = 0; |
972 | u32 virt_addr = 0; | 1020 | u32 virt_addr = 0; |
973 | u32 tag = 0; | 1021 | u32 tag = 0; |
@@ -1007,7 +1055,7 @@ static int bl_bootstrap(struct pmu_gk20a *pmu, | |||
1007 | pwr_falcon_imemc_aincw_f(1)); | 1055 | pwr_falcon_imemc_aincw_f(1)); |
1008 | virt_addr = pmu_bl_gm10x_desc->bl_start_tag << 8; | 1056 | virt_addr = pmu_bl_gm10x_desc->bl_start_tag << 8; |
1009 | tag = virt_addr >> 8; /* tag is always 256B aligned */ | 1057 | tag = virt_addr >> 8; /* tag is always 256B aligned */ |
1010 | bl_ucode = (u32 *)(pmu->ucode.cpuva); | 1058 | bl_ucode = (u32 *)(acr->hsbl_ucode.cpuva); |
1011 | for (index = 0; index < bl_sz/4; index++) { | 1059 | for (index = 0; index < bl_sz/4; index++) { |
1012 | if ((index % 64) == 0) { | 1060 | if ((index % 64) == 0) { |
1013 | gk20a_writel(g, pwr_falcon_imemt_r(0), | 1061 | gk20a_writel(g, pwr_falcon_imemt_r(0), |
@@ -1027,8 +1075,6 @@ static int bl_bootstrap(struct pmu_gk20a *pmu, | |||
1027 | gk20a_writel(g, pwr_falcon_cpuctl_r(), | 1075 | gk20a_writel(g, pwr_falcon_cpuctl_r(), |
1028 | pwr_falcon_cpuctl_startcpu_f(1)); | 1076 | pwr_falcon_cpuctl_startcpu_f(1)); |
1029 | 1077 | ||
1030 | gk20a_writel(g, pwr_falcon_os_r(), desc->app_version); | ||
1031 | |||
1032 | return 0; | 1078 | return 0; |
1033 | } | 1079 | } |
1034 | 1080 | ||
@@ -1082,7 +1128,6 @@ int gm20b_init_pmu_setup_hw1(struct gk20a *g, struct flcn_bl_dmem_desc *desc, | |||
1082 | */ | 1128 | */ |
1083 | int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt) | 1129 | int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt) |
1084 | { | 1130 | { |
1085 | struct pmu_gk20a *pmu = &g->pmu; | ||
1086 | struct mm_gk20a *mm = &g->mm; | 1131 | struct mm_gk20a *mm = &g->mm; |
1087 | struct vm_gk20a *vm = &mm->pmu.vm; | 1132 | struct vm_gk20a *vm = &mm->pmu.vm; |
1088 | struct device *d = dev_from_gk20a(g); | 1133 | struct device *d = dev_from_gk20a(g); |
@@ -1092,29 +1137,73 @@ int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt) | |||
1092 | u32 bl_sz; | 1137 | u32 bl_sz; |
1093 | void *bl_cpuva; | 1138 | void *bl_cpuva; |
1094 | u64 bl_pmu_va; | 1139 | u64 bl_pmu_va; |
1095 | const struct firmware *hsbl_fw; | ||
1096 | struct acr_gm20b *acr = &g->acr; | 1140 | struct acr_gm20b *acr = &g->acr; |
1141 | const struct firmware *hsbl_fw = acr->hsbl_fw; | ||
1097 | struct hsflcn_bl_desc *pmu_bl_gm10x_desc; | 1142 | struct hsflcn_bl_desc *pmu_bl_gm10x_desc; |
1098 | u32 *pmu_bl_gm10x = NULL; | 1143 | u32 *pmu_bl_gm10x = NULL; |
1099 | DEFINE_DMA_ATTRS(attrs); | 1144 | DEFINE_DMA_ATTRS(attrs); |
1100 | gm20b_dbg_pmu(""); | 1145 | gm20b_dbg_pmu(""); |
1101 | 1146 | ||
1102 | hsbl_fw = gk20a_request_firmware(g, GM20B_HSBIN_PMU_BL_UCODE_IMAGE); | ||
1103 | if (!hsbl_fw) { | 1147 | if (!hsbl_fw) { |
1104 | gk20a_err(dev_from_gk20a(g), "failed to load pmu ucode!!"); | 1148 | hsbl_fw = gk20a_request_firmware(g, |
1105 | return -ENOENT; | 1149 | GM20B_HSBIN_PMU_BL_UCODE_IMAGE); |
1150 | if (!hsbl_fw) { | ||
1151 | gk20a_err(dev_from_gk20a(g), "pmu ucode load fail"); | ||
1152 | return -ENOENT; | ||
1153 | } | ||
1154 | acr->hsbl_fw = hsbl_fw; | ||
1155 | acr->bl_bin_hdr = (struct bin_hdr *)hsbl_fw->data; | ||
1156 | acr->pmu_hsbl_desc = (struct hsflcn_bl_desc *)(hsbl_fw->data + | ||
1157 | acr->bl_bin_hdr->header_offset); | ||
1158 | pmu_bl_gm10x_desc = acr->pmu_hsbl_desc; | ||
1159 | pmu_bl_gm10x = (u32 *)(hsbl_fw->data + | ||
1160 | acr->bl_bin_hdr->data_offset); | ||
1161 | bl_sz = ALIGN(pmu_bl_gm10x_desc->bl_img_hdr.bl_code_size, | ||
1162 | 256); | ||
1163 | acr->hsbl_ucode.size = bl_sz; | ||
1164 | gm20b_dbg_pmu("Executing Generic Bootloader\n"); | ||
1165 | |||
1166 | /*TODO in code verify that enable PMU is done, | ||
1167 | scrubbing etc is done*/ | ||
1168 | /*TODO in code verify that gmmu vm init is done*/ | ||
1169 | dma_set_attr(DMA_ATTR_READ_ONLY, &attrs); | ||
1170 | bl_cpuva = dma_alloc_attrs(d, bl_sz, | ||
1171 | &iova, | ||
1172 | GFP_KERNEL, | ||
1173 | &attrs); | ||
1174 | gm20b_dbg_pmu("bl size is %x\n", bl_sz); | ||
1175 | if (!bl_cpuva) { | ||
1176 | gk20a_err(d, "failed to allocate memory\n"); | ||
1177 | err = -ENOMEM; | ||
1178 | goto err_done; | ||
1179 | } | ||
1180 | acr->hsbl_ucode.cpuva = bl_cpuva; | ||
1181 | acr->hsbl_ucode.iova = iova; | ||
1182 | |||
1183 | err = gk20a_get_sgtable(d, &sgt_pmu_ucode, | ||
1184 | bl_cpuva, | ||
1185 | iova, | ||
1186 | bl_sz); | ||
1187 | if (err) { | ||
1188 | gk20a_err(d, "failed to allocate sg table\n"); | ||
1189 | goto err_free_cpu_va; | ||
1190 | } | ||
1191 | |||
1192 | bl_pmu_va = gk20a_gmmu_map(vm, &sgt_pmu_ucode, | ||
1193 | bl_sz, | ||
1194 | 0, /* flags */ | ||
1195 | gk20a_mem_flag_read_only); | ||
1196 | if (!bl_pmu_va) { | ||
1197 | gk20a_err(d, "failed to map pmu ucode memory!!"); | ||
1198 | goto err_free_ucode_sgt; | ||
1199 | } | ||
1200 | acr->hsbl_ucode.pmu_va = bl_pmu_va; | ||
1201 | |||
1202 | for (i = 0; i < (bl_sz) >> 2; i++) | ||
1203 | gk20a_mem_wr32(bl_cpuva, i, pmu_bl_gm10x[i]); | ||
1204 | gm20b_dbg_pmu("Copied bl ucode to bl_cpuva\n"); | ||
1205 | gk20a_free_sgtable(&sgt_pmu_ucode); | ||
1106 | } | 1206 | } |
1107 | acr->bl_bin_hdr = (struct bin_hdr *)hsbl_fw->data; | ||
1108 | acr->pmu_hsbl_desc = (struct hsflcn_bl_desc *)(hsbl_fw->data + | ||
1109 | acr->bl_bin_hdr->header_offset); | ||
1110 | pmu_bl_gm10x_desc = acr->pmu_hsbl_desc; | ||
1111 | pmu_bl_gm10x = (u32 *)(hsbl_fw->data + acr->bl_bin_hdr->data_offset); | ||
1112 | bl_sz = ALIGN(pmu_bl_gm10x_desc->bl_img_hdr.bl_code_size, | ||
1113 | 256); | ||
1114 | gm20b_dbg_pmu("Executing Generic Bootloader\n"); | ||
1115 | |||
1116 | /*TODO in code verify that enable PMU is done, scrubbing etc is done*/ | ||
1117 | /*TODO in code verify that gmmu vm init is done*/ | ||
1118 | /* | 1207 | /* |
1119 | * Disable interrupts to avoid kernel hitting breakpoint due | 1208 | * Disable interrupts to avoid kernel hitting breakpoint due |
1120 | * to PMU halt | 1209 | * to PMU halt |
@@ -1122,43 +1211,13 @@ int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt) | |||
1122 | 1211 | ||
1123 | gk20a_writel(g, pwr_falcon_irqsclr_r(), | 1212 | gk20a_writel(g, pwr_falcon_irqsclr_r(), |
1124 | gk20a_readl(g, pwr_falcon_irqsclr_r()) & (~(0x10))); | 1213 | gk20a_readl(g, pwr_falcon_irqsclr_r()) & (~(0x10))); |
1214 | gm20b_dbg_pmu("err reg :%x\n", readl(mc + | ||
1215 | MC_ERR_GENERALIZED_CARVEOUT_STATUS_0)); | ||
1216 | gm20b_dbg_pmu("phys sec reg %x\n", gk20a_readl(g, | ||
1217 | pwr_falcon_mmu_phys_sec_r())); | ||
1218 | gm20b_dbg_pmu("sctl reg %x\n", gk20a_readl(g, pwr_falcon_sctl_r())); | ||
1125 | 1219 | ||
1126 | dma_set_attr(DMA_ATTR_READ_ONLY, &attrs); | 1220 | gm20b_init_pmu_setup_hw1(g, desc, acr->hsbl_ucode.size); |
1127 | bl_cpuva = dma_alloc_attrs(d, bl_sz, | ||
1128 | &iova, | ||
1129 | GFP_KERNEL, | ||
1130 | &attrs); | ||
1131 | gm20b_dbg_pmu("bl size is %x\n", bl_sz); | ||
1132 | if (!bl_cpuva) { | ||
1133 | gk20a_err(d, "failed to allocate memory\n"); | ||
1134 | err = -ENOMEM; | ||
1135 | goto err_done; | ||
1136 | } | ||
1137 | |||
1138 | err = gk20a_get_sgtable(d, &sgt_pmu_ucode, | ||
1139 | bl_cpuva, | ||
1140 | iova, | ||
1141 | bl_sz); | ||
1142 | if (err) { | ||
1143 | gk20a_err(d, "failed to allocate sg table\n"); | ||
1144 | goto err_free_cpu_va; | ||
1145 | } | ||
1146 | |||
1147 | bl_pmu_va = gk20a_gmmu_map(vm, &sgt_pmu_ucode, | ||
1148 | bl_sz, | ||
1149 | 0, /* flags */ | ||
1150 | gk20a_mem_flag_read_only); | ||
1151 | if (!bl_pmu_va) { | ||
1152 | gk20a_err(d, "failed to map pmu ucode memory!!"); | ||
1153 | goto err_free_ucode_sgt; | ||
1154 | } | ||
1155 | |||
1156 | for (i = 0; i < (bl_sz) >> 2; i++) | ||
1157 | gk20a_mem_wr32(bl_cpuva, i, pmu_bl_gm10x[i]); | ||
1158 | gm20b_dbg_pmu("Copied bl ucode to bl_cpuva\n"); | ||
1159 | pmu->ucode.cpuva = bl_cpuva; | ||
1160 | pmu->ucode.pmu_va = bl_pmu_va; | ||
1161 | gm20b_init_pmu_setup_hw1(g, desc, bl_sz); | ||
1162 | /* Poll for HALT */ | 1221 | /* Poll for HALT */ |
1163 | if (b_wait_for_halt) { | 1222 | if (b_wait_for_halt) { |
1164 | err = pmu_wait_for_halt(g, GPU_TIMEOUT_DEFAULT); | 1223 | err = pmu_wait_for_halt(g, GPU_TIMEOUT_DEFAULT); |
@@ -1176,16 +1235,17 @@ int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt) | |||
1176 | pwr_falcon_mmu_phys_sec_r())); | 1235 | pwr_falcon_mmu_phys_sec_r())); |
1177 | gm20b_dbg_pmu("sctl reg %x\n", gk20a_readl(g, pwr_falcon_sctl_r())); | 1236 | gm20b_dbg_pmu("sctl reg %x\n", gk20a_readl(g, pwr_falcon_sctl_r())); |
1178 | start_gm20b_pmu(g); | 1237 | start_gm20b_pmu(g); |
1179 | err = 0; | 1238 | return 0; |
1180 | err_unmap_bl: | 1239 | err_unmap_bl: |
1181 | gk20a_gmmu_unmap(vm, pmu->ucode.pmu_va, | 1240 | gk20a_gmmu_unmap(vm, acr->hsbl_ucode.pmu_va, |
1182 | bl_sz, gk20a_mem_flag_none); | 1241 | acr->hsbl_ucode.size, gk20a_mem_flag_none); |
1183 | err_free_ucode_sgt: | 1242 | err_free_ucode_sgt: |
1184 | gk20a_free_sgtable(&sgt_pmu_ucode); | 1243 | gk20a_free_sgtable(&sgt_pmu_ucode); |
1185 | err_free_cpu_va: | 1244 | err_free_cpu_va: |
1186 | dma_free_attrs(d, bl_sz, | 1245 | dma_free_attrs(d, acr->hsbl_ucode.size, |
1187 | bl_cpuva, iova, &attrs); | 1246 | acr->hsbl_ucode.cpuva, acr->hsbl_ucode.iova, &attrs); |
1188 | err_done: | 1247 | err_done: |
1248 | release_firmware(hsbl_fw); | ||
1189 | return err; | 1249 | return err; |
1190 | } | 1250 | } |
1191 | 1251 | ||
diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.h b/drivers/gpu/nvgpu/gm20b/acr_gm20b.h index b186e489..d1c42e46 100644 --- a/drivers/gpu/nvgpu/gm20b/acr_gm20b.h +++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.h | |||
@@ -365,6 +365,13 @@ struct acr_gm20b { | |||
365 | struct bin_hdr *hsbin_hdr; | 365 | struct bin_hdr *hsbin_hdr; |
366 | struct acr_fw_header *fw_hdr; | 366 | struct acr_fw_header *fw_hdr; |
367 | u32 pmu_args; | 367 | u32 pmu_args; |
368 | const struct firmware *acr_fw; | ||
369 | struct pmu_mem_desc acr_ucode; | ||
370 | const struct firmware *hsbl_fw; | ||
371 | struct pmu_mem_desc hsbl_ucode; | ||
372 | struct flcn_bl_dmem_desc bl_dmem_desc; | ||
373 | const struct firmware *pmu_fw; | ||
374 | const struct firmware *pmu_desc; | ||
368 | }; | 375 | }; |
369 | 376 | ||
370 | void gm20b_init_secure_pmu(struct gpu_ops *gops); | 377 | void gm20b_init_secure_pmu(struct gpu_ops *gops); |