mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-16 07:24:39 +08:00
3cc808e323
Some reported by Stephen Rothwell. The rest were found by running the kernel-doc build script. Some indentation fixes. Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202311241526.Y2WZeUau-lkp@intel.com/ Signed-off-by: Donald Robson <donald.robson@imgtec.com> Signed-off-by: Maxime Ripard <mripard@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20231128173507.95119-1-donald.robson@imgtec.com
510 lines
14 KiB
C
510 lines
14 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
|
|
/* Copyright (c) 2023 Imagination Technologies Ltd. */
|
|
|
|
#ifndef PVR_FW_H
|
|
#define PVR_FW_H
|
|
|
|
#include "pvr_fw_info.h"
|
|
#include "pvr_fw_trace.h"
|
|
#include "pvr_gem.h"
|
|
|
|
#include <drm/drm_mm.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
/* Forward declarations from "pvr_device.h". */
|
|
struct pvr_device;
|
|
struct pvr_file;
|
|
|
|
/* Forward declaration from "pvr_vm.h". */
|
|
struct pvr_vm_context;
|
|
|
|
#define ROGUE_FWIF_FWCCB_NUMCMDS_LOG2 5
|
|
|
|
#define ROGUE_FWIF_KCCB_NUMCMDS_LOG2_DEFAULT 7
|
|
|
|
/**
|
|
* struct pvr_fw_object - container for firmware memory allocations
|
|
*/
|
|
struct pvr_fw_object {
|
|
/** @ref_count: FW object reference counter. */
|
|
struct kref ref_count;
|
|
|
|
/** @gem: GEM object backing the FW object. */
|
|
struct pvr_gem_object *gem;
|
|
|
|
/**
|
|
* @fw_mm_node: Node representing mapping in FW address space. @pvr_obj->lock must
|
|
* be held when writing.
|
|
*/
|
|
struct drm_mm_node fw_mm_node;
|
|
|
|
/**
|
|
* @fw_addr_offset: Virtual address offset of firmware mapping. Only
|
|
* valid if @flags has %PVR_GEM_OBJECT_FLAGS_FW_MAPPED
|
|
* set.
|
|
*/
|
|
u32 fw_addr_offset;
|
|
|
|
/**
|
|
* @init: Initialisation callback. Will be called on object creation and FW hard reset.
|
|
* Object will have been zeroed before this is called.
|
|
*/
|
|
void (*init)(void *cpu_ptr, void *priv);
|
|
|
|
/** @init_priv: Private data for initialisation callback. */
|
|
void *init_priv;
|
|
|
|
/** @node: Node for firmware object list. */
|
|
struct list_head node;
|
|
};
|
|
|
|
/**
|
|
* struct pvr_fw_defs - FW processor function table and static definitions
|
|
*/
|
|
struct pvr_fw_defs {
|
|
/**
|
|
* @init:
|
|
*
|
|
* FW processor specific initialisation.
|
|
* @pvr_dev: Target PowerVR device.
|
|
*
|
|
* This function must call pvr_fw_heap_calculate() to initialise the firmware heap for this
|
|
* FW processor.
|
|
*
|
|
* This function is mandatory.
|
|
*
|
|
* Returns:
|
|
* * 0 on success, or
|
|
* * Any appropriate error on failure.
|
|
*/
|
|
int (*init)(struct pvr_device *pvr_dev);
|
|
|
|
/**
|
|
* @fini:
|
|
*
|
|
* FW processor specific finalisation.
|
|
* @pvr_dev: Target PowerVR device.
|
|
*
|
|
* This function is optional.
|
|
*/
|
|
void (*fini)(struct pvr_device *pvr_dev);
|
|
|
|
/**
|
|
* @fw_process:
|
|
*
|
|
* Load and process firmware image.
|
|
* @pvr_dev: Target PowerVR device.
|
|
* @fw: Pointer to firmware image.
|
|
* @fw_code_ptr: Pointer to firmware code section.
|
|
* @fw_data_ptr: Pointer to firmware data section.
|
|
* @fw_core_code_ptr: Pointer to firmware core code section. May be %NULL.
|
|
* @fw_core_data_ptr: Pointer to firmware core data section. May be %NULL.
|
|
* @core_code_alloc_size: Total allocation size of core code section.
|
|
*
|
|
* This function is mandatory.
|
|
*
|
|
* Returns:
|
|
* * 0 on success, or
|
|
* * Any appropriate error on failure.
|
|
*/
|
|
int (*fw_process)(struct pvr_device *pvr_dev, const u8 *fw,
|
|
u8 *fw_code_ptr, u8 *fw_data_ptr, u8 *fw_core_code_ptr,
|
|
u8 *fw_core_data_ptr, u32 core_code_alloc_size);
|
|
|
|
/**
|
|
* @vm_map:
|
|
*
|
|
* Map FW object into FW processor address space.
|
|
* @pvr_dev: Target PowerVR device.
|
|
* @fw_obj: FW object to map.
|
|
*
|
|
* This function is mandatory.
|
|
*
|
|
* Returns:
|
|
* * 0 on success, or
|
|
* * Any appropriate error on failure.
|
|
*/
|
|
int (*vm_map)(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj);
|
|
|
|
/**
|
|
* @vm_unmap:
|
|
*
|
|
* Unmap FW object from FW processor address space.
|
|
* @pvr_dev: Target PowerVR device.
|
|
* @fw_obj: FW object to map.
|
|
*
|
|
* This function is mandatory.
|
|
*/
|
|
void (*vm_unmap)(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj);
|
|
|
|
/**
|
|
* @get_fw_addr_with_offset:
|
|
*
|
|
* Called to get address of object in firmware address space, with offset.
|
|
* @fw_obj: Pointer to object.
|
|
* @offset: Desired offset from start of object.
|
|
*
|
|
* This function is mandatory.
|
|
*
|
|
* Returns:
|
|
* * Address in firmware address space.
|
|
*/
|
|
u32 (*get_fw_addr_with_offset)(struct pvr_fw_object *fw_obj, u32 offset);
|
|
|
|
/**
|
|
* @wrapper_init:
|
|
*
|
|
* Called to initialise FW wrapper.
|
|
* @pvr_dev: Target PowerVR device.
|
|
*
|
|
* This function is mandatory.
|
|
*
|
|
* Returns:
|
|
* * 0 on success.
|
|
* * Any appropriate error on failure.
|
|
*/
|
|
int (*wrapper_init)(struct pvr_device *pvr_dev);
|
|
|
|
/**
|
|
* @has_fixed_data_addr:
|
|
*
|
|
* Called to check if firmware fixed data must be loaded at the address given by the
|
|
* firmware layout table.
|
|
*
|
|
* This function is mandatory.
|
|
*
|
|
* Returns:
|
|
* * %true if firmware fixed data must be loaded at the address given by the firmware
|
|
* layout table.
|
|
* * %false otherwise.
|
|
*/
|
|
bool (*has_fixed_data_addr)(void);
|
|
|
|
/**
|
|
* @irq: FW Interrupt information.
|
|
*
|
|
* Those are processor dependent, and should be initialized by the
|
|
* processor backend in pvr_fw_funcs::init().
|
|
*/
|
|
struct {
|
|
/** @enable_reg: FW interrupt enable register. */
|
|
u32 enable_reg;
|
|
|
|
/** @status_reg: FW interrupt status register. */
|
|
u32 status_reg;
|
|
|
|
/**
|
|
* @clear_reg: FW interrupt clear register.
|
|
*
|
|
* If @status_reg == @clear_reg, we clear by write a bit to zero,
|
|
* otherwise we clear by writing a bit to one.
|
|
*/
|
|
u32 clear_reg;
|
|
|
|
/** @event_mask: Bitmask of events to listen for. */
|
|
u32 event_mask;
|
|
|
|
/** @clear_mask: Value to write to the clear_reg in order to clear FW IRQs. */
|
|
u32 clear_mask;
|
|
} irq;
|
|
};
|
|
|
|
/**
|
|
* struct pvr_fw_mem - FW memory allocations
|
|
*/
|
|
struct pvr_fw_mem {
|
|
/** @code_obj: Object representing firmware code. */
|
|
struct pvr_fw_object *code_obj;
|
|
|
|
/** @data_obj: Object representing firmware data. */
|
|
struct pvr_fw_object *data_obj;
|
|
|
|
/**
|
|
* @core_code_obj: Object representing firmware core code. May be
|
|
* %NULL if firmware does not contain this section.
|
|
*/
|
|
struct pvr_fw_object *core_code_obj;
|
|
|
|
/**
|
|
* @core_data_obj: Object representing firmware core data. May be
|
|
* %NULL if firmware does not contain this section.
|
|
*/
|
|
struct pvr_fw_object *core_data_obj;
|
|
|
|
/** @code: Driver-side copy of firmware code. */
|
|
u8 *code;
|
|
|
|
/** @data: Driver-side copy of firmware data. */
|
|
u8 *data;
|
|
|
|
/**
|
|
* @core_code: Driver-side copy of firmware core code. May be %NULL if firmware does not
|
|
* contain this section.
|
|
*/
|
|
u8 *core_code;
|
|
|
|
/**
|
|
* @core_data: Driver-side copy of firmware core data. May be %NULL if firmware does not
|
|
* contain this section.
|
|
*/
|
|
u8 *core_data;
|
|
|
|
/** @code_alloc_size: Allocation size of firmware code section. */
|
|
u32 code_alloc_size;
|
|
|
|
/** @data_alloc_size: Allocation size of firmware data section. */
|
|
u32 data_alloc_size;
|
|
|
|
/** @core_code_alloc_size: Allocation size of firmware core code section. */
|
|
u32 core_code_alloc_size;
|
|
|
|
/** @core_data_alloc_size: Allocation size of firmware core data section. */
|
|
u32 core_data_alloc_size;
|
|
|
|
/**
|
|
* @fwif_connection_ctl_obj: Object representing FWIF connection control
|
|
* structure.
|
|
*/
|
|
struct pvr_fw_object *fwif_connection_ctl_obj;
|
|
|
|
/** @osinit_obj: Object representing FW OSINIT structure. */
|
|
struct pvr_fw_object *osinit_obj;
|
|
|
|
/** @sysinit_obj: Object representing FW SYSINIT structure. */
|
|
struct pvr_fw_object *sysinit_obj;
|
|
|
|
/** @osdata_obj: Object representing FW OSDATA structure. */
|
|
struct pvr_fw_object *osdata_obj;
|
|
|
|
/** @hwrinfobuf_obj: Object representing FW hwrinfobuf structure. */
|
|
struct pvr_fw_object *hwrinfobuf_obj;
|
|
|
|
/** @sysdata_obj: Object representing FW SYSDATA structure. */
|
|
struct pvr_fw_object *sysdata_obj;
|
|
|
|
/** @power_sync_obj: Object representing power sync state. */
|
|
struct pvr_fw_object *power_sync_obj;
|
|
|
|
/** @fault_page_obj: Object representing FW fault page. */
|
|
struct pvr_fw_object *fault_page_obj;
|
|
|
|
/** @gpu_util_fwcb_obj: Object representing FW GPU utilisation control structure. */
|
|
struct pvr_fw_object *gpu_util_fwcb_obj;
|
|
|
|
/** @runtime_cfg_obj: Object representing FW runtime config structure. */
|
|
struct pvr_fw_object *runtime_cfg_obj;
|
|
|
|
/** @mmucache_sync_obj: Object used as the sync parameter in an MMU cache operation. */
|
|
struct pvr_fw_object *mmucache_sync_obj;
|
|
};
|
|
|
|
struct pvr_fw_device {
|
|
/** @firmware: Handle to the firmware loaded into the device. */
|
|
const struct firmware *firmware;
|
|
|
|
/** @header: Pointer to firmware header. */
|
|
const struct pvr_fw_info_header *header;
|
|
|
|
/** @layout_entries: Pointer to firmware layout. */
|
|
const struct pvr_fw_layout_entry *layout_entries;
|
|
|
|
/** @mem: Structure containing objects representing firmware memory allocations. */
|
|
struct pvr_fw_mem mem;
|
|
|
|
/** @booted: %true if the firmware has been booted, %false otherwise. */
|
|
bool booted;
|
|
|
|
/**
|
|
* @processor_type: FW processor type for this device. Must be one of
|
|
* %PVR_FW_PROCESSOR_TYPE_*.
|
|
*/
|
|
u16 processor_type;
|
|
|
|
/** @funcs: Function table for the FW processor used by this device. */
|
|
const struct pvr_fw_defs *defs;
|
|
|
|
/** @processor_data: Pointer to data specific to FW processor. */
|
|
union {
|
|
/** @mips_data: Pointer to MIPS-specific data. */
|
|
struct pvr_fw_mips_data *mips_data;
|
|
} processor_data;
|
|
|
|
/** @fw_heap_info: Firmware heap information. */
|
|
struct {
|
|
/** @gpu_addr: Base address of firmware heap in GPU address space. */
|
|
u64 gpu_addr;
|
|
|
|
/** @size: Size of main area of heap. */
|
|
u32 size;
|
|
|
|
/** @offset_mask: Mask for offsets within FW heap. */
|
|
u32 offset_mask;
|
|
|
|
/** @raw_size: Raw size of heap, including reserved areas. */
|
|
u32 raw_size;
|
|
|
|
/** @log2_size: Log2 of raw size of heap. */
|
|
u32 log2_size;
|
|
|
|
/** @config_offset: Offset of config area within heap. */
|
|
u32 config_offset;
|
|
|
|
/** @reserved_size: Size of reserved area in heap. */
|
|
u32 reserved_size;
|
|
} fw_heap_info;
|
|
|
|
/** @fw_mm: Firmware address space allocator. */
|
|
struct drm_mm fw_mm;
|
|
|
|
/** @fw_mm_lock: Lock protecting access to &fw_mm. */
|
|
spinlock_t fw_mm_lock;
|
|
|
|
/** @fw_mm_base: Base address of address space managed by @fw_mm. */
|
|
u64 fw_mm_base;
|
|
|
|
/**
|
|
* @fwif_connection_ctl: Pointer to CPU mapping of FWIF connection
|
|
* control structure.
|
|
*/
|
|
struct rogue_fwif_connection_ctl *fwif_connection_ctl;
|
|
|
|
/** @fwif_sysinit: Pointer to CPU mapping of FW SYSINIT structure. */
|
|
struct rogue_fwif_sysinit *fwif_sysinit;
|
|
|
|
/** @fwif_sysdata: Pointer to CPU mapping of FW SYSDATA structure. */
|
|
struct rogue_fwif_sysdata *fwif_sysdata;
|
|
|
|
/** @fwif_osinit: Pointer to CPU mapping of FW OSINIT structure. */
|
|
struct rogue_fwif_osinit *fwif_osinit;
|
|
|
|
/** @fwif_osdata: Pointer to CPU mapping of FW OSDATA structure. */
|
|
struct rogue_fwif_osdata *fwif_osdata;
|
|
|
|
/** @power_sync: Pointer to CPU mapping of power sync state. */
|
|
u32 *power_sync;
|
|
|
|
/** @hwrinfobuf: Pointer to CPU mapping of FW HWR info buffer. */
|
|
struct rogue_fwif_hwrinfobuf *hwrinfobuf;
|
|
|
|
/** @fw_trace: Device firmware trace buffer state. */
|
|
struct pvr_fw_trace fw_trace;
|
|
|
|
/** @fw_objs: Structure tracking FW objects. */
|
|
struct {
|
|
/** @list: Head of FW object list. */
|
|
struct list_head list;
|
|
|
|
/** @lock: Lock protecting access to FW object list. */
|
|
struct mutex lock;
|
|
} fw_objs;
|
|
};
|
|
|
|
#define pvr_fw_irq_read_reg(pvr_dev, name) \
|
|
pvr_cr_read32((pvr_dev), (pvr_dev)->fw_dev.defs->irq.name ## _reg)
|
|
|
|
#define pvr_fw_irq_write_reg(pvr_dev, name, value) \
|
|
pvr_cr_write32((pvr_dev), (pvr_dev)->fw_dev.defs->irq.name ## _reg, value)
|
|
|
|
#define pvr_fw_irq_pending(pvr_dev) \
|
|
(pvr_fw_irq_read_reg(pvr_dev, status) & (pvr_dev)->fw_dev.defs->irq.event_mask)
|
|
|
|
#define pvr_fw_irq_clear(pvr_dev) \
|
|
pvr_fw_irq_write_reg(pvr_dev, clear, (pvr_dev)->fw_dev.defs->irq.clear_mask)
|
|
|
|
#define pvr_fw_irq_enable(pvr_dev) \
|
|
pvr_fw_irq_write_reg(pvr_dev, enable, (pvr_dev)->fw_dev.defs->irq.event_mask)
|
|
|
|
#define pvr_fw_irq_disable(pvr_dev) \
|
|
pvr_fw_irq_write_reg(pvr_dev, enable, 0)
|
|
|
|
extern const struct pvr_fw_defs pvr_fw_defs_meta;
|
|
extern const struct pvr_fw_defs pvr_fw_defs_mips;
|
|
|
|
int pvr_fw_validate_init_device_info(struct pvr_device *pvr_dev);
|
|
int pvr_fw_init(struct pvr_device *pvr_dev);
|
|
void pvr_fw_fini(struct pvr_device *pvr_dev);
|
|
|
|
int pvr_wait_for_fw_boot(struct pvr_device *pvr_dev);
|
|
|
|
int
|
|
pvr_fw_hard_reset(struct pvr_device *pvr_dev);
|
|
|
|
void pvr_fw_mts_schedule(struct pvr_device *pvr_dev, u32 val);
|
|
|
|
void
|
|
pvr_fw_heap_info_init(struct pvr_device *pvr_dev, u32 log2_size, u32 reserved_size);
|
|
|
|
const struct pvr_fw_layout_entry *
|
|
pvr_fw_find_layout_entry(struct pvr_device *pvr_dev, enum pvr_fw_section_id id);
|
|
int
|
|
pvr_fw_find_mmu_segment(struct pvr_device *pvr_dev, u32 addr, u32 size, void *fw_code_ptr,
|
|
void *fw_data_ptr, void *fw_core_code_ptr, void *fw_core_data_ptr,
|
|
void **host_addr_out);
|
|
|
|
int
|
|
pvr_fw_structure_cleanup(struct pvr_device *pvr_dev, u32 type, struct pvr_fw_object *fw_obj,
|
|
u32 offset);
|
|
|
|
int pvr_fw_object_create(struct pvr_device *pvr_dev, size_t size, u64 flags,
|
|
void (*init)(void *cpu_ptr, void *priv), void *init_priv,
|
|
struct pvr_fw_object **pvr_obj_out);
|
|
|
|
void *pvr_fw_object_create_and_map(struct pvr_device *pvr_dev, size_t size, u64 flags,
|
|
void (*init)(void *cpu_ptr, void *priv),
|
|
void *init_priv, struct pvr_fw_object **pvr_obj_out);
|
|
|
|
void *
|
|
pvr_fw_object_create_and_map_offset(struct pvr_device *pvr_dev, u32 dev_offset, size_t size,
|
|
u64 flags, void (*init)(void *cpu_ptr, void *priv),
|
|
void *init_priv, struct pvr_fw_object **pvr_obj_out);
|
|
|
|
static __always_inline void *
|
|
pvr_fw_object_vmap(struct pvr_fw_object *fw_obj)
|
|
{
|
|
return pvr_gem_object_vmap(fw_obj->gem);
|
|
}
|
|
|
|
static __always_inline void
|
|
pvr_fw_object_vunmap(struct pvr_fw_object *fw_obj)
|
|
{
|
|
pvr_gem_object_vunmap(fw_obj->gem);
|
|
}
|
|
|
|
void pvr_fw_object_destroy(struct pvr_fw_object *fw_obj);
|
|
|
|
static __always_inline void
|
|
pvr_fw_object_unmap_and_destroy(struct pvr_fw_object *fw_obj)
|
|
{
|
|
pvr_fw_object_vunmap(fw_obj);
|
|
pvr_fw_object_destroy(fw_obj);
|
|
}
|
|
|
|
/**
|
|
* pvr_fw_object_get_dma_addr() - Get DMA address for given offset in firmware
|
|
* object.
|
|
* @fw_obj: Pointer to object to lookup address in.
|
|
* @offset: Offset within object to lookup address at.
|
|
* @dma_addr_out: Pointer to location to store DMA address.
|
|
*
|
|
* Returns:
|
|
* * 0 on success, or
|
|
* * -%EINVAL if object is not currently backed, or if @offset is out of valid
|
|
* range for this object.
|
|
*/
|
|
static __always_inline int
|
|
pvr_fw_object_get_dma_addr(struct pvr_fw_object *fw_obj, u32 offset, dma_addr_t *dma_addr_out)
|
|
{
|
|
return pvr_gem_get_dma_addr(fw_obj->gem, offset, dma_addr_out);
|
|
}
|
|
|
|
void pvr_fw_object_get_fw_addr_offset(struct pvr_fw_object *fw_obj, u32 offset, u32 *fw_addr_out);
|
|
|
|
static __always_inline void
|
|
pvr_fw_object_get_fw_addr(struct pvr_fw_object *fw_obj, u32 *fw_addr_out)
|
|
{
|
|
pvr_fw_object_get_fw_addr_offset(fw_obj, 0, fw_addr_out);
|
|
}
|
|
|
|
#endif /* PVR_FW_H */
|