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