diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c | 126 |
1 files changed, 16 insertions, 110 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c index d5395ebfe8d3..6707b8edc086 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c @@ -20,103 +20,8 @@ * DEALINGS IN THE SOFTWARE. */ -#include "priv.h" - -#include <core/gpuobj.h> - -/* - * The BL header format used by GM20B's firmware is slightly different - * from the one of GM200. Fix the differences here. - */ -struct gm20b_flcn_bl_desc { - u32 reserved[4]; - u32 signature[4]; - u32 ctx_dma; - u32 code_dma_base; - u32 non_sec_code_off; - u32 non_sec_code_size; - u32 sec_code_off; - u32 sec_code_size; - u32 code_entry_point; - u32 data_dma_base; - u32 data_size; -}; - -static int -gm20b_secboot_prepare_blobs(struct gm200_secboot *gsb) -{ - struct nvkm_subdev *subdev = &gsb->base.subdev; - int acr_size; - int ret; - - ret = gm20x_secboot_prepare_blobs(gsb); - if (ret) - return ret; - - acr_size = gsb->acr_load_blob->size; - /* - * On Tegra the WPR region is set by the bootloader. It is illegal for - * the HS blob to be larger than this region. - */ - if (acr_size > gsb->wpr_size) { - nvkm_error(subdev, "WPR region too small for FW blob!\n"); - nvkm_error(subdev, "required: %dB\n", acr_size); - nvkm_error(subdev, "WPR size: %dB\n", gsb->wpr_size); - return -ENOSPC; - } - - return 0; -} - -/** - * gm20b_secboot_fixup_bl_desc - adapt BL descriptor to format used by GM20B FW - * - * There is only a slight format difference (DMA addresses being 32-bits and - * 256B-aligned) to address. - */ -static void -gm20b_secboot_fixup_bl_desc(const struct gm200_flcn_bl_desc *desc, void *ret) -{ - struct gm20b_flcn_bl_desc *gdesc = ret; - u64 addr; - - memcpy(gdesc->reserved, desc->reserved, sizeof(gdesc->reserved)); - memcpy(gdesc->signature, desc->signature, sizeof(gdesc->signature)); - gdesc->ctx_dma = desc->ctx_dma; - addr = desc->code_dma_base.hi; - addr <<= 32; - addr |= desc->code_dma_base.lo; - gdesc->code_dma_base = lower_32_bits(addr >> 8); - gdesc->non_sec_code_off = desc->non_sec_code_off; - gdesc->non_sec_code_size = desc->non_sec_code_size; - gdesc->sec_code_off = desc->sec_code_off; - gdesc->sec_code_size = desc->sec_code_size; - gdesc->code_entry_point = desc->code_entry_point; - addr = desc->data_dma_base.hi; - addr <<= 32; - addr |= desc->data_dma_base.lo; - gdesc->data_dma_base = lower_32_bits(addr >> 8); - gdesc->data_size = desc->data_size; -} - -static void -gm20b_secboot_fixup_hs_desc(struct gm200_secboot *gsb, - struct hsflcn_acr_desc *desc) -{ - desc->ucode_blob_base = gsb->ls_blob->addr; - desc->ucode_blob_size = gsb->ls_blob->size; - - desc->wpr_offset = 0; -} - -static const struct gm200_secboot_func -gm20b_secboot_func = { - .bl_desc_size = sizeof(struct gm20b_flcn_bl_desc), - .fixup_bl_desc = gm20b_secboot_fixup_bl_desc, - .fixup_hs_desc = gm20b_secboot_fixup_hs_desc, - .prepare_blobs = gm20b_secboot_prepare_blobs, -}; - +#include "acr.h" +#include "gm200.h" #ifdef CONFIG_ARCH_TEGRA #define TEGRA_MC_BASE 0x70019000 @@ -144,15 +49,15 @@ gm20b_tegra_read_wpr(struct gm200_secboot *gsb) nvkm_error(&sb->subdev, "Cannot map Tegra MC registers\n"); return PTR_ERR(mc); } - gsb->wpr_addr = ioread32_native(mc + MC_SECURITY_CARVEOUT2_BOM_0) | + sb->wpr_addr = ioread32_native(mc + MC_SECURITY_CARVEOUT2_BOM_0) | ((u64)ioread32_native(mc + MC_SECURITY_CARVEOUT2_BOM_HI_0) << 32); - gsb->wpr_size = ioread32_native(mc + MC_SECURITY_CARVEOUT2_SIZE_128K) + sb->wpr_size = ioread32_native(mc + MC_SECURITY_CARVEOUT2_SIZE_128K) << 17; cfg = ioread32_native(mc + MC_SECURITY_CARVEOUT2_CFG0); iounmap(mc); /* Check that WPR settings are valid */ - if (gsb->wpr_size == 0) { + if (sb->wpr_size == 0) { nvkm_error(&sb->subdev, "WPR region is empty\n"); return -EINVAL; } @@ -174,7 +79,7 @@ gm20b_tegra_read_wpr(struct gm200_secboot *gsb) #endif static int -gm20b_secboot_init(struct nvkm_secboot *sb) +gm20b_secboot_oneinit(struct nvkm_secboot *sb) { struct gm200_secboot *gsb = gm200_secboot(sb); int ret; @@ -183,17 +88,15 @@ gm20b_secboot_init(struct nvkm_secboot *sb) if (ret) return ret; - return gm200_secboot_init(sb); + return gm200_secboot_oneinit(sb); } static const struct nvkm_secboot_func gm20b_secboot = { .dtor = gm200_secboot_dtor, - .init = gm20b_secboot_init, - .reset = gm200_secboot_reset, - .start = gm200_secboot_start, - .managed_falcons = BIT(NVKM_SECBOOT_FALCON_FECS), - .boot_falcon = NVKM_SECBOOT_FALCON_PMU, + .oneinit = gm20b_secboot_oneinit, + .fini = gm200_secboot_fini, + .run_blob = gm200_secboot_run_blob, }; int @@ -202,6 +105,11 @@ gm20b_secboot_new(struct nvkm_device *device, int index, { int ret; struct gm200_secboot *gsb; + struct nvkm_acr *acr; + + acr = acr_r352_new(BIT(NVKM_SECBOOT_FALCON_FECS)); + if (IS_ERR(acr)) + return PTR_ERR(acr); gsb = kzalloc(sizeof(*gsb), GFP_KERNEL); if (!gsb) { @@ -210,12 +118,10 @@ gm20b_secboot_new(struct nvkm_device *device, int index, } *psb = &gsb->base; - ret = nvkm_secboot_ctor(&gm20b_secboot, device, index, &gsb->base); + ret = nvkm_secboot_ctor(&gm20b_secboot, acr, device, index, &gsb->base); if (ret) return ret; - gsb->func = &gm20b_secboot_func; - return 0; } |