JustOS/linux-6.13/drivers/gpu/drm/i915/soc/intel_rom.c
justuser 02e73b8cd9 up
2025-01-24 17:00:19 +03:00

161 lines
3.1 KiB
C

// SPDX-License-Identifier: MIT
/*
* Copyright © 2024 Intel Corporation
*/
#include "i915_drv.h"
#include "i915_reg.h"
#include "intel_rom.h"
#include "intel_uncore.h"
struct intel_rom {
/* for PCI ROM */
struct pci_dev *pdev;
void __iomem *oprom;
/* for SPI */
struct intel_uncore *uncore;
loff_t offset;
size_t size;
u32 (*read32)(struct intel_rom *rom, loff_t offset);
u16 (*read16)(struct intel_rom *rom, loff_t offset);
void (*read_block)(struct intel_rom *rom, void *data, loff_t offset, size_t size);
void (*free)(struct intel_rom *rom);
};
static u32 spi_read32(struct intel_rom *rom, loff_t offset)
{
intel_uncore_write(rom->uncore, PRIMARY_SPI_ADDRESS,
rom->offset + offset);
return intel_uncore_read(rom->uncore, PRIMARY_SPI_TRIGGER);
}
static u16 spi_read16(struct intel_rom *rom, loff_t offset)
{
return spi_read32(rom, offset) & 0xffff;
}
struct intel_rom *intel_rom_spi(struct drm_i915_private *i915)
{
struct intel_rom *rom;
u32 static_region;
rom = kzalloc(sizeof(*rom), GFP_KERNEL);
if (!rom)
return NULL;
rom->uncore = &i915->uncore;
static_region = intel_uncore_read(rom->uncore, SPI_STATIC_REGIONS);
static_region &= OPTIONROM_SPI_REGIONID_MASK;
intel_uncore_write(rom->uncore, PRIMARY_SPI_REGIONID, static_region);
rom->offset = intel_uncore_read(rom->uncore, OROM_OFFSET) & OROM_OFFSET_MASK;
rom->size = 0x200000;
rom->read32 = spi_read32;
rom->read16 = spi_read16;
return rom;
}
static u32 pci_read32(struct intel_rom *rom, loff_t offset)
{
return ioread32(rom->oprom + offset);
}
static u16 pci_read16(struct intel_rom *rom, loff_t offset)
{
return ioread16(rom->oprom + offset);
}
static void pci_read_block(struct intel_rom *rom, void *data,
loff_t offset, size_t size)
{
memcpy_fromio(data, rom->oprom + offset, size);
}
static void pci_free(struct intel_rom *rom)
{
pci_unmap_rom(rom->pdev, rom->oprom);
}
struct intel_rom *intel_rom_pci(struct drm_i915_private *i915)
{
struct intel_rom *rom;
rom = kzalloc(sizeof(*rom), GFP_KERNEL);
if (!rom)
return NULL;
rom->pdev = to_pci_dev(i915->drm.dev);
rom->oprom = pci_map_rom(rom->pdev, &rom->size);
if (!rom->oprom) {
kfree(rom);
return NULL;
}
rom->read32 = pci_read32;
rom->read16 = pci_read16;
rom->read_block = pci_read_block;
rom->free = pci_free;
return rom;
}
u32 intel_rom_read32(struct intel_rom *rom, loff_t offset)
{
return rom->read32(rom, offset);
}
u16 intel_rom_read16(struct intel_rom *rom, loff_t offset)
{
return rom->read16(rom, offset);
}
void intel_rom_read_block(struct intel_rom *rom, void *data,
loff_t offset, size_t size)
{
u32 *ptr = data;
loff_t index;
if (rom->read_block) {
rom->read_block(rom, data, offset, size);
return;
}
for (index = 0; index < size; index += 4)
*ptr++ = rom->read32(rom, offset + index);
}
loff_t intel_rom_find(struct intel_rom *rom, u32 needle)
{
loff_t offset;
for (offset = 0; offset < rom->size; offset += 4) {
if (rom->read32(rom, offset) == needle)
return offset;
}
return -ENOENT;
}
size_t intel_rom_size(struct intel_rom *rom)
{
return rom->size;
}
void intel_rom_free(struct intel_rom *rom)
{
if (rom && rom->free)
rom->free(rom);
kfree(rom);
}