Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2024 Intel Corporation
  4 */
  5
  6#include "i915_drv.h"
  7#include "i915_reg.h"
  8
  9#include "intel_rom.h"
 10#include "intel_uncore.h"
 11
 12struct intel_rom {
 13	/* for PCI ROM */
 14	struct pci_dev *pdev;
 15	void __iomem *oprom;
 16
 17	/* for SPI */
 18	struct intel_uncore *uncore;
 19	loff_t offset;
 20
 21	size_t size;
 22
 23	u32 (*read32)(struct intel_rom *rom, loff_t offset);
 24	u16 (*read16)(struct intel_rom *rom, loff_t offset);
 25	void (*read_block)(struct intel_rom *rom, void *data, loff_t offset, size_t size);
 26	void (*free)(struct intel_rom *rom);
 27};
 28
 29static u32 spi_read32(struct intel_rom *rom, loff_t offset)
 30{
 31	intel_uncore_write(rom->uncore, PRIMARY_SPI_ADDRESS,
 32			   rom->offset + offset);
 33
 34	return intel_uncore_read(rom->uncore, PRIMARY_SPI_TRIGGER);
 35}
 36
 37static u16 spi_read16(struct intel_rom *rom, loff_t offset)
 38{
 39	return spi_read32(rom, offset) & 0xffff;
 40}
 41
 42struct intel_rom *intel_rom_spi(struct drm_i915_private *i915)
 43{
 44	struct intel_rom *rom;
 45	u32 static_region;
 46
 47	rom = kzalloc(sizeof(*rom), GFP_KERNEL);
 48	if (!rom)
 49		return NULL;
 50
 51	rom->uncore = &i915->uncore;
 52
 53	static_region = intel_uncore_read(rom->uncore, SPI_STATIC_REGIONS);
 54	static_region &= OPTIONROM_SPI_REGIONID_MASK;
 55	intel_uncore_write(rom->uncore, PRIMARY_SPI_REGIONID, static_region);
 56
 57	rom->offset = intel_uncore_read(rom->uncore, OROM_OFFSET) & OROM_OFFSET_MASK;
 58
 59	rom->size = 0x200000;
 60
 61	rom->read32 = spi_read32;
 62	rom->read16 = spi_read16;
 63
 64	return rom;
 65}
 66
 67static u32 pci_read32(struct intel_rom *rom, loff_t offset)
 68{
 69	return ioread32(rom->oprom + offset);
 70}
 71
 72static u16 pci_read16(struct intel_rom *rom, loff_t offset)
 73{
 74	return ioread16(rom->oprom + offset);
 75}
 76
 77static void pci_read_block(struct intel_rom *rom, void *data,
 78			   loff_t offset, size_t size)
 79{
 80	memcpy_fromio(data, rom->oprom + offset, size);
 81}
 82
 83static void pci_free(struct intel_rom *rom)
 84{
 85	pci_unmap_rom(rom->pdev, rom->oprom);
 86}
 87
 88struct intel_rom *intel_rom_pci(struct drm_i915_private *i915)
 89{
 90	struct intel_rom *rom;
 91
 92	rom = kzalloc(sizeof(*rom), GFP_KERNEL);
 93	if (!rom)
 94		return NULL;
 95
 96	rom->pdev = to_pci_dev(i915->drm.dev);
 97
 98	rom->oprom = pci_map_rom(rom->pdev, &rom->size);
 99	if (!rom->oprom) {
100		kfree(rom);
101		return NULL;
102	}
103
104	rom->read32 = pci_read32;
105	rom->read16 = pci_read16;
106	rom->read_block = pci_read_block;
107	rom->free = pci_free;
108
109	return rom;
110}
111
112u32 intel_rom_read32(struct intel_rom *rom, loff_t offset)
113{
114	return rom->read32(rom, offset);
115}
116
117u16 intel_rom_read16(struct intel_rom *rom, loff_t offset)
118{
119	return rom->read16(rom, offset);
120}
121
122void intel_rom_read_block(struct intel_rom *rom, void *data,
123			  loff_t offset, size_t size)
124{
125	u32 *ptr = data;
126	loff_t index;
127
128	if (rom->read_block) {
129		rom->read_block(rom, data, offset, size);
130		return;
131	}
132
133	for (index = 0; index < size; index += 4)
134		*ptr++ = rom->read32(rom, offset + index);
135}
136
137loff_t intel_rom_find(struct intel_rom *rom, u32 needle)
138{
139	loff_t offset;
140
141	for (offset = 0; offset < rom->size; offset += 4) {
142		if (rom->read32(rom, offset) == needle)
143			return offset;
144	}
145
146	return -ENOENT;
147}
148
149size_t intel_rom_size(struct intel_rom *rom)
150{
151	return rom->size;
152}
153
154void intel_rom_free(struct intel_rom *rom)
155{
156	if (rom && rom->free)
157		rom->free(rom);
158
159	kfree(rom);
160}