xref: /linux/drivers/gpu/drm/i915/soc/intel_rom.c (revision c31f4aa8fed048fa70e742c4bb49bb48dc489ab3)
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 
12 struct 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 
29 static 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 
37 static u16 spi_read16(struct intel_rom *rom, loff_t offset)
38 {
39 	return spi_read32(rom, offset) & 0xffff;
40 }
41 
42 struct intel_rom *intel_rom_spi(struct drm_device *drm)
43 {
44 	struct drm_i915_private *i915 = to_i915(drm);
45 	struct intel_rom *rom;
46 	u32 static_region;
47 
48 	rom = kzalloc(sizeof(*rom), GFP_KERNEL);
49 	if (!rom)
50 		return NULL;
51 
52 	rom->uncore = &i915->uncore;
53 
54 	static_region = intel_uncore_read(rom->uncore, SPI_STATIC_REGIONS);
55 	static_region &= OPTIONROM_SPI_REGIONID_MASK;
56 	intel_uncore_write(rom->uncore, PRIMARY_SPI_REGIONID, static_region);
57 
58 	rom->offset = intel_uncore_read(rom->uncore, OROM_OFFSET) & OROM_OFFSET_MASK;
59 
60 	rom->size = 0x200000;
61 
62 	rom->read32 = spi_read32;
63 	rom->read16 = spi_read16;
64 
65 	return rom;
66 }
67 
68 static u32 pci_read32(struct intel_rom *rom, loff_t offset)
69 {
70 	return ioread32(rom->oprom + offset);
71 }
72 
73 static u16 pci_read16(struct intel_rom *rom, loff_t offset)
74 {
75 	return ioread16(rom->oprom + offset);
76 }
77 
78 static void pci_read_block(struct intel_rom *rom, void *data,
79 			   loff_t offset, size_t size)
80 {
81 	memcpy_fromio(data, rom->oprom + offset, size);
82 }
83 
84 static void pci_free(struct intel_rom *rom)
85 {
86 	pci_unmap_rom(rom->pdev, rom->oprom);
87 }
88 
89 struct intel_rom *intel_rom_pci(struct drm_device *drm)
90 {
91 	struct intel_rom *rom;
92 
93 	rom = kzalloc(sizeof(*rom), GFP_KERNEL);
94 	if (!rom)
95 		return NULL;
96 
97 	rom->pdev = to_pci_dev(drm->dev);
98 
99 	rom->oprom = pci_map_rom(rom->pdev, &rom->size);
100 	if (!rom->oprom) {
101 		kfree(rom);
102 		return NULL;
103 	}
104 
105 	rom->read32 = pci_read32;
106 	rom->read16 = pci_read16;
107 	rom->read_block = pci_read_block;
108 	rom->free = pci_free;
109 
110 	return rom;
111 }
112 
113 u32 intel_rom_read32(struct intel_rom *rom, loff_t offset)
114 {
115 	return rom->read32(rom, offset);
116 }
117 
118 u16 intel_rom_read16(struct intel_rom *rom, loff_t offset)
119 {
120 	return rom->read16(rom, offset);
121 }
122 
123 void intel_rom_read_block(struct intel_rom *rom, void *data,
124 			  loff_t offset, size_t size)
125 {
126 	u32 *ptr = data;
127 	loff_t index;
128 
129 	if (rom->read_block) {
130 		rom->read_block(rom, data, offset, size);
131 		return;
132 	}
133 
134 	for (index = 0; index < size; index += 4)
135 		*ptr++ = rom->read32(rom, offset + index);
136 }
137 
138 loff_t intel_rom_find(struct intel_rom *rom, u32 needle)
139 {
140 	loff_t offset;
141 
142 	for (offset = 0; offset < rom->size; offset += 4) {
143 		if (rom->read32(rom, offset) == needle)
144 			return offset;
145 	}
146 
147 	return -ENOENT;
148 }
149 
150 size_t intel_rom_size(struct intel_rom *rom)
151 {
152 	return rom->size;
153 }
154 
155 void intel_rom_free(struct intel_rom *rom)
156 {
157 	if (rom && rom->free)
158 		rom->free(rom);
159 
160 	kfree(rom);
161 }
162