1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
// 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);
}
|