.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * arch/parisc/kernel/firmware.c - safe PDC access routines |
---|
3 | 4 | * |
---|
4 | 5 | * PDC == Processor Dependent Code |
---|
5 | 6 | * |
---|
6 | | - * See http://www.parisc-linux.org/documentation/index.html |
---|
| 7 | + * See PDC documentation at |
---|
| 8 | + * https://parisc.wiki.kernel.org/index.php/Technical_Documentation |
---|
7 | 9 | * for documentation describing the entry points and calling |
---|
8 | 10 | * conventions defined below. |
---|
9 | 11 | * |
---|
.. | .. |
---|
12 | 14 | * Copyright 2003 Grant Grundler <grundler parisc-linux org> |
---|
13 | 15 | * Copyright 2003,2004 Ryan Bradetich <rbrad@parisc-linux.org> |
---|
14 | 16 | * Copyright 2004,2006 Thibaut VARENE <varenet@parisc-linux.org> |
---|
15 | | - * |
---|
16 | | - * This program is free software; you can redistribute it and/or modify |
---|
17 | | - * it under the terms of the GNU General Public License as published by |
---|
18 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
19 | | - * (at your option) any later version. |
---|
20 | | - * |
---|
21 | 17 | */ |
---|
22 | 18 | |
---|
23 | 19 | /* I think it would be in everyone's best interest to follow this |
---|
.. | .. |
---|
87 | 83 | |
---|
88 | 84 | /* Firmware needs to be initially set to narrow to determine the |
---|
89 | 85 | * actual firmware width. */ |
---|
90 | | -int parisc_narrow_firmware __read_mostly = 1; |
---|
| 86 | +int parisc_narrow_firmware __ro_after_init = 1; |
---|
91 | 87 | #endif |
---|
92 | 88 | |
---|
93 | 89 | /* On most currently-supported platforms, IODC I/O calls are 32-bit calls |
---|
.. | .. |
---|
315 | 311 | |
---|
316 | 312 | return retval; |
---|
317 | 313 | } |
---|
| 314 | + |
---|
| 315 | +/** |
---|
| 316 | + * pdc_cpu_rendenzvous - Stop currently executing CPU |
---|
| 317 | + * @retval: -1 on error, 0 on success |
---|
| 318 | + */ |
---|
| 319 | +int __pdc_cpu_rendezvous(void) |
---|
| 320 | +{ |
---|
| 321 | + if (is_pdc_pat()) |
---|
| 322 | + return mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_RENDEZVOUS); |
---|
| 323 | + else |
---|
| 324 | + return mem_pdc_call(PDC_PROC, 1, 0); |
---|
| 325 | +} |
---|
| 326 | + |
---|
318 | 327 | |
---|
319 | 328 | /** |
---|
320 | 329 | * pdc_chassis_warn - Fetches chassis warnings |
---|
.. | .. |
---|
566 | 575 | spin_unlock_irqrestore(&pdc_lock, flags); |
---|
567 | 576 | |
---|
568 | 577 | return retval; |
---|
| 578 | +} |
---|
| 579 | + |
---|
| 580 | +/** |
---|
| 581 | + * pdc_model_platform_info - Returns machine product and serial number. |
---|
| 582 | + * @orig_prod_num: Return buffer for original product number. |
---|
| 583 | + * @current_prod_num: Return buffer for current product number. |
---|
| 584 | + * @serial_no: Return buffer for serial number. |
---|
| 585 | + * |
---|
| 586 | + * Returns strings containing the original and current product numbers and the |
---|
| 587 | + * serial number of the system. |
---|
| 588 | + */ |
---|
| 589 | +int pdc_model_platform_info(char *orig_prod_num, char *current_prod_num, |
---|
| 590 | + char *serial_no) |
---|
| 591 | +{ |
---|
| 592 | + int retval; |
---|
| 593 | + unsigned long flags; |
---|
| 594 | + |
---|
| 595 | + spin_lock_irqsave(&pdc_lock, flags); |
---|
| 596 | + retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_GET_PLATFORM_INFO, |
---|
| 597 | + __pa(orig_prod_num), __pa(current_prod_num), __pa(serial_no)); |
---|
| 598 | + convert_to_wide(pdc_result); |
---|
| 599 | + spin_unlock_irqrestore(&pdc_lock, flags); |
---|
| 600 | + |
---|
| 601 | + return retval; |
---|
569 | 602 | } |
---|
570 | 603 | |
---|
571 | 604 | /** |
---|
.. | .. |
---|
1197 | 1230 | */ |
---|
1198 | 1231 | int pdc_iodc_print(const unsigned char *str, unsigned count) |
---|
1199 | 1232 | { |
---|
1200 | | - unsigned int i; |
---|
| 1233 | + unsigned int i, found = 0; |
---|
1201 | 1234 | unsigned long flags; |
---|
1202 | 1235 | |
---|
1203 | 1236 | for (i = 0; i < count;) { |
---|
.. | .. |
---|
1206 | 1239 | iodc_dbuf[i+0] = '\r'; |
---|
1207 | 1240 | iodc_dbuf[i+1] = '\n'; |
---|
1208 | 1241 | i += 2; |
---|
| 1242 | + found = 1; |
---|
1209 | 1243 | goto print; |
---|
1210 | 1244 | default: |
---|
1211 | 1245 | iodc_dbuf[i] = str[i]; |
---|
.. | .. |
---|
1222 | 1256 | __pa(iodc_retbuf), 0, __pa(iodc_dbuf), i, 0); |
---|
1223 | 1257 | spin_unlock_irqrestore(&pdc_lock, flags); |
---|
1224 | 1258 | |
---|
1225 | | - return i; |
---|
| 1259 | + return i - found; |
---|
1226 | 1260 | } |
---|
1227 | 1261 | |
---|
1228 | 1262 | #if !defined(BOOTLOADER) |
---|
.. | .. |
---|
1326 | 1360 | } |
---|
1327 | 1361 | |
---|
1328 | 1362 | /** |
---|
| 1363 | + * pdc_pat_cell_info - Retrieve the cell's information. |
---|
| 1364 | + * @info: The pointer to a struct pdc_pat_cell_info_rtn_block. |
---|
| 1365 | + * @actcnt: The number of bytes which should be written to info. |
---|
| 1366 | + * @offset: offset of the structure. |
---|
| 1367 | + * @cell_number: The cell number which should be asked, or -1 for current cell. |
---|
| 1368 | + * |
---|
| 1369 | + * This PDC call returns information about the given cell (or all cells). |
---|
| 1370 | + */ |
---|
| 1371 | +int pdc_pat_cell_info(struct pdc_pat_cell_info_rtn_block *info, |
---|
| 1372 | + unsigned long *actcnt, unsigned long offset, |
---|
| 1373 | + unsigned long cell_number) |
---|
| 1374 | +{ |
---|
| 1375 | + int retval; |
---|
| 1376 | + unsigned long flags; |
---|
| 1377 | + struct pdc_pat_cell_info_rtn_block result; |
---|
| 1378 | + |
---|
| 1379 | + spin_lock_irqsave(&pdc_lock, flags); |
---|
| 1380 | + retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_GET_INFO, |
---|
| 1381 | + __pa(pdc_result), __pa(&result), *actcnt, |
---|
| 1382 | + offset, cell_number); |
---|
| 1383 | + if (!retval) { |
---|
| 1384 | + *actcnt = pdc_result[0]; |
---|
| 1385 | + memcpy(info, &result, *actcnt); |
---|
| 1386 | + } |
---|
| 1387 | + spin_unlock_irqrestore(&pdc_lock, flags); |
---|
| 1388 | + |
---|
| 1389 | + return retval; |
---|
| 1390 | +} |
---|
| 1391 | + |
---|
| 1392 | +/** |
---|
1329 | 1393 | * pdc_pat_cpu_get_number - Retrieve the cpu number. |
---|
1330 | 1394 | * @cpu_info: The return buffer. |
---|
1331 | 1395 | * @hpa: The Hard Physical Address of the CPU. |
---|
.. | .. |
---|
1413 | 1477 | } |
---|
1414 | 1478 | |
---|
1415 | 1479 | /** |
---|
| 1480 | + * pdc_pat_pd_get_PDC_interface_revisions - Retrieve PDC interface revisions. |
---|
| 1481 | + * @legacy_rev: The legacy revision. |
---|
| 1482 | + * @pat_rev: The PAT revision. |
---|
| 1483 | + * @pdc_cap: The PDC capabilities. |
---|
| 1484 | + * |
---|
| 1485 | + */ |
---|
| 1486 | +int pdc_pat_pd_get_pdc_revisions(unsigned long *legacy_rev, |
---|
| 1487 | + unsigned long *pat_rev, unsigned long *pdc_cap) |
---|
| 1488 | +{ |
---|
| 1489 | + int retval; |
---|
| 1490 | + unsigned long flags; |
---|
| 1491 | + |
---|
| 1492 | + spin_lock_irqsave(&pdc_lock, flags); |
---|
| 1493 | + retval = mem_pdc_call(PDC_PAT_PD, PDC_PAT_PD_GET_PDC_INTERF_REV, |
---|
| 1494 | + __pa(pdc_result)); |
---|
| 1495 | + if (retval == PDC_OK) { |
---|
| 1496 | + *legacy_rev = pdc_result[0]; |
---|
| 1497 | + *pat_rev = pdc_result[1]; |
---|
| 1498 | + *pdc_cap = pdc_result[2]; |
---|
| 1499 | + } |
---|
| 1500 | + spin_unlock_irqrestore(&pdc_lock, flags); |
---|
| 1501 | + |
---|
| 1502 | + return retval; |
---|
| 1503 | +} |
---|
| 1504 | + |
---|
| 1505 | + |
---|
| 1506 | +/** |
---|
1416 | 1507 | * pdc_pat_io_pci_cfg_read - Read PCI configuration space. |
---|
1417 | 1508 | * @pci_addr: PCI configuration space address for which the read request is being made. |
---|
1418 | 1509 | * @pci_size: Size of read in bytes. Valid values are 1, 2, and 4. |
---|