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