]> Git Repo - linux.git/blob - drivers/gpu/drm/i915/soc/intel_rom.c
Linux 6.14-rc3
[linux.git] / drivers / gpu / drm / i915 / soc / intel_rom.c
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_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
67 static u32 pci_read32(struct intel_rom *rom, loff_t offset)
68 {
69         return ioread32(rom->oprom + offset);
70 }
71
72 static u16 pci_read16(struct intel_rom *rom, loff_t offset)
73 {
74         return ioread16(rom->oprom + offset);
75 }
76
77 static 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
83 static void pci_free(struct intel_rom *rom)
84 {
85         pci_unmap_rom(rom->pdev, rom->oprom);
86 }
87
88 struct 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
112 u32 intel_rom_read32(struct intel_rom *rom, loff_t offset)
113 {
114         return rom->read32(rom, offset);
115 }
116
117 u16 intel_rom_read16(struct intel_rom *rom, loff_t offset)
118 {
119         return rom->read16(rom, offset);
120 }
121
122 void 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
137 loff_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
149 size_t intel_rom_size(struct intel_rom *rom)
150 {
151         return rom->size;
152 }
153
154 void intel_rom_free(struct intel_rom *rom)
155 {
156         if (rom && rom->free)
157                 rom->free(rom);
158
159         kfree(rom);
160 }
This page took 0.043557 seconds and 4 git commands to generate.