1 // SPDX-License-Identifier: GPL-2.0-only OR MIT 2 /* Copyright (c) 2023 Imagination Technologies Ltd. */ 3 4 #include "pvr_device.h" 5 #include "pvr_fw.h" 6 #include "pvr_fw_mips.h" 7 #include "pvr_gem.h" 8 #include "pvr_rogue_mips.h" 9 #include "pvr_vm_mips.h" 10 11 #include <linux/elf.h> 12 #include <linux/err.h> 13 #include <linux/types.h> 14 15 #define ROGUE_FW_HEAP_MIPS_BASE 0xC0000000 16 #define ROGUE_FW_HEAP_MIPS_SHIFT 24 /* 16 MB */ 17 #define ROGUE_FW_HEAP_MIPS_RESERVED_SIZE SZ_1M 18 19 /** 20 * process_elf_command_stream() - Process ELF firmware image and populate 21 * firmware sections 22 * @pvr_dev: Device pointer. 23 * @fw: Pointer to firmware image. 24 * @fw_code_ptr: Pointer to FW code section. 25 * @fw_data_ptr: Pointer to FW data section. 26 * @fw_core_code_ptr: Pointer to FW coremem code section. 27 * @fw_core_data_ptr: Pointer to FW coremem data section. 28 * 29 * Returns : 30 * * 0 on success, or 31 * * -EINVAL on any error in ELF command stream. 32 */ 33 static int 34 process_elf_command_stream(struct pvr_device *pvr_dev, const u8 *fw, u8 *fw_code_ptr, 35 u8 *fw_data_ptr, u8 *fw_core_code_ptr, u8 *fw_core_data_ptr) 36 { 37 struct elf32_hdr *header = (struct elf32_hdr *)fw; 38 struct elf32_phdr *program_header = (struct elf32_phdr *)(fw + header->e_phoff); 39 struct drm_device *drm_dev = from_pvr_device(pvr_dev); 40 int err; 41 42 for (u32 entry = 0; entry < header->e_phnum; entry++, program_header++) { 43 void *write_addr; 44 45 /* Only consider loadable entries in the ELF segment table */ 46 if (program_header->p_type != PT_LOAD) 47 continue; 48 49 err = pvr_fw_find_mmu_segment(pvr_dev, program_header->p_vaddr, 50 program_header->p_memsz, fw_code_ptr, fw_data_ptr, 51 fw_core_code_ptr, fw_core_data_ptr, &write_addr); 52 if (err) { 53 drm_err(drm_dev, 54 "Addr 0x%x (size: %d) not found in any firmware segment", 55 program_header->p_vaddr, program_header->p_memsz); 56 return err; 57 } 58 59 /* Write to FW allocation only if available */ 60 if (write_addr) { 61 memcpy(write_addr, fw + program_header->p_offset, 62 program_header->p_filesz); 63 64 memset((u8 *)write_addr + program_header->p_filesz, 0, 65 program_header->p_memsz - program_header->p_filesz); 66 } 67 } 68 69 return 0; 70 } 71 72 static int 73 pvr_mips_init(struct pvr_device *pvr_dev) 74 { 75 pvr_fw_heap_info_init(pvr_dev, ROGUE_FW_HEAP_MIPS_SHIFT, ROGUE_FW_HEAP_MIPS_RESERVED_SIZE); 76 77 return pvr_vm_mips_init(pvr_dev); 78 } 79 80 static void 81 pvr_mips_fini(struct pvr_device *pvr_dev) 82 { 83 pvr_vm_mips_fini(pvr_dev); 84 } 85 86 static int 87 pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw, 88 u8 *fw_code_ptr, u8 *fw_data_ptr, u8 *fw_core_code_ptr, u8 *fw_core_data_ptr, 89 u32 core_code_alloc_size) 90 { 91 struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev; 92 struct pvr_fw_mips_data *mips_data = fw_dev->processor_data.mips_data; 93 const struct pvr_fw_layout_entry *boot_code_entry; 94 const struct pvr_fw_layout_entry *boot_data_entry; 95 const struct pvr_fw_layout_entry *exception_code_entry; 96 const struct pvr_fw_layout_entry *stack_entry; 97 struct rogue_mipsfw_boot_data *boot_data; 98 dma_addr_t dma_addr; 99 int err; 100 101 err = process_elf_command_stream(pvr_dev, fw, fw_code_ptr, fw_data_ptr, fw_core_code_ptr, 102 fw_core_data_ptr); 103 if (err) 104 return err; 105 106 boot_code_entry = pvr_fw_find_layout_entry(pvr_dev, MIPS_BOOT_CODE); 107 boot_data_entry = pvr_fw_find_layout_entry(pvr_dev, MIPS_BOOT_DATA); 108 exception_code_entry = pvr_fw_find_layout_entry(pvr_dev, MIPS_EXCEPTIONS_CODE); 109 if (!boot_code_entry || !boot_data_entry || !exception_code_entry) 110 return -EINVAL; 111 112 WARN_ON(pvr_gem_get_dma_addr(fw_dev->mem.code_obj->gem, boot_code_entry->alloc_offset, 113 &mips_data->boot_code_dma_addr)); 114 WARN_ON(pvr_gem_get_dma_addr(fw_dev->mem.data_obj->gem, boot_data_entry->alloc_offset, 115 &mips_data->boot_data_dma_addr)); 116 WARN_ON(pvr_gem_get_dma_addr(fw_dev->mem.code_obj->gem, 117 exception_code_entry->alloc_offset, 118 &mips_data->exception_code_dma_addr)); 119 120 stack_entry = pvr_fw_find_layout_entry(pvr_dev, MIPS_STACK); 121 if (!stack_entry) 122 return -EINVAL; 123 124 boot_data = (struct rogue_mipsfw_boot_data *)(fw_data_ptr + boot_data_entry->alloc_offset + 125 ROGUE_MIPSFW_BOOTLDR_CONF_OFFSET); 126 127 WARN_ON(pvr_fw_object_get_dma_addr(fw_dev->mem.data_obj, stack_entry->alloc_offset, 128 &dma_addr)); 129 boot_data->stack_phys_addr = dma_addr; 130 131 boot_data->reg_base = pvr_dev->regs_resource->start; 132 133 for (u32 page_nr = 0; page_nr < ARRAY_SIZE(boot_data->pt_phys_addr); page_nr++) { 134 /* Firmware expects 4k pages, but host page size might be different. */ 135 u32 src_page_nr = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) >> PAGE_SHIFT; 136 u32 page_offset = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) & ~PAGE_MASK; 137 138 boot_data->pt_phys_addr[page_nr] = mips_data->pt_dma_addr[src_page_nr] + 139 page_offset; 140 } 141 142 boot_data->pt_log2_page_size = ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K; 143 boot_data->pt_num_pages = ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES; 144 boot_data->reserved1 = 0; 145 boot_data->reserved2 = 0; 146 147 return 0; 148 } 149 150 static int 151 pvr_mips_wrapper_init(struct pvr_device *pvr_dev) 152 { 153 struct pvr_fw_mips_data *mips_data = pvr_dev->fw_dev.processor_data.mips_data; 154 const u64 remap_settings = ROGUE_MIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE; 155 u32 phys_bus_width; 156 157 int err = PVR_FEATURE_VALUE(pvr_dev, phys_bus_width, &phys_bus_width); 158 159 if (WARN_ON(err)) 160 return err; 161 162 /* Currently MIPS FW only supported with physical bus width > 32 bits. */ 163 if (WARN_ON(phys_bus_width <= 32)) 164 return -EINVAL; 165 166 pvr_cr_write32(pvr_dev, ROGUE_CR_MIPS_WRAPPER_CONFIG, 167 (ROGUE_MIPSFW_REGISTERS_VIRTUAL_BASE >> 168 ROGUE_MIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN) | 169 ROGUE_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_MICROMIPS); 170 171 /* Configure remap for boot code, boot data and exceptions code areas. */ 172 pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG1, 173 ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN | 174 ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG1_MODE_ENABLE_EN); 175 pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG2, 176 (mips_data->boot_code_dma_addr & 177 ~ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG2_ADDR_OUT_CLRMSK) | remap_settings); 178 179 if (PVR_HAS_QUIRK(pvr_dev, 63553)) { 180 /* 181 * WA always required on 36 bit cores, to avoid continuous unmapped memory accesses 182 * to address 0x0. 183 */ 184 WARN_ON(phys_bus_width != 36); 185 186 pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP5_CONFIG1, 187 ROGUE_CR_MIPS_ADDR_REMAP5_CONFIG1_MODE_ENABLE_EN); 188 pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP5_CONFIG2, 189 (mips_data->boot_code_dma_addr & 190 ~ROGUE_CR_MIPS_ADDR_REMAP5_CONFIG2_ADDR_OUT_CLRMSK) | 191 remap_settings); 192 } 193 194 pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG1, 195 ROGUE_MIPSFW_DATA_REMAP_PHYS_ADDR_IN | 196 ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG1_MODE_ENABLE_EN); 197 pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG2, 198 (mips_data->boot_data_dma_addr & 199 ~ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG2_ADDR_OUT_CLRMSK) | remap_settings); 200 201 pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG1, 202 ROGUE_MIPSFW_CODE_REMAP_PHYS_ADDR_IN | 203 ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG1_MODE_ENABLE_EN); 204 pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG2, 205 (mips_data->exception_code_dma_addr & 206 ~ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG2_ADDR_OUT_CLRMSK) | remap_settings); 207 208 /* Garten IDLE bit controlled by MIPS. */ 209 pvr_cr_write64(pvr_dev, ROGUE_CR_MTS_GARTEN_WRAPPER_CONFIG, 210 ROGUE_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META); 211 212 /* Turn on the EJTAG probe. */ 213 pvr_cr_write32(pvr_dev, ROGUE_CR_MIPS_DEBUG_CONFIG, 0); 214 215 return 0; 216 } 217 218 static u32 219 pvr_mips_get_fw_addr_with_offset(struct pvr_fw_object *fw_obj, u32 offset) 220 { 221 struct pvr_device *pvr_dev = to_pvr_device(gem_from_pvr_gem(fw_obj->gem)->dev); 222 223 /* MIPS cacheability is determined by page table. */ 224 return ((fw_obj->fw_addr_offset + offset) & pvr_dev->fw_dev.fw_heap_info.offset_mask) | 225 ROGUE_FW_HEAP_MIPS_BASE; 226 } 227 228 static bool 229 pvr_mips_has_fixed_data_addr(void) 230 { 231 return true; 232 } 233 234 const struct pvr_fw_defs pvr_fw_defs_mips = { 235 .init = pvr_mips_init, 236 .fini = pvr_mips_fini, 237 .fw_process = pvr_mips_fw_process, 238 .vm_map = pvr_vm_mips_map, 239 .vm_unmap = pvr_vm_mips_unmap, 240 .get_fw_addr_with_offset = pvr_mips_get_fw_addr_with_offset, 241 .wrapper_init = pvr_mips_wrapper_init, 242 .has_fixed_data_addr = pvr_mips_has_fixed_data_addr, 243 .irq = { 244 .enable_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_ENABLE, 245 .status_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS, 246 .clear_reg = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR, 247 .event_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_STATUS_EVENT_EN, 248 .clear_mask = ROGUE_CR_MIPS_WRAPPER_IRQ_CLEAR_EVENT_EN, 249 }, 250 }; 251