Commit 14a43e69ed257a1fadadf9fea2c05adb1686419f
1 parent
817c21ad9a
Exists in
master
and in
20 other branches
powerpc/powernv: Basic support for OPAL
Add definition of OPAL interfaces along with the wrappers to call into OPAL runtime and the early device-tree parsing hook to locate the OPAL runtime firmware. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Showing 9 changed files with 691 additions and 5 deletions Side-by-side Diff
- arch/powerpc/include/asm/firmware.h
- arch/powerpc/include/asm/opal.h
- arch/powerpc/kernel/prom.c
- arch/powerpc/platforms/powernv/Kconfig
- arch/powerpc/platforms/powernv/Makefile
- arch/powerpc/platforms/powernv/opal-wrappers.S
- arch/powerpc/platforms/powernv/opal.c
- arch/powerpc/platforms/powernv/setup.c
- arch/powerpc/platforms/powernv/smp.c
arch/powerpc/include/asm/firmware.h
... | ... | @@ -48,6 +48,8 @@ |
48 | 48 | #define FW_FEATURE_CMO ASM_CONST(0x0000000002000000) |
49 | 49 | #define FW_FEATURE_VPHN ASM_CONST(0x0000000004000000) |
50 | 50 | #define FW_FEATURE_XCMO ASM_CONST(0x0000000008000000) |
51 | +#define FW_FEATURE_OPAL ASM_CONST(0x0000000010000000) | |
52 | +#define FW_FEATURE_OPALv2 ASM_CONST(0x0000000020000000) | |
51 | 53 | |
52 | 54 | #ifndef __ASSEMBLY__ |
53 | 55 | |
... | ... | @@ -65,6 +67,8 @@ |
65 | 67 | FW_FEATURE_PSERIES_ALWAYS = 0, |
66 | 68 | FW_FEATURE_ISERIES_POSSIBLE = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, |
67 | 69 | FW_FEATURE_ISERIES_ALWAYS = FW_FEATURE_ISERIES | FW_FEATURE_LPAR, |
70 | + FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_OPALv2, | |
71 | + FW_FEATURE_POWERNV_ALWAYS = 0, | |
68 | 72 | FW_FEATURE_PS3_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1, |
69 | 73 | FW_FEATURE_PS3_ALWAYS = FW_FEATURE_LPAR | FW_FEATURE_PS3_LV1, |
70 | 74 | FW_FEATURE_CELLEB_POSSIBLE = FW_FEATURE_LPAR | FW_FEATURE_BEAT, |
... | ... | @@ -78,6 +82,9 @@ |
78 | 82 | #ifdef CONFIG_PPC_ISERIES |
79 | 83 | FW_FEATURE_ISERIES_POSSIBLE | |
80 | 84 | #endif |
85 | +#ifdef CONFIG_PPC_POWERNV | |
86 | + FW_FEATURE_POWERNV_POSSIBLE | | |
87 | +#endif | |
81 | 88 | #ifdef CONFIG_PPC_PS3 |
82 | 89 | FW_FEATURE_PS3_POSSIBLE | |
83 | 90 | #endif |
... | ... | @@ -94,6 +101,9 @@ |
94 | 101 | #endif |
95 | 102 | #ifdef CONFIG_PPC_ISERIES |
96 | 103 | FW_FEATURE_ISERIES_ALWAYS & |
104 | +#endif | |
105 | +#ifdef CONFIG_PPC_POWERNV | |
106 | + FW_FEATURE_POWERNV_ALWAYS & | |
97 | 107 | #endif |
98 | 108 | #ifdef CONFIG_PPC_PS3 |
99 | 109 | FW_FEATURE_PS3_ALWAYS & |
arch/powerpc/include/asm/opal.h
... | ... | @@ -37,15 +37,395 @@ |
37 | 37 | |
38 | 38 | extern long opal_do_takeover(struct opal_takeover_args *args); |
39 | 39 | |
40 | +struct rtas_args; | |
40 | 41 | extern int opal_enter_rtas(struct rtas_args *args, |
41 | 42 | unsigned long data, |
42 | 43 | unsigned long entry); |
43 | 44 | |
44 | - | |
45 | 45 | #endif /* __ASSEMBLY__ */ |
46 | 46 | |
47 | 47 | /****** OPAL APIs ******/ |
48 | 48 | |
49 | +/* Return codes */ | |
50 | +#define OPAL_SUCCESS 0 | |
51 | +#define OPAL_PARAMETER -1 | |
52 | +#define OPAL_BUSY -2 | |
53 | +#define OPAL_PARTIAL -3 | |
54 | +#define OPAL_CONSTRAINED -4 | |
55 | +#define OPAL_CLOSED -5 | |
56 | +#define OPAL_HARDWARE -6 | |
57 | +#define OPAL_UNSUPPORTED -7 | |
58 | +#define OPAL_PERMISSION -8 | |
59 | +#define OPAL_NO_MEM -9 | |
60 | +#define OPAL_RESOURCE -10 | |
61 | +#define OPAL_INTERNAL_ERROR -11 | |
62 | +#define OPAL_BUSY_EVENT -12 | |
63 | +#define OPAL_HARDWARE_FROZEN -13 | |
64 | + | |
65 | +/* API Tokens (in r0) */ | |
66 | +#define OPAL_CONSOLE_WRITE 1 | |
67 | +#define OPAL_CONSOLE_READ 2 | |
68 | +#define OPAL_RTC_READ 3 | |
69 | +#define OPAL_RTC_WRITE 4 | |
70 | +#define OPAL_CEC_POWER_DOWN 5 | |
71 | +#define OPAL_CEC_REBOOT 6 | |
72 | +#define OPAL_READ_NVRAM 7 | |
73 | +#define OPAL_WRITE_NVRAM 8 | |
74 | +#define OPAL_HANDLE_INTERRUPT 9 | |
75 | +#define OPAL_POLL_EVENTS 10 | |
76 | +#define OPAL_PCI_SET_HUB_TCE_MEMORY 11 | |
77 | +#define OPAL_PCI_SET_PHB_TCE_MEMORY 12 | |
78 | +#define OPAL_PCI_CONFIG_READ_BYTE 13 | |
79 | +#define OPAL_PCI_CONFIG_READ_HALF_WORD 14 | |
80 | +#define OPAL_PCI_CONFIG_READ_WORD 15 | |
81 | +#define OPAL_PCI_CONFIG_WRITE_BYTE 16 | |
82 | +#define OPAL_PCI_CONFIG_WRITE_HALF_WORD 17 | |
83 | +#define OPAL_PCI_CONFIG_WRITE_WORD 18 | |
84 | +#define OPAL_SET_XIVE 19 | |
85 | +#define OPAL_GET_XIVE 20 | |
86 | +#define OPAL_GET_COMPLETION_TOKEN_STATUS 21 /* obsolete */ | |
87 | +#define OPAL_REGISTER_OPAL_EXCEPTION_HANDLER 22 | |
88 | +#define OPAL_PCI_EEH_FREEZE_STATUS 23 | |
89 | +#define OPAL_PCI_SHPC 24 | |
90 | +#define OPAL_CONSOLE_WRITE_BUFFER_SPACE 25 | |
91 | +#define OPAL_PCI_EEH_FREEZE_CLEAR 26 | |
92 | +#define OPAL_PCI_PHB_MMIO_ENABLE 27 | |
93 | +#define OPAL_PCI_SET_PHB_MEM_WINDOW 28 | |
94 | +#define OPAL_PCI_MAP_PE_MMIO_WINDOW 29 | |
95 | +#define OPAL_PCI_SET_PHB_TABLE_MEMORY 30 | |
96 | +#define OPAL_PCI_SET_PE 31 | |
97 | +#define OPAL_PCI_SET_PELTV 32 | |
98 | +#define OPAL_PCI_SET_MVE 33 | |
99 | +#define OPAL_PCI_SET_MVE_ENABLE 34 | |
100 | +#define OPAL_PCI_GET_XIVE_REISSUE 35 | |
101 | +#define OPAL_PCI_SET_XIVE_REISSUE 36 | |
102 | +#define OPAL_PCI_SET_XIVE_PE 37 | |
103 | +#define OPAL_GET_XIVE_SOURCE 38 | |
104 | +#define OPAL_GET_MSI_32 39 | |
105 | +#define OPAL_GET_MSI_64 40 | |
106 | +#define OPAL_START_CPU 41 | |
107 | +#define OPAL_QUERY_CPU_STATUS 42 | |
108 | +#define OPAL_WRITE_OPPANEL 43 | |
109 | +#define OPAL_PCI_MAP_PE_DMA_WINDOW 44 | |
110 | +#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45 | |
111 | +#define OPAL_PCI_RESET 49 | |
112 | + | |
113 | +#ifndef __ASSEMBLY__ | |
114 | + | |
115 | +/* Other enums */ | |
116 | +enum OpalVendorApiTokens { | |
117 | + OPAL_START_VENDOR_API_RANGE = 1000, OPAL_END_VENDOR_API_RANGE = 1999 | |
118 | +}; | |
119 | +enum OpalFreezeState { | |
120 | + OPAL_EEH_STOPPED_NOT_FROZEN = 0, | |
121 | + OPAL_EEH_STOPPED_MMIO_FREEZE = 1, | |
122 | + OPAL_EEH_STOPPED_DMA_FREEZE = 2, | |
123 | + OPAL_EEH_STOPPED_MMIO_DMA_FREEZE = 3, | |
124 | + OPAL_EEH_STOPPED_RESET = 4, | |
125 | + OPAL_EEH_STOPPED_TEMP_UNAVAIL = 5, | |
126 | + OPAL_EEH_STOPPED_PERM_UNAVAIL = 6 | |
127 | +}; | |
128 | +enum OpalEehFreezeActionToken { | |
129 | + OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1, | |
130 | + OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2, | |
131 | + OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3 | |
132 | +}; | |
133 | +enum OpalPciStatusToken { | |
134 | + OPAL_EEH_PHB_NO_ERROR = 0, | |
135 | + OPAL_EEH_PHB_FATAL = 1, | |
136 | + OPAL_EEH_PHB_RECOVERABLE = 2, | |
137 | + OPAL_EEH_PHB_BUS_ERROR = 3, | |
138 | + OPAL_EEH_PCI_NO_DEVSEL = 4, | |
139 | + OPAL_EEH_PCI_TA = 5, | |
140 | + OPAL_EEH_PCIEX_UR = 6, | |
141 | + OPAL_EEH_PCIEX_CA = 7, | |
142 | + OPAL_EEH_PCI_MMIO_ERROR = 8, | |
143 | + OPAL_EEH_PCI_DMA_ERROR = 9 | |
144 | +}; | |
145 | +enum OpalShpcAction { | |
146 | + OPAL_SHPC_GET_LINK_STATE = 0, | |
147 | + OPAL_SHPC_GET_SLOT_STATE = 1 | |
148 | +}; | |
149 | +enum OpalShpcLinkState { | |
150 | + OPAL_SHPC_LINK_DOWN = 0, | |
151 | + OPAL_SHPC_LINK_UP = 1 | |
152 | +}; | |
153 | +enum OpalMmioWindowType { | |
154 | + OPAL_M32_WINDOW_TYPE = 1, | |
155 | + OPAL_M64_WINDOW_TYPE = 2, | |
156 | + OPAL_IO_WINDOW_TYPE = 3 | |
157 | +}; | |
158 | +enum OpalShpcSlotState { | |
159 | + OPAL_SHPC_DEV_NOT_PRESENT = 0, | |
160 | + OPAL_SHPC_DEV_PRESENT = 1 | |
161 | +}; | |
162 | +enum OpalExceptionHandler { | |
163 | + OPAL_MACHINE_CHECK_HANDLER = 1, | |
164 | + OPAL_HYPERVISOR_MAINTENANCE_HANDLER = 2, | |
165 | + OPAL_SOFTPATCH_HANDLER = 3 | |
166 | +}; | |
167 | +enum OpalPendingState { | |
168 | + OPAL_EVENT_OPAL_INTERNAL = 0x1, | |
169 | + OPAL_EVENT_NVRAM = 0x2, | |
170 | + OPAL_EVENT_RTC = 0x4, | |
171 | + OPAL_EVENT_CONSOLE_OUTPUT = 0x8, | |
172 | + OPAL_EVENT_CONSOLE_INPUT = 0x10 | |
173 | +}; | |
174 | + | |
175 | +/* Machine check related definitions */ | |
176 | +enum OpalMCE_Version { | |
177 | + OpalMCE_V1 = 1, | |
178 | +}; | |
179 | + | |
180 | +enum OpalMCE_Severity { | |
181 | + OpalMCE_SEV_NO_ERROR = 0, | |
182 | + OpalMCE_SEV_WARNING = 1, | |
183 | + OpalMCE_SEV_ERROR_SYNC = 2, | |
184 | + OpalMCE_SEV_FATAL = 3, | |
185 | +}; | |
186 | + | |
187 | +enum OpalMCE_Disposition { | |
188 | + OpalMCE_DISPOSITION_RECOVERED = 0, | |
189 | + OpalMCE_DISPOSITION_NOT_RECOVERED = 1, | |
190 | +}; | |
191 | + | |
192 | +enum OpalMCE_Initiator { | |
193 | + OpalMCE_INITIATOR_UNKNOWN = 0, | |
194 | + OpalMCE_INITIATOR_CPU = 1, | |
195 | +}; | |
196 | + | |
197 | +enum OpalMCE_ErrorType { | |
198 | + OpalMCE_ERROR_TYPE_UNKNOWN = 0, | |
199 | + OpalMCE_ERROR_TYPE_UE = 1, | |
200 | + OpalMCE_ERROR_TYPE_SLB = 2, | |
201 | + OpalMCE_ERROR_TYPE_ERAT = 3, | |
202 | + OpalMCE_ERROR_TYPE_TLB = 4, | |
203 | +}; | |
204 | + | |
205 | +enum OpalMCE_UeErrorType { | |
206 | + OpalMCE_UE_ERROR_INDETERMINATE = 0, | |
207 | + OpalMCE_UE_ERROR_IFETCH = 1, | |
208 | + OpalMCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH = 2, | |
209 | + OpalMCE_UE_ERROR_LOAD_STORE = 3, | |
210 | + OpalMCE_UE_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 4, | |
211 | +}; | |
212 | + | |
213 | +enum OpalMCE_SlbErrorType { | |
214 | + OpalMCE_SLB_ERROR_INDETERMINATE = 0, | |
215 | + OpalMCE_SLB_ERROR_PARITY = 1, | |
216 | + OpalMCE_SLB_ERROR_MULTIHIT = 2, | |
217 | +}; | |
218 | + | |
219 | +enum OpalMCE_EratErrorType { | |
220 | + OpalMCE_ERAT_ERROR_INDETERMINATE = 0, | |
221 | + OpalMCE_ERAT_ERROR_PARITY = 1, | |
222 | + OpalMCE_ERAT_ERROR_MULTIHIT = 2, | |
223 | +}; | |
224 | + | |
225 | +enum OpalMCE_TlbErrorType { | |
226 | + OpalMCE_TLB_ERROR_INDETERMINATE = 0, | |
227 | + OpalMCE_TLB_ERROR_PARITY = 1, | |
228 | + OpalMCE_TLB_ERROR_MULTIHIT = 2, | |
229 | +}; | |
230 | + | |
231 | +enum OpalThreadStatus { | |
232 | + OPAL_THREAD_INACTIVE = 0x0, | |
233 | + OPAL_THREAD_STARTED = 0x1 | |
234 | +}; | |
235 | + | |
236 | +enum OpalPciBusCompare { | |
237 | + OpalPciBusAny = 0, /* Any bus number match */ | |
238 | + OpalPciBus3Bits = 2, /* Match top 3 bits of bus number */ | |
239 | + OpalPciBus4Bits = 3, /* Match top 4 bits of bus number */ | |
240 | + OpalPciBus5Bits = 4, /* Match top 5 bits of bus number */ | |
241 | + OpalPciBus6Bits = 5, /* Match top 6 bits of bus number */ | |
242 | + OpalPciBus7Bits = 6, /* Match top 7 bits of bus number */ | |
243 | + OpalPciBusAll = 7, /* Match bus number exactly */ | |
244 | +}; | |
245 | + | |
246 | +enum OpalDeviceCompare { | |
247 | + OPAL_IGNORE_RID_DEVICE_NUMBER = 0, | |
248 | + OPAL_COMPARE_RID_DEVICE_NUMBER = 1 | |
249 | +}; | |
250 | + | |
251 | +enum OpalFuncCompare { | |
252 | + OPAL_IGNORE_RID_FUNCTION_NUMBER = 0, | |
253 | + OPAL_COMPARE_RID_FUNCTION_NUMBER = 1 | |
254 | +}; | |
255 | + | |
256 | +enum OpalPeAction { | |
257 | + OPAL_UNMAP_PE = 0, | |
258 | + OPAL_MAP_PE = 1 | |
259 | +}; | |
260 | + | |
261 | +enum OpalPciResetAndReinitScope { | |
262 | + OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3, | |
263 | + OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5, | |
264 | + OPAL_PCI_IODA_RESET = 6, | |
265 | +}; | |
266 | + | |
267 | +enum OpalPciResetState { OPAL_DEASSERT_RESET = 0, OPAL_ASSERT_RESET = 1 }; | |
268 | + | |
269 | +struct opal_machine_check_event { | |
270 | + enum OpalMCE_Version version:8; /* 0x00 */ | |
271 | + uint8_t in_use; /* 0x01 */ | |
272 | + enum OpalMCE_Severity severity:8; /* 0x02 */ | |
273 | + enum OpalMCE_Initiator initiator:8; /* 0x03 */ | |
274 | + enum OpalMCE_ErrorType error_type:8; /* 0x04 */ | |
275 | + enum OpalMCE_Disposition disposition:8; /* 0x05 */ | |
276 | + uint8_t reserved_1[2]; /* 0x06 */ | |
277 | + uint64_t gpr3; /* 0x08 */ | |
278 | + uint64_t srr0; /* 0x10 */ | |
279 | + uint64_t srr1; /* 0x18 */ | |
280 | + union { /* 0x20 */ | |
281 | + struct { | |
282 | + enum OpalMCE_UeErrorType ue_error_type:8; | |
283 | + uint8_t effective_address_provided; | |
284 | + uint8_t physical_address_provided; | |
285 | + uint8_t reserved_1[5]; | |
286 | + uint64_t effective_address; | |
287 | + uint64_t physical_address; | |
288 | + uint8_t reserved_2[8]; | |
289 | + } ue_error; | |
290 | + | |
291 | + struct { | |
292 | + enum OpalMCE_SlbErrorType slb_error_type:8; | |
293 | + uint8_t effective_address_provided; | |
294 | + uint8_t reserved_1[6]; | |
295 | + uint64_t effective_address; | |
296 | + uint8_t reserved_2[16]; | |
297 | + } slb_error; | |
298 | + | |
299 | + struct { | |
300 | + enum OpalMCE_EratErrorType erat_error_type:8; | |
301 | + uint8_t effective_address_provided; | |
302 | + uint8_t reserved_1[6]; | |
303 | + uint64_t effective_address; | |
304 | + uint8_t reserved_2[16]; | |
305 | + } erat_error; | |
306 | + | |
307 | + struct { | |
308 | + enum OpalMCE_TlbErrorType tlb_error_type:8; | |
309 | + uint8_t effective_address_provided; | |
310 | + uint8_t reserved_1[6]; | |
311 | + uint64_t effective_address; | |
312 | + uint8_t reserved_2[16]; | |
313 | + } tlb_error; | |
314 | + } u; | |
315 | +}; | |
316 | + | |
317 | +typedef struct oppanel_line { | |
318 | + /* XXX */ | |
319 | +} oppanel_line_t; | |
320 | + | |
321 | +/* API functions */ | |
322 | +int64_t opal_console_write(int64_t term_number, int64_t *length, | |
323 | + const uint8_t *buffer); | |
324 | +int64_t opal_console_read(int64_t term_number, int64_t *length, | |
325 | + uint8_t *buffer); | |
326 | +int64_t opal_console_write_buffer_space(int64_t term_number, | |
327 | + int64_t *length); | |
328 | +int64_t opal_rtc_read(uint32_t *year_month_day, | |
329 | + uint64_t *hour_minute_second_millisecond); | |
330 | +int64_t opal_rtc_write(uint32_t year_month_day, | |
331 | + uint64_t hour_minute_second_millisecond); | |
332 | +int64_t opal_cec_power_down(uint64_t request); | |
333 | +int64_t opal_cec_reboot(void); | |
334 | +int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset); | |
335 | +int64_t opal_write_nvram(uint64_t buffer, uint64_t size, uint64_t offset); | |
336 | +int64_t opal_handle_interrupt(uint64_t isn, uint64_t *outstanding_event_mask); | |
337 | +int64_t opal_poll_events(uint64_t *outstanding_event_mask); | |
338 | +int64_t opal_pci_set_hub_tce_memory(uint64_t hub_id, uint64_t tce_mem_addr, | |
339 | + uint64_t tce_mem_size); | |
340 | +int64_t opal_pci_set_phb_tce_memory(uint64_t phb_id, uint64_t tce_mem_addr, | |
341 | + uint64_t tce_mem_size); | |
342 | +int64_t opal_pci_config_read_byte(uint64_t phb_id, uint64_t bus_dev_func, | |
343 | + uint64_t offset, uint8_t *data); | |
344 | +int64_t opal_pci_config_read_half_word(uint64_t phb_id, uint64_t bus_dev_func, | |
345 | + uint64_t offset, uint16_t *data); | |
346 | +int64_t opal_pci_config_read_word(uint64_t phb_id, uint64_t bus_dev_func, | |
347 | + uint64_t offset, uint32_t *data); | |
348 | +int64_t opal_pci_config_write_byte(uint64_t phb_id, uint64_t bus_dev_func, | |
349 | + uint64_t offset, uint8_t data); | |
350 | +int64_t opal_pci_config_write_half_word(uint64_t phb_id, uint64_t bus_dev_func, | |
351 | + uint64_t offset, uint16_t data); | |
352 | +int64_t opal_pci_config_write_word(uint64_t phb_id, uint64_t bus_dev_func, | |
353 | + uint64_t offset, uint32_t data); | |
354 | +int64_t opal_set_xive(uint32_t isn, uint16_t server, uint8_t priority); | |
355 | +int64_t opal_get_xive(uint32_t isn, uint16_t *server, uint8_t *priority); | |
356 | +int64_t opal_register_exception_handler(uint64_t opal_exception, | |
357 | + uint64_t handler_address, | |
358 | + uint64_t glue_cache_line); | |
359 | +int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number, | |
360 | + uint8_t *freeze_state, | |
361 | + uint16_t *pci_error_type, | |
362 | + uint64_t *phb_status); | |
363 | +int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number, | |
364 | + uint64_t eeh_action_token); | |
365 | +int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state); | |
366 | + | |
367 | + | |
368 | + | |
369 | +int64_t opal_pci_phb_mmio_enable(uint64_t phb_id, uint16_t window_type, | |
370 | + uint16_t window_num, uint16_t enable); | |
371 | +int64_t opal_pci_set_phb_mem_window(uint64_t phb_id, uint16_t window_type, | |
372 | + uint16_t window_num, | |
373 | + uint64_t starting_real_address, | |
374 | + uint64_t starting_pci_address, | |
375 | + uint16_t segment_size); | |
376 | +int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number, | |
377 | + uint16_t window_type, uint16_t window_num, | |
378 | + uint16_t segment_num); | |
379 | +int64_t opal_pci_set_phb_table_memory(uint64_t phb_id, uint64_t rtt_addr, | |
380 | + uint64_t ivt_addr, uint64_t ivt_len, | |
381 | + uint64_t reject_array_addr, | |
382 | + uint64_t peltv_addr); | |
383 | +int64_t opal_pci_set_pe(uint64_t phb_id, uint64_t pe_number, uint64_t bus_dev_func, | |
384 | + uint8_t bus_compare, uint8_t dev_compare, uint8_t func_compare, | |
385 | + uint8_t pe_action); | |
386 | +int64_t opal_pci_set_peltv(uint64_t phb_id, uint32_t parent_pe, uint32_t child_pe, | |
387 | + uint8_t state); | |
388 | +int64_t opal_pci_set_mve(uint64_t phb_id, uint32_t mve_number, uint32_t pe_number); | |
389 | +int64_t opal_pci_set_mve_enable(uint64_t phb_id, uint32_t mve_number, | |
390 | + uint32_t state); | |
391 | +int64_t opal_pci_get_xive_reissue(uint64_t phb_id, uint32_t xive_number, | |
392 | + uint8_t *p_bit, uint8_t *q_bit); | |
393 | +int64_t opal_pci_set_xive_reissue(uint64_t phb_id, uint32_t xive_number, | |
394 | + uint8_t p_bit, uint8_t q_bit); | |
395 | +int64_t opal_pci_set_xive_pe(uint64_t phb_id, uint32_t pe_number, | |
396 | + uint32_t xive_num); | |
397 | +int64_t opal_get_xive_source(uint64_t phb_id, uint32_t xive_num, | |
398 | + int32_t *interrupt_source_number); | |
399 | +int64_t opal_get_msi_32(uint64_t phb_id, uint32_t mve_number, uint32_t xive_num, | |
400 | + uint8_t msi_range, uint32_t *msi_address, | |
401 | + uint32_t *message_data); | |
402 | +int64_t opal_get_msi_64(uint64_t phb_id, uint32_t mve_number, | |
403 | + uint32_t xive_num, uint8_t msi_range, | |
404 | + uint64_t *msi_address, uint32_t *message_data); | |
405 | +int64_t opal_start_cpu(uint64_t thread_number, uint64_t start_address); | |
406 | +int64_t opal_query_cpu_status(uint64_t thread_number, uint8_t *thread_status); | |
407 | +int64_t opal_write_oppanel(oppanel_line_t *lines, uint64_t num_lines); | |
408 | +int64_t opal_pci_map_pe_dma_window(uint64_t phb_id, uint16_t pe_number, uint16_t window_id, | |
409 | + uint16_t tce_levels, uint64_t tce_table_addr, | |
410 | + uint64_t tce_table_size, uint64_t tce_page_size); | |
411 | +int64_t opal_pci_map_pe_dma_window_real(uint64_t phb_id, uint16_t pe_number, | |
412 | + uint16_t dma_window_number, uint64_t pci_start_addr, | |
413 | + uint64_t pci_mem_size); | |
414 | +int64_t opal_pci_reset(uint64_t phb_id, uint8_t reset_scope, uint8_t assert_state); | |
415 | + | |
416 | +/* Internal functions */ | |
417 | +extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data); | |
418 | + | |
419 | +extern int opal_get_chars(uint32_t vtermno, char *buf, int count); | |
420 | +extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len); | |
421 | + | |
422 | +extern void hvc_opal_init_early(void); | |
423 | + | |
424 | +/* Internal functions */ | |
425 | +extern int early_init_dt_scan_opal(unsigned long node, const char *uname, | |
426 | + int depth, void *data); | |
427 | + | |
428 | +#endif /* __ASSEMBLY__ */ | |
49 | 429 | |
50 | 430 | #endif /* __OPAL_H */ |
arch/powerpc/kernel/prom.c
... | ... | @@ -54,6 +54,8 @@ |
54 | 54 | #include <asm/pci-bridge.h> |
55 | 55 | #include <asm/phyp_dump.h> |
56 | 56 | #include <asm/kexec.h> |
57 | +#include <asm/opal.h> | |
58 | + | |
57 | 59 | #include <mm/mmu_decl.h> |
58 | 60 | |
59 | 61 | #ifdef DEBUG |
... | ... | @@ -705,6 +707,11 @@ |
705 | 707 | #ifdef CONFIG_PPC_RTAS |
706 | 708 | /* Some machines might need RTAS info for debugging, grab it now. */ |
707 | 709 | of_scan_flat_dt(early_init_dt_scan_rtas, NULL); |
710 | +#endif | |
711 | + | |
712 | +#ifdef CONFIG_PPC_POWERNV | |
713 | + /* Some machines might need OPAL info for debugging, grab it now. */ | |
714 | + of_scan_flat_dt(early_init_dt_scan_opal, NULL); | |
708 | 715 | #endif |
709 | 716 | |
710 | 717 | #ifdef CONFIG_PHYP_DUMP |
arch/powerpc/platforms/powernv/Kconfig
1 | 1 | config PPC_POWERNV |
2 | 2 | depends on PPC64 && PPC_BOOK3S |
3 | 3 | bool "IBM PowerNV (Non-Virtualized) platform support" |
4 | - select PPC_RTAS | |
5 | 4 | select PPC_NATIVE |
6 | 5 | select PPC_XICS |
7 | 6 | select PPC_ICP_NATIVE |
8 | - select PPC_ICS_RTAS | |
9 | 7 | select PPC_P7_NAP |
10 | 8 | select PPC_PCI_CHOICE if EMBEDDED |
11 | 9 | default y |
10 | + | |
11 | +config PPC_POWERNV_RTAS | |
12 | + depends on PPC_POWERNV | |
13 | + bool "Support for RTAS based PowerNV platforms such as BML" | |
14 | + default y | |
15 | + select PPC_ICS_RTAS | |
16 | + select PPC_RTAS |
arch/powerpc/platforms/powernv/Makefile
arch/powerpc/platforms/powernv/opal-wrappers.S
1 | +/* | |
2 | + * PowerNV OPAL API wrappers | |
3 | + * | |
4 | + * Copyright 2011 IBM Corp. | |
5 | + * | |
6 | + * This program is free software; you can redistribute it and/or | |
7 | + * modify it under the terms of the GNU General Public License | |
8 | + * as published by the Free Software Foundation; either version | |
9 | + * 2 of the License, or (at your option) any later version. | |
10 | + */ | |
11 | + | |
12 | +#include <asm/ppc_asm.h> | |
13 | +#include <asm/hvcall.h> | |
14 | +#include <asm/asm-offsets.h> | |
15 | +#include <asm/opal.h> | |
16 | + | |
17 | +/* TODO: | |
18 | + * | |
19 | + * - Trace irqs in/off (needs saving/restoring all args, argh...) | |
20 | + * - Get r11 feed up by Dave so I can have better register usage | |
21 | + */ | |
22 | +#define OPAL_CALL(name, token) \ | |
23 | + _GLOBAL(name); \ | |
24 | + mflr r0; \ | |
25 | + mfcr r12; \ | |
26 | + std r0,16(r1); \ | |
27 | + std r12,8(r1); \ | |
28 | + std r1,PACAR1(r13); \ | |
29 | + li r0,0; \ | |
30 | + mfmsr r12; \ | |
31 | + ori r0,r0,MSR_EE; \ | |
32 | + std r12,PACASAVEDMSR(r13); \ | |
33 | + andc r12,r12,r0; \ | |
34 | + mtmsrd r12,1; \ | |
35 | + LOAD_REG_ADDR(r0,.opal_return); \ | |
36 | + mtlr r0; \ | |
37 | + li r0,MSR_DR|MSR_IR; \ | |
38 | + andc r12,r12,r0; \ | |
39 | + li r0,token; \ | |
40 | + mtspr SPRN_HSRR1,r12; \ | |
41 | + LOAD_REG_ADDR(r11,opal); \ | |
42 | + ld r12,8(r11); \ | |
43 | + ld r2,0(r11); \ | |
44 | + mtspr SPRN_HSRR0,r12; \ | |
45 | + hrfid | |
46 | + | |
47 | +_STATIC(opal_return) | |
48 | + ld r2,PACATOC(r13); | |
49 | + ld r4,8(r1); | |
50 | + ld r5,16(r1); | |
51 | + ld r6,PACASAVEDMSR(r13); | |
52 | + mtspr SPRN_SRR0,r5; | |
53 | + mtspr SPRN_SRR1,r6; | |
54 | + mtcr r4; | |
55 | + rfid | |
56 | + | |
57 | +OPAL_CALL(opal_console_write, OPAL_CONSOLE_WRITE); | |
58 | +OPAL_CALL(opal_console_read, OPAL_CONSOLE_READ); | |
59 | +OPAL_CALL(opal_console_write_buffer_space, OPAL_CONSOLE_WRITE_BUFFER_SPACE); | |
60 | +OPAL_CALL(opal_rtc_read, OPAL_RTC_READ); | |
61 | +OPAL_CALL(opal_rtc_write, OPAL_RTC_WRITE); | |
62 | +OPAL_CALL(opal_cec_power_down, OPAL_CEC_POWER_DOWN); | |
63 | +OPAL_CALL(opal_cec_reboot, OPAL_CEC_REBOOT); | |
64 | +OPAL_CALL(opal_read_nvram, OPAL_READ_NVRAM); | |
65 | +OPAL_CALL(opal_write_nvram, OPAL_WRITE_NVRAM); | |
66 | +OPAL_CALL(opal_handle_interrupt, OPAL_HANDLE_INTERRUPT); | |
67 | +OPAL_CALL(opal_poll_events, OPAL_POLL_EVENTS); | |
68 | +OPAL_CALL(opal_pci_set_hub_tce_memory, OPAL_PCI_SET_HUB_TCE_MEMORY); | |
69 | +OPAL_CALL(opal_pci_set_phb_tce_memory, OPAL_PCI_SET_PHB_TCE_MEMORY); | |
70 | +OPAL_CALL(opal_pci_config_read_byte, OPAL_PCI_CONFIG_READ_BYTE); | |
71 | +OPAL_CALL(opal_pci_config_read_half_word, OPAL_PCI_CONFIG_READ_HALF_WORD); | |
72 | +OPAL_CALL(opal_pci_config_read_word, OPAL_PCI_CONFIG_READ_WORD); | |
73 | +OPAL_CALL(opal_pci_config_write_byte, OPAL_PCI_CONFIG_WRITE_BYTE); | |
74 | +OPAL_CALL(opal_pci_config_write_half_word, OPAL_PCI_CONFIG_WRITE_HALF_WORD); | |
75 | +OPAL_CALL(opal_pci_config_write_word, OPAL_PCI_CONFIG_WRITE_WORD); | |
76 | +OPAL_CALL(opal_set_xive, OPAL_SET_XIVE); | |
77 | +OPAL_CALL(opal_get_xive, OPAL_GET_XIVE); | |
78 | +OPAL_CALL(opal_register_exception_handler, OPAL_REGISTER_OPAL_EXCEPTION_HANDLER); | |
79 | +OPAL_CALL(opal_pci_eeh_freeze_status, OPAL_PCI_EEH_FREEZE_STATUS); | |
80 | +OPAL_CALL(opal_pci_eeh_freeze_clear, OPAL_PCI_EEH_FREEZE_CLEAR); | |
81 | +OPAL_CALL(opal_pci_shpc, OPAL_PCI_SHPC); | |
82 | +OPAL_CALL(opal_pci_phb_mmio_enable, OPAL_PCI_PHB_MMIO_ENABLE); | |
83 | +OPAL_CALL(opal_pci_set_phb_mem_window, OPAL_PCI_SET_PHB_MEM_WINDOW); | |
84 | +OPAL_CALL(opal_pci_map_pe_mmio_window, OPAL_PCI_MAP_PE_MMIO_WINDOW); | |
85 | +OPAL_CALL(opal_pci_set_phb_table_memory, OPAL_PCI_SET_PHB_TABLE_MEMORY); | |
86 | +OPAL_CALL(opal_pci_set_pe, OPAL_PCI_SET_PE); | |
87 | +OPAL_CALL(opal_pci_set_peltv, OPAL_PCI_SET_PELTV); | |
88 | +OPAL_CALL(opal_pci_set_mve, OPAL_PCI_SET_MVE); | |
89 | +OPAL_CALL(opal_pci_set_mve_enable, OPAL_PCI_SET_MVE_ENABLE); | |
90 | +OPAL_CALL(opal_pci_get_xive_reissue, OPAL_PCI_GET_XIVE_REISSUE); | |
91 | +OPAL_CALL(opal_pci_set_xive_reissue, OPAL_PCI_SET_XIVE_REISSUE); | |
92 | +OPAL_CALL(opal_pci_set_xive_pe, OPAL_PCI_SET_XIVE_PE); | |
93 | +OPAL_CALL(opal_get_xive_source, OPAL_GET_XIVE_SOURCE); | |
94 | +OPAL_CALL(opal_get_msi_32, OPAL_GET_MSI_32); | |
95 | +OPAL_CALL(opal_get_msi_64, OPAL_GET_MSI_64); | |
96 | +OPAL_CALL(opal_start_cpu, OPAL_START_CPU); | |
97 | +OPAL_CALL(opal_query_cpu_status, OPAL_QUERY_CPU_STATUS); | |
98 | +OPAL_CALL(opal_write_oppanel, OPAL_WRITE_OPPANEL); | |
99 | +OPAL_CALL(opal_pci_map_pe_dma_window, OPAL_PCI_MAP_PE_DMA_WINDOW); | |
100 | +OPAL_CALL(opal_pci_map_pe_dma_window_real, OPAL_PCI_MAP_PE_DMA_WINDOW_REAL); | |
101 | +OPAL_CALL(opal_pci_reset, OPAL_PCI_RESET); |
arch/powerpc/platforms/powernv/opal.c
1 | +/* | |
2 | + * PowerNV OPAL high level interfaces | |
3 | + * | |
4 | + * Copyright 2011 IBM Corp. | |
5 | + * | |
6 | + * This program is free software; you can redistribute it and/or | |
7 | + * modify it under the terms of the GNU General Public License | |
8 | + * as published by the Free Software Foundation; either version | |
9 | + * 2 of the License, or (at your option) any later version. | |
10 | + */ | |
11 | + | |
12 | +#undef DEBUG | |
13 | + | |
14 | +#include <linux/types.h> | |
15 | +#include <linux/of.h> | |
16 | +#include <linux/of_platform.h> | |
17 | +#include <asm/opal.h> | |
18 | +#include <asm/firmware.h> | |
19 | + | |
20 | +#include "powernv.h" | |
21 | + | |
22 | +struct opal { | |
23 | + u64 base; | |
24 | + u64 entry; | |
25 | +} opal; | |
26 | + | |
27 | +static struct device_node *opal_node; | |
28 | +static DEFINE_SPINLOCK(opal_write_lock); | |
29 | + | |
30 | +int __init early_init_dt_scan_opal(unsigned long node, | |
31 | + const char *uname, int depth, void *data) | |
32 | +{ | |
33 | + const void *basep, *entryp; | |
34 | + unsigned long basesz, entrysz; | |
35 | + | |
36 | + if (depth != 1 || strcmp(uname, "ibm,opal") != 0) | |
37 | + return 0; | |
38 | + | |
39 | + basep = of_get_flat_dt_prop(node, "opal-base-address", &basesz); | |
40 | + entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz); | |
41 | + | |
42 | + if (!basep || !entryp) | |
43 | + return 1; | |
44 | + | |
45 | + opal.base = of_read_number(basep, basesz/4); | |
46 | + opal.entry = of_read_number(entryp, entrysz/4); | |
47 | + | |
48 | + pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%ld)\n", | |
49 | + opal.base, basep, basesz); | |
50 | + pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n", | |
51 | + opal.entry, entryp, entrysz); | |
52 | + | |
53 | + powerpc_firmware_features |= FW_FEATURE_OPAL; | |
54 | + if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) { | |
55 | + powerpc_firmware_features |= FW_FEATURE_OPALv2; | |
56 | + printk("OPAL V2 detected !\n"); | |
57 | + } else { | |
58 | + printk("OPAL V1 detected !\n"); | |
59 | + } | |
60 | + | |
61 | + return 1; | |
62 | +} | |
63 | + | |
64 | +int opal_get_chars(uint32_t vtermno, char *buf, int count) | |
65 | +{ | |
66 | + s64 len, rc; | |
67 | + u64 evt; | |
68 | + | |
69 | + if (!opal.entry) | |
70 | + return 0; | |
71 | + opal_poll_events(&evt); | |
72 | + if ((evt & OPAL_EVENT_CONSOLE_INPUT) == 0) | |
73 | + return 0; | |
74 | + len = count; | |
75 | + rc = opal_console_read(vtermno, &len, buf); | |
76 | + if (rc == OPAL_SUCCESS) | |
77 | + return len; | |
78 | + return 0; | |
79 | +} | |
80 | + | |
81 | +int opal_put_chars(uint32_t vtermno, const char *data, int total_len) | |
82 | +{ | |
83 | + int written = 0; | |
84 | + s64 len, rc = OPAL_BUSY; | |
85 | + unsigned long flags; | |
86 | + u64 evt; | |
87 | + | |
88 | + if (!opal.entry) | |
89 | + return 0; | |
90 | + | |
91 | + /* We want put_chars to be atomic to avoid mangling of hvsi | |
92 | + * packets. To do that, we first test for room and return | |
93 | + * -EAGAIN if there isn't enough | |
94 | + */ | |
95 | + spin_lock_irqsave(&opal_write_lock, flags); | |
96 | + rc = opal_console_write_buffer_space(vtermno, &len); | |
97 | + if (rc || len < total_len) { | |
98 | + spin_unlock_irqrestore(&opal_write_lock, flags); | |
99 | + /* Closed -> drop characters */ | |
100 | + if (rc) | |
101 | + return total_len; | |
102 | + opal_poll_events(&evt); | |
103 | + return -EAGAIN; | |
104 | + } | |
105 | + | |
106 | + /* We still try to handle partial completions, though they | |
107 | + * should no longer happen. | |
108 | + */ | |
109 | + while(total_len > 0 && (rc == OPAL_BUSY || | |
110 | + rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) { | |
111 | + len = total_len; | |
112 | + rc = opal_console_write(vtermno, &len, data); | |
113 | + if (rc == OPAL_SUCCESS) { | |
114 | + total_len -= len; | |
115 | + data += len; | |
116 | + written += len; | |
117 | + } | |
118 | + /* This is a bit nasty but we need that for the console to | |
119 | + * flush when there aren't any interrupts. We will clean | |
120 | + * things a bit later to limit that to synchronous path | |
121 | + * such as the kernel console and xmon/udbg | |
122 | + */ | |
123 | + do | |
124 | + opal_poll_events(&evt); | |
125 | + while(rc == OPAL_SUCCESS && (evt & OPAL_EVENT_CONSOLE_OUTPUT)); | |
126 | + } | |
127 | + spin_unlock_irqrestore(&opal_write_lock, flags); | |
128 | + return written; | |
129 | +} | |
130 | + | |
131 | +static int __init opal_init(void) | |
132 | +{ | |
133 | + struct device_node *np, *consoles; | |
134 | + | |
135 | + opal_node = of_find_node_by_path("/ibm,opal"); | |
136 | + if (!opal_node) { | |
137 | + pr_warn("opal: Node not found\n"); | |
138 | + return -ENODEV; | |
139 | + } | |
140 | + if (firmware_has_feature(FW_FEATURE_OPALv2)) | |
141 | + consoles = of_find_node_by_path("/ibm,opal/consoles"); | |
142 | + else | |
143 | + consoles = of_node_get(opal_node); | |
144 | + | |
145 | + /* Register serial ports */ | |
146 | + for_each_child_of_node(consoles, np) { | |
147 | + if (strcmp(np->name, "serial")) | |
148 | + continue; | |
149 | + of_platform_device_create(np, NULL, NULL); | |
150 | + } | |
151 | + of_node_put(consoles); | |
152 | + return 0; | |
153 | +} | |
154 | +subsys_initcall(opal_init); |
arch/powerpc/platforms/powernv/setup.c
... | ... | @@ -74,6 +74,12 @@ |
74 | 74 | if (root) |
75 | 75 | model = of_get_property(root, "model", NULL); |
76 | 76 | seq_printf(m, "machine\t\t: PowerNV %s\n", model); |
77 | + if (firmware_has_feature(FW_FEATURE_OPALv2)) | |
78 | + seq_printf(m, "firmware\t: OPAL v2\n"); | |
79 | + else if (firmware_has_feature(FW_FEATURE_OPAL)) | |
80 | + seq_printf(m, "firmware\t: OPAL v1\n"); | |
81 | + else | |
82 | + seq_printf(m, "firmware\t: BML\n"); | |
77 | 83 | of_node_put(root); |
78 | 84 | } |
79 | 85 |
arch/powerpc/platforms/powernv/smp.c
... | ... | @@ -30,6 +30,7 @@ |
30 | 30 | #include <asm/vdso_datapage.h> |
31 | 31 | #include <asm/cputhreads.h> |
32 | 32 | #include <asm/xics.h> |
33 | +#include <asm/opal.h> | |
33 | 34 | |
34 | 35 | #include "powernv.h" |
35 | 36 | |
... | ... | @@ -62,6 +63,28 @@ |
62 | 63 | return 1; |
63 | 64 | } |
64 | 65 | |
66 | +int __devinit pnv_smp_kick_cpu(int nr) | |
67 | +{ | |
68 | + unsigned int pcpu = get_hard_smp_processor_id(nr); | |
69 | + unsigned long start_here = __pa(*((unsigned long *) | |
70 | + generic_secondary_smp_init)); | |
71 | + long rc; | |
72 | + | |
73 | + BUG_ON(nr < 0 || nr >= NR_CPUS); | |
74 | + | |
75 | + /* On OPAL v2 the CPU are still spinning inside OPAL itself, | |
76 | + * get them back now | |
77 | + */ | |
78 | + if (firmware_has_feature(FW_FEATURE_OPALv2)) { | |
79 | + pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu); | |
80 | + rc = opal_start_cpu(pcpu, start_here); | |
81 | + if (rc != OPAL_SUCCESS) | |
82 | + pr_warn("OPAL Error %ld starting CPU %d\n", | |
83 | + rc, nr); | |
84 | + } | |
85 | + return smp_generic_kick_cpu(nr); | |
86 | +} | |
87 | + | |
65 | 88 | #ifdef CONFIG_HOTPLUG_CPU |
66 | 89 | |
67 | 90 | static int pnv_smp_cpu_disable(void) |
... | ... | @@ -127,7 +150,7 @@ |
127 | 150 | .message_pass = smp_muxed_ipi_message_pass, |
128 | 151 | .cause_ipi = NULL, /* Filled at runtime by xics_smp_probe() */ |
129 | 152 | .probe = xics_smp_probe, |
130 | - .kick_cpu = smp_generic_kick_cpu, | |
153 | + .kick_cpu = pnv_smp_kick_cpu, | |
131 | 154 | .setup_cpu = pnv_smp_setup_cpu, |
132 | 155 | .cpu_bootable = pnv_smp_cpu_bootable, |
133 | 156 | #ifdef CONFIG_HOTPLUG_CPU |