| 1 | |
| 2 | |
| 3 | * arch/parisc/kernel/firmware.c - safe PDC access routines
|
| 4 | *
|
| 5 | * PDC == Processor Dependent Code
|
| 6 | *
|
| 7 | * See PDC documentation at
|
| 8 | * https://parisc.wiki.kernel.org/index.php/Technical_Documentation
|
| 9 | * for documentation describing the entry points and calling
|
| 10 | * conventions defined below.
|
| 11 | *
|
| 12 | * Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, [email protected])
|
| 13 | * Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy)
|
| 14 | * Copyright 2003 Grant Grundler <grundler parisc-linux org>
|
| 15 | * Copyright 2003,2004 Ryan Bradetich <[email protected]>
|
| 16 | * Copyright 2004,2006 Thibaut VARENE <[email protected]>
|
| 17 |
|
| 18 |
|
| 19 | |
| 20 | * guidelines when writing PDC wrappers:
|
| 21 | *
|
| 22 | * - the name of the pdc wrapper should match one of the macros
|
| 23 | * used for the first two arguments
|
| 24 | * - don't use caps for random parts of the name
|
| 25 | * - use the static PDC result buffers and "copyout" to structs
|
| 26 | * supplied by the caller to encapsulate alignment restrictions
|
| 27 | * - hold pdc_lock while in PDC or using static result buffers
|
| 28 | * - use __pa() to convert virtual (kernel) pointers to physical
|
| 29 | * ones.
|
| 30 | * - the name of the struct used for pdc return values should equal
|
| 31 | * one of the macros used for the first two arguments to the
|
| 32 | * corresponding PDC call
|
| 33 | * - keep the order of arguments
|
| 34 | * - don't be smart (setting trailing NUL bytes for strings, return
|
| 35 | * something useful even if the call failed) unless you are sure
|
| 36 | * it's not going to affect functionality or performance
|
| 37 | *
|
| 38 | * Example:
|
| 39 | * int pdc_cache_info(struct pdc_cache_info *cache_info )
|
| 40 | * {
|
| 41 | * int retval;
|
| 42 | *
|
| 43 | * spin_lock_irq(&pdc_lock);
|
| 44 | * retval = mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
|
| 45 | * convert_to_wide(pdc_result);
|
| 46 | * memcpy(cache_info, pdc_result, sizeof(*cache_info));
|
| 47 | * spin_unlock_irq(&pdc_lock);
|
| 48 | *
|
| 49 | * return retval;
|
| 50 | * }
|
| 51 | * prumpf 991016
|
| 52 |
|
| 53 |
|
| 54 | #include <linux/stdarg.h>
|
| 55 |
|
| 56 | #include <linux/delay.h>
|
| 57 | #include <linux/init.h>
|
| 58 | #include <linux/kernel.h>
|
| 59 | #include <linux/module.h>
|
| 60 | #include <linux/string.h>
|
| 61 | #include <linux/spinlock.h>
|
| 62 |
|
| 63 | #include <asm/page.h>
|
| 64 | #include <asm/pdc.h>
|
| 65 | #include <asm/pdcpat.h>
|
| 66 | #include <asm/processor.h>
|
| 67 |
|
| 68 | #if defined(BOOTLOADER)
|
| 69 | # undef spin_lock_irqsave
|
| 70 | # define spin_lock_irqsave(a, b) { b = 1; }
|
| 71 | # undef spin_unlock_irqrestore
|
| 72 | # define spin_unlock_irqrestore(a, b)
|
| 73 | #else
|
| 74 | static DEFINE_SPINLOCK(pdc_lock);
|
| 75 | #endif
|
| 76 |
|
| 77 | static unsigned long pdc_result[NUM_PDC_RESULT] __aligned(8);
|
| 78 | static unsigned long pdc_result2[NUM_PDC_RESULT] __aligned(8);
|
| 79 |
|
| 80 | #ifdef CONFIG_64BIT
|
| 81 | #define WIDE_FIRMWARE PDC_MODEL_OS64
|
| 82 | #define NARROW_FIRMWARE PDC_MODEL_OS32
|
| 83 |
|
| 84 | |
| 85 | * actual firmware width.
|
| 86 | int parisc_narrow_firmware __ro_after_init = NARROW_FIRMWARE;
|
| 87 | #endif
|
| 88 |
|
| 89 | |
| 90 | * and MEM_PDC calls are always the same width as the OS.
|
| 91 | * Some PAT boxes may have 64-bit IODC I/O.
|
| 92 | *
|
| 93 | * Ryan Bradetich added the now obsolete CONFIG_PDC_NARROW to allow
|
| 94 | * 64-bit kernels to run on systems with 32-bit MEM_PDC calls.
|
| 95 | * This allowed wide kernels to run on Cxxx boxes.
|
| 96 | * We now detect 32-bit-only PDC and dynamically switch to 32-bit mode
|
| 97 | * when running a 64-bit kernel on such boxes (e.g. C200 or C360).
|
| 98 |
|
| 99 |
|
| 100 | #ifdef CONFIG_64BIT
|
| 101 | long real64_call(unsigned long function, ...);
|
| 102 | #endif
|
| 103 | long real32_call(unsigned long function, ...);
|
| 104 |
|
| 105 | #ifdef CONFIG_64BIT
|
| 106 | # define MEM_PDC (unsigned long)(PAGE0->mem_pdc_hi) << 32 | PAGE0->mem_pdc
|
| 107 | # define mem_pdc_call(args...) unlikely(parisc_narrow_firmware) ? real32_call(MEM_PDC, args) : real64_call(MEM_PDC, args)
|
| 108 | #else
|
| 109 | # define MEM_PDC (unsigned long)PAGE0->mem_pdc
|
| 110 | # define mem_pdc_call(args...) real32_call(MEM_PDC, args)
|
| 111 | #endif
|
| 112 |
|
| 113 |
|
| 114 | |
| 115 | * f_extend - Convert PDC addresses to kernel addresses.
|
| 116 | * @address: Address returned from PDC.
|
| 117 | *
|
| 118 | * This function is used to convert PDC addresses into kernel addresses
|
| 119 | * when the PDC address size and kernel address size are different.
|
| 120 |
|
| 121 | static unsigned long f_extend(unsigned long address)
|
| 122 | {
|
| 123 | #ifdef CONFIG_64BIT
|
| 124 | if(unlikely(parisc_narrow_firmware)) {
|
| 125 | if((address & 0xff000000) == 0xf0000000)
|
| 126 | return (0xfffffff0UL << 32) | (u32)address;
|
| 127 |
|
| 128 | if((address & 0xf0000000) == 0xf0000000)
|
| 129 | return (0xffffffffUL << 32) | (u32)address;
|
| 130 | }
|
| 131 | #endif
|
| 132 | return address;
|
| 133 | }
|
| 134 |
|
| 135 | |
| 136 | * convert_to_wide - Convert the return buffer addresses into kernel addresses.
|
| 137 | * @addr: The return buffer from PDC.
|
| 138 | *
|
| 139 | * This function is used to convert the return buffer addresses retrieved from PDC
|
| 140 | * into kernel addresses when the PDC address size and kernel address size are
|
| 141 | * different.
|
| 142 |
|
| 143 | static void convert_to_wide(unsigned long *addr)
|
| 144 | {
|
| 145 | #ifdef CONFIG_64BIT
|
| 146 | int i;
|
| 147 | unsigned int *p = (unsigned int *)addr;
|
| 148 |
|
| 149 | if (unlikely(parisc_narrow_firmware)) {
|
| 150 | for (i = (NUM_PDC_RESULT-1); i >= 0; --i)
|
| 151 | addr[i] = p[i];
|
| 152 | }
|
| 153 | #endif
|
| 154 | }
|
| 155 |
|
| 156 | #ifdef CONFIG_64BIT
|
| 157 | void set_firmware_width_unlocked(void)
|
| 158 | {
|
| 159 | int ret;
|
| 160 |
|
| 161 | ret = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES,
|
| 162 | __pa(pdc_result), 0);
|
| 163 | if (ret < 0)
|
| 164 | return;
|
| 165 | convert_to_wide(pdc_result);
|
| 166 | if (pdc_result[0] != NARROW_FIRMWARE)
|
| 167 | parisc_narrow_firmware = 0;
|
| 168 | }
|
| 169 |
|
| 170 | |
| 171 | * set_firmware_width - Determine if the firmware is wide or narrow.
|
| 172 | *
|
| 173 | * This function must be called before any pdc_* function that uses the
|
| 174 | * convert_to_wide function.
|
| 175 |
|
| 176 | void set_firmware_width(void)
|
| 177 | {
|
| 178 | unsigned long flags;
|
| 179 |
|
| 180 |
|
| 181 | if (parisc_narrow_firmware != NARROW_FIRMWARE)
|
| 182 | return;
|
| 183 |
|
| 184 | spin_lock_irqsave(&pdc_lock, flags);
|
| 185 | set_firmware_width_unlocked();
|
| 186 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 187 | }
|
| 188 | #else
|
| 189 | void set_firmware_width_unlocked(void)
|
| 190 | {
|
| 191 | return;
|
| 192 | }
|
| 193 |
|
| 194 | void set_firmware_width(void)
|
| 195 | {
|
| 196 | return;
|
| 197 | }
|
| 198 | #endif
|
| 199 |
|
| 200 |
|
| 201 | #if !defined(BOOTLOADER)
|
| 202 | |
| 203 | * pdc_emergency_unlock - Unlock the linux pdc lock
|
| 204 | *
|
| 205 | * This call unlocks the linux pdc lock in case we need some PDC functions
|
| 206 | * (like pdc_add_valid) during kernel stack dump.
|
| 207 |
|
| 208 | void pdc_emergency_unlock(void)
|
| 209 | {
|
| 210 |
|
| 211 | if (spin_is_locked(&pdc_lock))
|
| 212 | spin_unlock(&pdc_lock);
|
| 213 | }
|
| 214 |
|
| 215 |
|
| 216 | |
| 217 | * pdc_add_valid - Verify address can be accessed without causing a HPMC.
|
| 218 | * @address: Address to be verified.
|
| 219 | *
|
| 220 | * This PDC call attempts to read from the specified address and verifies
|
| 221 | * if the address is valid.
|
| 222 | *
|
| 223 | * The return value is PDC_OK (0) in case accessing this address is valid.
|
| 224 |
|
| 225 | int pdc_add_valid(unsigned long address)
|
| 226 | {
|
| 227 | int retval;
|
| 228 | unsigned long flags;
|
| 229 |
|
| 230 | spin_lock_irqsave(&pdc_lock, flags);
|
| 231 | retval = mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, address);
|
| 232 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 233 |
|
| 234 | return retval;
|
| 235 | }
|
| 236 | EXPORT_SYMBOL(pdc_add_valid);
|
| 237 |
|
| 238 | |
| 239 | * pdc_instr - Get instruction that invokes PDCE_CHECK in HPMC handler.
|
| 240 | * @instr: Pointer to variable which will get instruction opcode.
|
| 241 | *
|
| 242 | * The return value is PDC_OK (0) in case call succeeded.
|
| 243 |
|
| 244 | int __init pdc_instr(unsigned int *instr)
|
| 245 | {
|
| 246 | int retval;
|
| 247 | unsigned long flags;
|
| 248 |
|
| 249 | spin_lock_irqsave(&pdc_lock, flags);
|
| 250 | retval = mem_pdc_call(PDC_INSTR, 0UL, __pa(pdc_result));
|
| 251 | convert_to_wide(pdc_result);
|
| 252 | *instr = pdc_result[0];
|
| 253 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 254 |
|
| 255 | return retval;
|
| 256 | }
|
| 257 |
|
| 258 | |
| 259 | * pdc_chassis_info - Return chassis information.
|
| 260 | * @chassis_info: The memory buffer address.
|
| 261 | * @led_info: The size of the memory buffer address.
|
| 262 | * @len: The size of the memory buffer address.
|
| 263 | *
|
| 264 | * An HVERSION dependent call for returning the chassis information.
|
| 265 |
|
| 266 | int __init pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len)
|
| 267 | {
|
| 268 | int retval;
|
| 269 | unsigned long flags;
|
| 270 |
|
| 271 | spin_lock_irqsave(&pdc_lock, flags);
|
| 272 | memcpy(&pdc_result, chassis_info, sizeof(*chassis_info));
|
| 273 | memcpy(&pdc_result2, led_info, len);
|
| 274 | retval = mem_pdc_call(PDC_CHASSIS, PDC_RETURN_CHASSIS_INFO,
|
| 275 | __pa(pdc_result), __pa(pdc_result2), len);
|
| 276 | memcpy(chassis_info, pdc_result, sizeof(*chassis_info));
|
| 277 | memcpy(led_info, pdc_result2, len);
|
| 278 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 279 |
|
| 280 | return retval;
|
| 281 | }
|
| 282 |
|
| 283 | |
| 284 | * pdc_pat_chassis_send_log - Sends a PDC PAT CHASSIS log message.
|
| 285 | * @state: state of the machine
|
| 286 | * @data: value for that state
|
| 287 | *
|
| 288 | * Must be correctly formatted or expect system crash
|
| 289 |
|
| 290 | #ifdef CONFIG_64BIT
|
| 291 | int pdc_pat_chassis_send_log(unsigned long state, unsigned long data)
|
| 292 | {
|
| 293 | int retval = 0;
|
| 294 | unsigned long flags;
|
| 295 |
|
| 296 | if (!is_pdc_pat())
|
| 297 | return -1;
|
| 298 |
|
| 299 | spin_lock_irqsave(&pdc_lock, flags);
|
| 300 | retval = mem_pdc_call(PDC_PAT_CHASSIS_LOG, PDC_PAT_CHASSIS_WRITE_LOG, __pa(&state), __pa(&data));
|
| 301 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 302 |
|
| 303 | return retval;
|
| 304 | }
|
| 305 | #endif
|
| 306 |
|
| 307 | |
| 308 | * pdc_chassis_disp - Updates chassis code
|
| 309 | * @disp: value to show on display
|
| 310 |
|
| 311 | int pdc_chassis_disp(unsigned long disp)
|
| 312 | {
|
| 313 | int retval = 0;
|
| 314 | unsigned long flags;
|
| 315 |
|
| 316 | spin_lock_irqsave(&pdc_lock, flags);
|
| 317 | retval = mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_DISP, disp);
|
| 318 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 319 |
|
| 320 | return retval;
|
| 321 | }
|
| 322 |
|
| 323 | |
| 324 | * __pdc_cpu_rendezvous - Stop currently executing CPU and do not return.
|
| 325 |
|
| 326 | int __pdc_cpu_rendezvous(void)
|
| 327 | {
|
| 328 | if (is_pdc_pat())
|
| 329 | return mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_RENDEZVOUS);
|
| 330 | else
|
| 331 | return mem_pdc_call(PDC_PROC, 1, 0);
|
| 332 | }
|
| 333 |
|
| 334 | |
| 335 | * pdc_cpu_rendezvous_lock - Lock PDC while transitioning to rendezvous state
|
| 336 |
|
| 337 | void pdc_cpu_rendezvous_lock(void) __acquires(&pdc_lock)
|
| 338 | {
|
| 339 | spin_lock(&pdc_lock);
|
| 340 | }
|
| 341 |
|
| 342 | |
| 343 | * pdc_cpu_rendezvous_unlock - Unlock PDC after reaching rendezvous state
|
| 344 |
|
| 345 | void pdc_cpu_rendezvous_unlock(void) __releases(&pdc_lock)
|
| 346 | {
|
| 347 | spin_unlock(&pdc_lock);
|
| 348 | }
|
| 349 |
|
| 350 | |
| 351 | * pdc_pat_get_PDC_entrypoint - Get PDC entry point for current CPU
|
| 352 | * @pdc_entry: pointer to where the PDC entry point should be stored
|
| 353 |
|
| 354 | int pdc_pat_get_PDC_entrypoint(unsigned long *pdc_entry)
|
| 355 | {
|
| 356 | int retval = 0;
|
| 357 | unsigned long flags;
|
| 358 |
|
| 359 | if (!IS_ENABLED(CONFIG_SMP) || !is_pdc_pat()) {
|
| 360 | *pdc_entry = MEM_PDC;
|
| 361 | return 0;
|
| 362 | }
|
| 363 |
|
| 364 | spin_lock_irqsave(&pdc_lock, flags);
|
| 365 | retval = mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_GET_PDC_ENTRYPOINT,
|
| 366 | __pa(pdc_result));
|
| 367 | *pdc_entry = pdc_result[0];
|
| 368 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 369 |
|
| 370 | return retval;
|
| 371 | }
|
| 372 | |
| 373 | * pdc_chassis_warn - Fetches chassis warnings
|
| 374 | * @warn: The warning value to be shown
|
| 375 |
|
| 376 | int pdc_chassis_warn(unsigned long *warn)
|
| 377 | {
|
| 378 | int retval = 0;
|
| 379 | unsigned long flags;
|
| 380 |
|
| 381 | spin_lock_irqsave(&pdc_lock, flags);
|
| 382 | retval = mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_WARN, __pa(pdc_result));
|
| 383 | *warn = pdc_result[0];
|
| 384 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 385 |
|
| 386 | return retval;
|
| 387 | }
|
| 388 |
|
| 389 | int pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info)
|
| 390 | {
|
| 391 | int ret;
|
| 392 |
|
| 393 | ret = mem_pdc_call(PDC_COPROC, PDC_COPROC_CFG, __pa(pdc_result));
|
| 394 | convert_to_wide(pdc_result);
|
| 395 | pdc_coproc_info->ccr_functional = pdc_result[0];
|
| 396 | pdc_coproc_info->ccr_present = pdc_result[1];
|
| 397 | pdc_coproc_info->revision = pdc_result[17];
|
| 398 | pdc_coproc_info->model = pdc_result[18];
|
| 399 |
|
| 400 | return ret;
|
| 401 | }
|
| 402 |
|
| 403 | |
| 404 | * pdc_coproc_cfg - To identify coprocessors attached to the processor.
|
| 405 | * @pdc_coproc_info: Return buffer address.
|
| 406 | *
|
| 407 | * This PDC call returns the presence and status of all the coprocessors
|
| 408 | * attached to the processor.
|
| 409 |
|
| 410 | int pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info)
|
| 411 | {
|
| 412 | int ret;
|
| 413 | unsigned long flags;
|
| 414 |
|
| 415 | spin_lock_irqsave(&pdc_lock, flags);
|
| 416 | ret = pdc_coproc_cfg_unlocked(pdc_coproc_info);
|
| 417 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 418 |
|
| 419 | return ret;
|
| 420 | }
|
| 421 |
|
| 422 | |
| 423 | * pdc_iodc_read - Read data from the modules IODC.
|
| 424 | * @actcnt: The actual number of bytes.
|
| 425 | * @hpa: The HPA of the module for the iodc read.
|
| 426 | * @index: The iodc entry point.
|
| 427 | * @iodc_data: A buffer memory for the iodc options.
|
| 428 | * @iodc_data_size: Size of the memory buffer.
|
| 429 | *
|
| 430 | * This PDC call reads from the IODC of the module specified by the hpa
|
| 431 | * argument.
|
| 432 |
|
| 433 | int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index,
|
| 434 | void *iodc_data, unsigned int iodc_data_size)
|
| 435 | {
|
| 436 | int retval;
|
| 437 | unsigned long flags;
|
| 438 |
|
| 439 | spin_lock_irqsave(&pdc_lock, flags);
|
| 440 | retval = mem_pdc_call(PDC_IODC, PDC_IODC_READ, __pa(pdc_result), hpa,
|
| 441 | index, __pa(pdc_result2), iodc_data_size);
|
| 442 | convert_to_wide(pdc_result);
|
| 443 | *actcnt = pdc_result[0];
|
| 444 | memcpy(iodc_data, pdc_result2, iodc_data_size);
|
| 445 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 446 |
|
| 447 | return retval;
|
| 448 | }
|
| 449 | EXPORT_SYMBOL(pdc_iodc_read);
|
| 450 |
|
| 451 | |
| 452 | * pdc_system_map_find_mods - Locate unarchitected modules.
|
| 453 | * @pdc_mod_info: Return buffer address.
|
| 454 | * @mod_path: pointer to dev path structure.
|
| 455 | * @mod_index: fixed address module index.
|
| 456 | *
|
| 457 | * To locate and identify modules which reside at fixed I/O addresses, which
|
| 458 | * do not self-identify via architected bus walks.
|
| 459 |
|
| 460 | int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info,
|
| 461 | struct pdc_module_path *mod_path, long mod_index)
|
| 462 | {
|
| 463 | int retval;
|
| 464 | unsigned long flags;
|
| 465 |
|
| 466 | spin_lock_irqsave(&pdc_lock, flags);
|
| 467 | memcpy(pdc_result2, mod_path, sizeof(*mod_path));
|
| 468 | retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result),
|
| 469 | __pa(pdc_result2), mod_index);
|
| 470 | convert_to_wide(pdc_result);
|
| 471 | memcpy(pdc_mod_info, pdc_result, sizeof(*pdc_mod_info));
|
| 472 | memcpy(mod_path, pdc_result2, sizeof(*mod_path));
|
| 473 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 474 |
|
| 475 | pdc_mod_info->mod_addr = f_extend(pdc_mod_info->mod_addr);
|
| 476 | return retval;
|
| 477 | }
|
| 478 |
|
| 479 | |
| 480 | * pdc_system_map_find_addrs - Retrieve additional address ranges.
|
| 481 | * @pdc_addr_info: Return buffer address.
|
| 482 | * @mod_index: Fixed address module index.
|
| 483 | * @addr_index: Address range index.
|
| 484 | *
|
| 485 | * Retrieve additional information about subsequent address ranges for modules
|
| 486 | * with multiple address ranges.
|
| 487 |
|
| 488 | int pdc_system_map_find_addrs(struct pdc_system_map_addr_info *pdc_addr_info,
|
| 489 | long mod_index, long addr_index)
|
| 490 | {
|
| 491 | int retval;
|
| 492 | unsigned long flags;
|
| 493 |
|
| 494 | spin_lock_irqsave(&pdc_lock, flags);
|
| 495 | retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_ADDRESS, __pa(pdc_result),
|
| 496 | mod_index, addr_index);
|
| 497 | convert_to_wide(pdc_result);
|
| 498 | memcpy(pdc_addr_info, pdc_result, sizeof(*pdc_addr_info));
|
| 499 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 500 |
|
| 501 | pdc_addr_info->mod_addr = f_extend(pdc_addr_info->mod_addr);
|
| 502 | return retval;
|
| 503 | }
|
| 504 |
|
| 505 | |
| 506 | * pdc_model_info - Return model information about the processor.
|
| 507 | * @model: The return buffer.
|
| 508 | *
|
| 509 | * Returns the version numbers, identifiers, and capabilities from the processor module.
|
| 510 |
|
| 511 | int pdc_model_info(struct pdc_model *model)
|
| 512 | {
|
| 513 | int retval;
|
| 514 | unsigned long flags;
|
| 515 |
|
| 516 | spin_lock_irqsave(&pdc_lock, flags);
|
| 517 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_INFO, __pa(pdc_result), 0);
|
| 518 | convert_to_wide(pdc_result);
|
| 519 | memcpy(model, pdc_result, sizeof(*model));
|
| 520 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 521 |
|
| 522 | return retval;
|
| 523 | }
|
| 524 |
|
| 525 | |
| 526 | * pdc_model_sysmodel - Get the system model name.
|
| 527 | * @os_id: The operating system ID asked for (an OS_ID_* value)
|
| 528 | * @name: A char array of at least 81 characters.
|
| 529 | *
|
| 530 | * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L).
|
| 531 | * Using OS_ID_HPUX will return the equivalent of the 'modelname' command
|
| 532 | * on HP/UX.
|
| 533 |
|
| 534 | int pdc_model_sysmodel(unsigned int os_id, char *name)
|
| 535 | {
|
| 536 | int retval;
|
| 537 | unsigned long flags;
|
| 538 |
|
| 539 | spin_lock_irqsave(&pdc_lock, flags);
|
| 540 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_SYSMODEL, __pa(pdc_result),
|
| 541 | os_id, __pa(name));
|
| 542 | convert_to_wide(pdc_result);
|
| 543 |
|
| 544 | if (retval == PDC_OK) {
|
| 545 | name[pdc_result[0]] = '\0';
|
| 546 | } else {
|
| 547 | name[0] = 0;
|
| 548 | }
|
| 549 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 550 |
|
| 551 | return retval;
|
| 552 | }
|
| 553 |
|
| 554 | |
| 555 | * pdc_model_versions - Identify the version number of each processor.
|
| 556 | * @versions: The return buffer.
|
| 557 | * @id: The id of the processor to check.
|
| 558 | *
|
| 559 | * Returns the version number for each processor component.
|
| 560 | *
|
| 561 | * This comment was here before, but I do not know what it means :( -RB
|
| 562 | * id: 0 = cpu revision, 1 = boot-rom-version
|
| 563 |
|
| 564 | int pdc_model_versions(unsigned long *versions, int id)
|
| 565 | {
|
| 566 | int retval;
|
| 567 | unsigned long flags;
|
| 568 |
|
| 569 | spin_lock_irqsave(&pdc_lock, flags);
|
| 570 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_VERSIONS, __pa(pdc_result), id);
|
| 571 | convert_to_wide(pdc_result);
|
| 572 | *versions = pdc_result[0];
|
| 573 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 574 |
|
| 575 | return retval;
|
| 576 | }
|
| 577 |
|
| 578 | |
| 579 | * pdc_model_cpuid - Returns the CPU_ID.
|
| 580 | * @cpu_id: The return buffer.
|
| 581 | *
|
| 582 | * Returns the CPU_ID value which uniquely identifies the cpu portion of
|
| 583 | * the processor module.
|
| 584 |
|
| 585 | int pdc_model_cpuid(unsigned long *cpu_id)
|
| 586 | {
|
| 587 | int retval;
|
| 588 | unsigned long flags;
|
| 589 |
|
| 590 | spin_lock_irqsave(&pdc_lock, flags);
|
| 591 | pdc_result[0] = 0;
|
| 592 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CPU_ID, __pa(pdc_result), 0);
|
| 593 | convert_to_wide(pdc_result);
|
| 594 | *cpu_id = pdc_result[0];
|
| 595 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 596 |
|
| 597 | return retval;
|
| 598 | }
|
| 599 |
|
| 600 | |
| 601 | * pdc_model_capabilities - Returns the platform capabilities.
|
| 602 | * @capabilities: The return buffer.
|
| 603 | *
|
| 604 | * Returns information about platform support for 32- and/or 64-bit
|
| 605 | * OSes, IO-PDIR coherency, and virtual aliasing.
|
| 606 |
|
| 607 | int pdc_model_capabilities(unsigned long *capabilities)
|
| 608 | {
|
| 609 | int retval;
|
| 610 | unsigned long flags;
|
| 611 |
|
| 612 | spin_lock_irqsave(&pdc_lock, flags);
|
| 613 | pdc_result[0] = 0;
|
| 614 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0);
|
| 615 | convert_to_wide(pdc_result);
|
| 616 | if (retval == PDC_OK) {
|
| 617 | *capabilities = pdc_result[0];
|
| 618 | } else {
|
| 619 | *capabilities = PDC_MODEL_OS32;
|
| 620 | }
|
| 621 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 622 |
|
| 623 | return retval;
|
| 624 | }
|
| 625 |
|
| 626 | |
| 627 | * pdc_model_platform_info - Returns machine product and serial number.
|
| 628 | * @orig_prod_num: Return buffer for original product number.
|
| 629 | * @current_prod_num: Return buffer for current product number.
|
| 630 | * @serial_no: Return buffer for serial number.
|
| 631 | *
|
| 632 | * Returns strings containing the original and current product numbers and the
|
| 633 | * serial number of the system.
|
| 634 |
|
| 635 | int pdc_model_platform_info(char *orig_prod_num, char *current_prod_num,
|
| 636 | char *serial_no)
|
| 637 | {
|
| 638 | int retval;
|
| 639 | unsigned long flags;
|
| 640 |
|
| 641 | spin_lock_irqsave(&pdc_lock, flags);
|
| 642 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_GET_PLATFORM_INFO,
|
| 643 | __pa(orig_prod_num), __pa(current_prod_num), __pa(serial_no));
|
| 644 | convert_to_wide(pdc_result);
|
| 645 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 646 |
|
| 647 | return retval;
|
| 648 | }
|
| 649 |
|
| 650 | |
| 651 | * pdc_cache_info - Return cache and TLB information.
|
| 652 | * @cache_info: The return buffer.
|
| 653 | *
|
| 654 | * Returns information about the processor's cache and TLB.
|
| 655 |
|
| 656 | int pdc_cache_info(struct pdc_cache_info *cache_info)
|
| 657 | {
|
| 658 | int retval;
|
| 659 | unsigned long flags;
|
| 660 |
|
| 661 | spin_lock_irqsave(&pdc_lock, flags);
|
| 662 | retval = mem_pdc_call(PDC_CACHE, PDC_CACHE_INFO, __pa(pdc_result), 0);
|
| 663 | convert_to_wide(pdc_result);
|
| 664 | memcpy(cache_info, pdc_result, sizeof(*cache_info));
|
| 665 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 666 |
|
| 667 | return retval;
|
| 668 | }
|
| 669 |
|
| 670 | |
| 671 | * pdc_spaceid_bits - Return whether Space ID hashing is turned on.
|
| 672 | * @space_bits: Should be 0, if not, bad mojo!
|
| 673 | *
|
| 674 | * Returns information about Space ID hashing.
|
| 675 |
|
| 676 | int pdc_spaceid_bits(unsigned long *space_bits)
|
| 677 | {
|
| 678 | int retval;
|
| 679 | unsigned long flags;
|
| 680 |
|
| 681 | spin_lock_irqsave(&pdc_lock, flags);
|
| 682 | pdc_result[0] = 0;
|
| 683 | retval = mem_pdc_call(PDC_CACHE, PDC_CACHE_RET_SPID, __pa(pdc_result), 0);
|
| 684 | convert_to_wide(pdc_result);
|
| 685 | *space_bits = pdc_result[0];
|
| 686 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 687 |
|
| 688 | return retval;
|
| 689 | }
|
| 690 |
|
| 691 | |
| 692 | * pdc_btlb_info - Return block TLB information.
|
| 693 | * @btlb: The return buffer.
|
| 694 | *
|
| 695 | * Returns information about the hardware Block TLB.
|
| 696 |
|
| 697 | int pdc_btlb_info(struct pdc_btlb_info *btlb)
|
| 698 | {
|
| 699 | int retval;
|
| 700 | unsigned long flags;
|
| 701 |
|
| 702 | if (IS_ENABLED(CONFIG_PA20))
|
| 703 | return PDC_BAD_PROC;
|
| 704 |
|
| 705 | spin_lock_irqsave(&pdc_lock, flags);
|
| 706 | retval = mem_pdc_call(PDC_BLOCK_TLB, PDC_BTLB_INFO, __pa(pdc_result), 0);
|
| 707 | memcpy(btlb, pdc_result, sizeof(*btlb));
|
| 708 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 709 |
|
| 710 | if(retval < 0) {
|
| 711 | btlb->max_size = 0;
|
| 712 | }
|
| 713 | return retval;
|
| 714 | }
|
| 715 |
|
| 716 | int pdc_btlb_insert(unsigned long long vpage, unsigned long physpage, unsigned long len,
|
| 717 | unsigned long entry_info, unsigned long slot)
|
| 718 | {
|
| 719 | int retval;
|
| 720 | unsigned long flags;
|
| 721 |
|
| 722 | if (IS_ENABLED(CONFIG_PA20))
|
| 723 | return PDC_BAD_PROC;
|
| 724 |
|
| 725 | spin_lock_irqsave(&pdc_lock, flags);
|
| 726 | retval = mem_pdc_call(PDC_BLOCK_TLB, PDC_BTLB_INSERT, (unsigned long) (vpage >> 32),
|
| 727 | (unsigned long) vpage, physpage, len, entry_info, slot);
|
| 728 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 729 | return retval;
|
| 730 | }
|
| 731 |
|
| 732 | int pdc_btlb_purge_all(void)
|
| 733 | {
|
| 734 | int retval;
|
| 735 | unsigned long flags;
|
| 736 |
|
| 737 | if (IS_ENABLED(CONFIG_PA20))
|
| 738 | return PDC_BAD_PROC;
|
| 739 |
|
| 740 | spin_lock_irqsave(&pdc_lock, flags);
|
| 741 | retval = mem_pdc_call(PDC_BLOCK_TLB, PDC_BTLB_PURGE_ALL);
|
| 742 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 743 | return retval;
|
| 744 | }
|
| 745 |
|
| 746 | |
| 747 | * pdc_mem_map_hpa - Find fixed module information.
|
| 748 | * @address: The return buffer
|
| 749 | * @mod_path: pointer to dev path structure.
|
| 750 | *
|
| 751 | * This call was developed for S700 workstations to allow the kernel to find
|
| 752 | * the I/O devices (Core I/O). In the future (Kittyhawk and beyond) this
|
| 753 | * call will be replaced (on workstations) by the architected PDC_SYSTEM_MAP
|
| 754 | * call.
|
| 755 | *
|
| 756 | * This call is supported by all existing S700 workstations (up to Gecko).
|
| 757 |
|
| 758 | int pdc_mem_map_hpa(struct pdc_memory_map *address,
|
| 759 | struct pdc_module_path *mod_path)
|
| 760 | {
|
| 761 | int retval;
|
| 762 | unsigned long flags;
|
| 763 |
|
| 764 | if (IS_ENABLED(CONFIG_PA20))
|
| 765 | return PDC_BAD_PROC;
|
| 766 |
|
| 767 | spin_lock_irqsave(&pdc_lock, flags);
|
| 768 | memcpy(pdc_result2, mod_path, sizeof(*mod_path));
|
| 769 | retval = mem_pdc_call(PDC_MEM_MAP, PDC_MEM_MAP_HPA, __pa(pdc_result),
|
| 770 | __pa(pdc_result2));
|
| 771 | memcpy(address, pdc_result, sizeof(*address));
|
| 772 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 773 |
|
| 774 | return retval;
|
| 775 | }
|
| 776 |
|
| 777 | |
| 778 | * pdc_lan_station_id - Get the LAN address.
|
| 779 | * @lan_addr: The return buffer.
|
| 780 | * @hpa: The network device HPA.
|
| 781 | *
|
| 782 | * Get the LAN station address when it is not directly available from the LAN hardware.
|
| 783 |
|
| 784 | int pdc_lan_station_id(char *lan_addr, unsigned long hpa)
|
| 785 | {
|
| 786 | int retval;
|
| 787 | unsigned long flags;
|
| 788 |
|
| 789 | spin_lock_irqsave(&pdc_lock, flags);
|
| 790 | retval = mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ,
|
| 791 | __pa(pdc_result), hpa);
|
| 792 | if (retval < 0) {
|
| 793 |
|
| 794 | memset(lan_addr, 0, PDC_LAN_STATION_ID_SIZE);
|
| 795 | } else {
|
| 796 | memcpy(lan_addr, pdc_result, PDC_LAN_STATION_ID_SIZE);
|
| 797 | }
|
| 798 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 799 |
|
| 800 | return retval;
|
| 801 | }
|
| 802 | EXPORT_SYMBOL(pdc_lan_station_id);
|
| 803 |
|
| 804 | |
| 805 | * pdc_stable_read - Read data from Stable Storage.
|
| 806 | * @staddr: Stable Storage address to access.
|
| 807 | * @memaddr: The memory address where Stable Storage data shall be copied.
|
| 808 | * @count: number of bytes to transfer. count is multiple of 4.
|
| 809 | *
|
| 810 | * This PDC call reads from the Stable Storage address supplied in staddr
|
| 811 | * and copies count bytes to the memory address memaddr.
|
| 812 | * The call will fail if staddr+count > PDC_STABLE size.
|
| 813 |
|
| 814 | int pdc_stable_read(unsigned long staddr, void *memaddr, unsigned long count)
|
| 815 | {
|
| 816 | int retval;
|
| 817 | unsigned long flags;
|
| 818 |
|
| 819 | spin_lock_irqsave(&pdc_lock, flags);
|
| 820 | retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_READ, staddr,
|
| 821 | __pa(pdc_result), count);
|
| 822 | convert_to_wide(pdc_result);
|
| 823 | memcpy(memaddr, pdc_result, count);
|
| 824 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 825 |
|
| 826 | return retval;
|
| 827 | }
|
| 828 | EXPORT_SYMBOL(pdc_stable_read);
|
| 829 |
|
| 830 | |
| 831 | * pdc_stable_write - Write data to Stable Storage.
|
| 832 | * @staddr: Stable Storage address to access.
|
| 833 | * @memaddr: The memory address where Stable Storage data shall be read from.
|
| 834 | * @count: number of bytes to transfer. count is multiple of 4.
|
| 835 | *
|
| 836 | * This PDC call reads count bytes from the supplied memaddr address,
|
| 837 | * and copies count bytes to the Stable Storage address staddr.
|
| 838 | * The call will fail if staddr+count > PDC_STABLE size.
|
| 839 |
|
| 840 | int pdc_stable_write(unsigned long staddr, void *memaddr, unsigned long count)
|
| 841 | {
|
| 842 | int retval;
|
| 843 | unsigned long flags;
|
| 844 |
|
| 845 | spin_lock_irqsave(&pdc_lock, flags);
|
| 846 | memcpy(pdc_result, memaddr, count);
|
| 847 | convert_to_wide(pdc_result);
|
| 848 | retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_WRITE, staddr,
|
| 849 | __pa(pdc_result), count);
|
| 850 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 851 |
|
| 852 | return retval;
|
| 853 | }
|
| 854 | EXPORT_SYMBOL(pdc_stable_write);
|
| 855 |
|
| 856 | |
| 857 | * pdc_stable_get_size - Get Stable Storage size in bytes.
|
| 858 | * @size: pointer where the size will be stored.
|
| 859 | *
|
| 860 | * This PDC call returns the number of bytes in the processor's Stable
|
| 861 | * Storage, which is the number of contiguous bytes implemented in Stable
|
| 862 | * Storage starting from staddr=0. size in an unsigned 64-bit integer
|
| 863 | * which is a multiple of four.
|
| 864 |
|
| 865 | int pdc_stable_get_size(unsigned long *size)
|
| 866 | {
|
| 867 | int retval;
|
| 868 | unsigned long flags;
|
| 869 |
|
| 870 | spin_lock_irqsave(&pdc_lock, flags);
|
| 871 | retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_RETURN_SIZE, __pa(pdc_result));
|
| 872 | *size = pdc_result[0];
|
| 873 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 874 |
|
| 875 | return retval;
|
| 876 | }
|
| 877 | EXPORT_SYMBOL(pdc_stable_get_size);
|
| 878 |
|
| 879 | |
| 880 | * pdc_stable_verify_contents - Checks that Stable Storage contents are valid.
|
| 881 | *
|
| 882 | * This PDC call is meant to be used to check the integrity of the current
|
| 883 | * contents of Stable Storage.
|
| 884 |
|
| 885 | int pdc_stable_verify_contents(void)
|
| 886 | {
|
| 887 | int retval;
|
| 888 | unsigned long flags;
|
| 889 |
|
| 890 | spin_lock_irqsave(&pdc_lock, flags);
|
| 891 | retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_VERIFY_CONTENTS);
|
| 892 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 893 |
|
| 894 | return retval;
|
| 895 | }
|
| 896 | EXPORT_SYMBOL(pdc_stable_verify_contents);
|
| 897 |
|
| 898 | |
| 899 | * pdc_stable_initialize - Sets Stable Storage contents to zero and initialize
|
| 900 | * the validity indicator.
|
| 901 | *
|
| 902 | * This PDC call will erase all contents of Stable Storage. Use with care!
|
| 903 |
|
| 904 | int pdc_stable_initialize(void)
|
| 905 | {
|
| 906 | int retval;
|
| 907 | unsigned long flags;
|
| 908 |
|
| 909 | spin_lock_irqsave(&pdc_lock, flags);
|
| 910 | retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_INITIALIZE);
|
| 911 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 912 |
|
| 913 | return retval;
|
| 914 | }
|
| 915 | EXPORT_SYMBOL(pdc_stable_initialize);
|
| 916 |
|
| 917 | |
| 918 | * pdc_get_initiator - Get the SCSI Interface Card params (SCSI ID, SDTR, SE or LVD)
|
| 919 | * @hwpath: fully bc.mod style path to the device.
|
| 920 | * @initiator: the array to return the result into
|
| 921 | *
|
| 922 | * Get the SCSI operational parameters from PDC.
|
| 923 | * Needed since HPUX never used BIOS or symbios card NVRAM.
|
| 924 | * Most ncr/sym cards won't have an entry and just use whatever
|
| 925 | * capabilities of the card are (eg Ultra, LVD). But there are
|
| 926 | * several cases where it's useful:
|
| 927 | * o set SCSI id for Multi-initiator clusters,
|
| 928 | * o cable too long (ie SE scsi 10Mhz won't support 6m length),
|
| 929 | * o bus width exported is less than what the interface chip supports.
|
| 930 |
|
| 931 | int pdc_get_initiator(struct hardware_path *hwpath, struct pdc_initiator *initiator)
|
| 932 | {
|
| 933 | int retval;
|
| 934 | unsigned long flags;
|
| 935 |
|
| 936 | spin_lock_irqsave(&pdc_lock, flags);
|
| 937 |
|
| 938 |
|
| 939 | #define IS_SPROCKETS() (strlen(boot_cpu_data.pdc.sys_model_name) == 14 && \
|
| 940 | strncmp(boot_cpu_data.pdc.sys_model_name, "9000/785", 8) == 0)
|
| 941 |
|
| 942 | retval = mem_pdc_call(PDC_INITIATOR, PDC_GET_INITIATOR,
|
| 943 | __pa(pdc_result), __pa(hwpath));
|
| 944 | if (retval < PDC_OK)
|
| 945 | goto out;
|
| 946 |
|
| 947 | if (pdc_result[0] < 16) {
|
| 948 | initiator->host_id = pdc_result[0];
|
| 949 | } else {
|
| 950 | initiator->host_id = -1;
|
| 951 | }
|
| 952 |
|
| 953 | |
| 954 | * Sprockets and Piranha return 20 or 40 (MT/s). Prelude returns
|
| 955 | * 1, 2, 5 or 10 for 5, 10, 20 or 40 MT/s, respectively
|
| 956 |
|
| 957 | switch (pdc_result[1]) {
|
| 958 | case 1: initiator->factor = 50; break;
|
| 959 | case 2: initiator->factor = 25; break;
|
| 960 | case 5: initiator->factor = 12; break;
|
| 961 | case 25: initiator->factor = 10; break;
|
| 962 | case 20: initiator->factor = 12; break;
|
| 963 | case 40: initiator->factor = 10; break;
|
| 964 | default: initiator->factor = -1; break;
|
| 965 | }
|
| 966 |
|
| 967 | if (IS_SPROCKETS()) {
|
| 968 | initiator->width = pdc_result[4];
|
| 969 | initiator->mode = pdc_result[5];
|
| 970 | } else {
|
| 971 | initiator->width = -1;
|
| 972 | initiator->mode = -1;
|
| 973 | }
|
| 974 |
|
| 975 | out:
|
| 976 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 977 |
|
| 978 | return (retval >= PDC_OK);
|
| 979 | }
|
| 980 | EXPORT_SYMBOL(pdc_get_initiator);
|
| 981 |
|
| 982 |
|
| 983 | |
| 984 | * pdc_pci_irt_size - Get the number of entries in the interrupt routing table.
|
| 985 | * @num_entries: The return value.
|
| 986 | * @hpa: The HPA for the device.
|
| 987 | *
|
| 988 | * This PDC function returns the number of entries in the specified cell's
|
| 989 | * interrupt table.
|
| 990 | * Similar to PDC_PAT stuff - but added for Forte/Allegro boxes
|
| 991 |
|
| 992 | int pdc_pci_irt_size(unsigned long *num_entries, unsigned long hpa)
|
| 993 | {
|
| 994 | int retval;
|
| 995 | unsigned long flags;
|
| 996 |
|
| 997 | spin_lock_irqsave(&pdc_lock, flags);
|
| 998 | retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE,
|
| 999 | __pa(pdc_result), hpa);
|
| 1000 | convert_to_wide(pdc_result);
|
| 1001 | *num_entries = pdc_result[0];
|
| 1002 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1003 |
|
| 1004 | return retval;
|
| 1005 | }
|
| 1006 |
|
| 1007 | |
| 1008 | * pdc_pci_irt - Get the PCI interrupt routing table.
|
| 1009 | * @num_entries: The number of entries in the table.
|
| 1010 | * @hpa: The Hard Physical Address of the device.
|
| 1011 | * @tbl:
|
| 1012 | *
|
| 1013 | * Get the PCI interrupt routing table for the device at the given HPA.
|
| 1014 | * Similar to PDC_PAT stuff - but added for Forte/Allegro boxes
|
| 1015 |
|
| 1016 | int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl)
|
| 1017 | {
|
| 1018 | int retval;
|
| 1019 | unsigned long flags;
|
| 1020 |
|
| 1021 | BUG_ON((unsigned long)tbl & 0x7);
|
| 1022 |
|
| 1023 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1024 | pdc_result[0] = num_entries;
|
| 1025 | retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL,
|
| 1026 | __pa(pdc_result), hpa, __pa(tbl));
|
| 1027 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1028 |
|
| 1029 | return retval;
|
| 1030 | }
|
| 1031 |
|
| 1032 |
|
| 1033 | #if 0 |
| 1034 |
|
| 1035 | /**
|
| 1036 | * pdc_pci_config_read - read PCI config space.
|
| 1037 | * @hpa: Token from PDC to indicate which PCI device
|
| 1038 | * @cfg_addr: Configuration space address to read from
|
| 1039 | *
|
| 1040 | * Read PCI Configuration space *before* linux PCI subsystem is running.
|
| 1041 | */
|
| 1042 | unsigned int pdc_pci_config_read(void *hpa, unsigned long cfg_addr)
|
| 1043 | {
|
| 1044 | int retval;
|
| 1045 | unsigned long flags;
|
| 1046 |
|
| 1047 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1048 | pdc_result[0] = 0;
|
| 1049 | pdc_result[1] = 0;
|
| 1050 | retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_READ_CONFIG,
|
| 1051 | __pa(pdc_result), hpa, cfg_addr&~3UL, 4UL);
|
| 1052 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1053 |
|
| 1054 | return retval ? ~0 : (unsigned int) pdc_result[0];
|
| 1055 | }
|
| 1056 |
|
| 1057 |
|
| 1058 | /**
|
| 1059 | * pdc_pci_config_write - read PCI config space.
|
| 1060 | * @hpa: Token from PDC to indicate which PCI device
|
| 1061 | * @cfg_addr: Configuration space address to write
|
| 1062 | * @val: Value we want in the 32-bit register
|
| 1063 | *
|
| 1064 | * Write PCI Configuration space *before* linux PCI subsystem is running.
|
| 1065 | */
|
| 1066 | void pdc_pci_config_write(void *hpa, unsigned long cfg_addr, unsigned int val)
|
| 1067 | {
|
| 1068 | int retval;
|
| 1069 | unsigned long flags;
|
| 1070 |
|
| 1071 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1072 | pdc_result[0] = 0;
|
| 1073 | retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_WRITE_CONFIG,
|
| 1074 | __pa(pdc_result), hpa,
|
| 1075 | cfg_addr&~3UL, 4UL, (unsigned long) val);
|
| 1076 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1077 |
|
| 1078 | return retval;
|
| 1079 | }
|
| 1080 | #endif
|
| 1081 |
|
| 1082 | |
| 1083 | * pdc_tod_read - Read the Time-Of-Day clock.
|
| 1084 | * @tod: The return buffer:
|
| 1085 | *
|
| 1086 | * Read the Time-Of-Day clock
|
| 1087 |
|
| 1088 | int pdc_tod_read(struct pdc_tod *tod)
|
| 1089 | {
|
| 1090 | int retval;
|
| 1091 | unsigned long flags;
|
| 1092 |
|
| 1093 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1094 | retval = mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(pdc_result), 0);
|
| 1095 | convert_to_wide(pdc_result);
|
| 1096 | memcpy(tod, pdc_result, sizeof(*tod));
|
| 1097 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1098 |
|
| 1099 | return retval;
|
| 1100 | }
|
| 1101 | EXPORT_SYMBOL(pdc_tod_read);
|
| 1102 |
|
| 1103 | int pdc_mem_pdt_info(struct pdc_mem_retinfo *rinfo)
|
| 1104 | {
|
| 1105 | int retval;
|
| 1106 | unsigned long flags;
|
| 1107 |
|
| 1108 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1109 | retval = mem_pdc_call(PDC_MEM, PDC_MEM_MEMINFO, __pa(pdc_result), 0);
|
| 1110 | convert_to_wide(pdc_result);
|
| 1111 | memcpy(rinfo, pdc_result, sizeof(*rinfo));
|
| 1112 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1113 |
|
| 1114 | return retval;
|
| 1115 | }
|
| 1116 |
|
| 1117 | int pdc_mem_pdt_read_entries(struct pdc_mem_read_pdt *pret,
|
| 1118 | unsigned long *pdt_entries_ptr)
|
| 1119 | {
|
| 1120 | int retval;
|
| 1121 | unsigned long flags;
|
| 1122 |
|
| 1123 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1124 | retval = mem_pdc_call(PDC_MEM, PDC_MEM_READ_PDT, __pa(pdc_result),
|
| 1125 | __pa(pdt_entries_ptr));
|
| 1126 | if (retval == PDC_OK) {
|
| 1127 | convert_to_wide(pdc_result);
|
| 1128 | memcpy(pret, pdc_result, sizeof(*pret));
|
| 1129 | }
|
| 1130 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1131 |
|
| 1132 | #ifdef CONFIG_64BIT
|
| 1133 | |
| 1134 | * 64-bit kernels should not call this PDT function in narrow mode.
|
| 1135 | * The pdt_entries_ptr array above will now contain 32-bit values
|
| 1136 |
|
| 1137 | if (WARN_ON_ONCE((retval == PDC_OK) && parisc_narrow_firmware))
|
| 1138 | return PDC_ERROR;
|
| 1139 | #endif
|
| 1140 |
|
| 1141 | return retval;
|
| 1142 | }
|
| 1143 |
|
| 1144 | |
| 1145 | * pdc_pim_toc11 - Fetch TOC PIM 1.1 data from firmware.
|
| 1146 | * @ret: pointer to return buffer
|
| 1147 |
|
| 1148 | int pdc_pim_toc11(struct pdc_toc_pim_11 *ret)
|
| 1149 | {
|
| 1150 | int retval;
|
| 1151 | unsigned long flags;
|
| 1152 |
|
| 1153 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1154 | retval = mem_pdc_call(PDC_PIM, PDC_PIM_TOC, __pa(pdc_result),
|
| 1155 | __pa(ret), sizeof(*ret));
|
| 1156 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1157 | return retval;
|
| 1158 | }
|
| 1159 |
|
| 1160 | |
| 1161 | * pdc_pim_toc20 - Fetch TOC PIM 2.0 data from firmware.
|
| 1162 | * @ret: pointer to return buffer
|
| 1163 |
|
| 1164 | int pdc_pim_toc20(struct pdc_toc_pim_20 *ret)
|
| 1165 | {
|
| 1166 | int retval;
|
| 1167 | unsigned long flags;
|
| 1168 |
|
| 1169 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1170 | retval = mem_pdc_call(PDC_PIM, PDC_PIM_TOC, __pa(pdc_result),
|
| 1171 | __pa(ret), sizeof(*ret));
|
| 1172 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1173 | return retval;
|
| 1174 | }
|
| 1175 |
|
| 1176 | |
| 1177 | * pdc_tod_set - Set the Time-Of-Day clock.
|
| 1178 | * @sec: The number of seconds since epoch.
|
| 1179 | * @usec: The number of micro seconds.
|
| 1180 | *
|
| 1181 | * Set the Time-Of-Day clock.
|
| 1182 |
|
| 1183 | int pdc_tod_set(unsigned long sec, unsigned long usec)
|
| 1184 | {
|
| 1185 | int retval;
|
| 1186 | unsigned long flags;
|
| 1187 |
|
| 1188 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1189 | retval = mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec);
|
| 1190 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1191 |
|
| 1192 | return retval;
|
| 1193 | }
|
| 1194 | EXPORT_SYMBOL(pdc_tod_set);
|
| 1195 |
|
| 1196 | #ifdef CONFIG_64BIT
|
| 1197 | int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr,
|
| 1198 | struct pdc_memory_table *tbl, unsigned long entries)
|
| 1199 | {
|
| 1200 | int retval;
|
| 1201 | unsigned long flags;
|
| 1202 |
|
| 1203 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1204 | retval = mem_pdc_call(PDC_MEM, PDC_MEM_TABLE, __pa(pdc_result), __pa(pdc_result2), entries);
|
| 1205 | convert_to_wide(pdc_result);
|
| 1206 | memcpy(r_addr, pdc_result, sizeof(*r_addr));
|
| 1207 | memcpy(tbl, pdc_result2, entries * sizeof(*tbl));
|
| 1208 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1209 |
|
| 1210 | return retval;
|
| 1211 | }
|
| 1212 | #endif
|
| 1213 |
|
| 1214 | |
| 1215 | * so I guessed at unsigned long. Someone who knows what this does, can fix
|
| 1216 | * it later. :)
|
| 1217 |
|
| 1218 | int pdc_do_firm_test_reset(unsigned long ftc_bitmap)
|
| 1219 | {
|
| 1220 | int retval;
|
| 1221 | unsigned long flags;
|
| 1222 |
|
| 1223 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1224 | retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_FIRM_TEST_RESET,
|
| 1225 | PDC_FIRM_TEST_MAGIC, ftc_bitmap);
|
| 1226 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1227 |
|
| 1228 | return retval;
|
| 1229 | }
|
| 1230 |
|
| 1231 | |
| 1232 | * pdc_do_reset - Reset the system.
|
| 1233 | *
|
| 1234 | * Reset the system.
|
| 1235 |
|
| 1236 | int pdc_do_reset(void)
|
| 1237 | {
|
| 1238 | int retval;
|
| 1239 | unsigned long flags;
|
| 1240 |
|
| 1241 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1242 | retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_RESET);
|
| 1243 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1244 |
|
| 1245 | return retval;
|
| 1246 | }
|
| 1247 |
|
| 1248 | |
| 1249 | * pdc_soft_power_info - Enable soft power switch.
|
| 1250 | * @power_reg: address of soft power register
|
| 1251 | *
|
| 1252 | * Return the absolute address of the soft power switch register
|
| 1253 |
|
| 1254 | int __init pdc_soft_power_info(unsigned long *power_reg)
|
| 1255 | {
|
| 1256 | int retval;
|
| 1257 | unsigned long flags;
|
| 1258 |
|
| 1259 | *power_reg = (unsigned long) (-1);
|
| 1260 |
|
| 1261 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1262 | retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_INFO, __pa(pdc_result), 0);
|
| 1263 | if (retval == PDC_OK) {
|
| 1264 | convert_to_wide(pdc_result);
|
| 1265 | *power_reg = f_extend(pdc_result[0]);
|
| 1266 | }
|
| 1267 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1268 |
|
| 1269 | return retval;
|
| 1270 | }
|
| 1271 |
|
| 1272 | |
| 1273 | * pdc_soft_power_button{_panic} - Control the soft power button behaviour
|
| 1274 | * @sw_control: 0 for hardware control, 1 for software control
|
| 1275 | *
|
| 1276 | *
|
| 1277 | * This PDC function places the soft power button under software or
|
| 1278 | * hardware control.
|
| 1279 | * Under software control the OS may control to when to allow to shut
|
| 1280 | * down the system. Under hardware control pressing the power button
|
| 1281 | * powers off the system immediately.
|
| 1282 | *
|
| 1283 | * The _panic version relies on spin_trylock to prevent deadlock
|
| 1284 | * on panic path.
|
| 1285 |
|
| 1286 | int pdc_soft_power_button(int sw_control)
|
| 1287 | {
|
| 1288 | int retval;
|
| 1289 | unsigned long flags;
|
| 1290 |
|
| 1291 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1292 | retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_ENABLE, __pa(pdc_result), sw_control);
|
| 1293 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1294 |
|
| 1295 | return retval;
|
| 1296 | }
|
| 1297 |
|
| 1298 | int pdc_soft_power_button_panic(int sw_control)
|
| 1299 | {
|
| 1300 | int retval;
|
| 1301 | unsigned long flags;
|
| 1302 |
|
| 1303 | if (!spin_trylock_irqsave(&pdc_lock, flags)) {
|
| 1304 | pr_emerg("Couldn't enable soft power button\n");
|
| 1305 | return -EBUSY;
|
| 1306 | }
|
| 1307 |
|
| 1308 | retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_ENABLE, __pa(pdc_result), sw_control);
|
| 1309 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1310 |
|
| 1311 | return retval;
|
| 1312 | }
|
| 1313 |
|
| 1314 | |
| 1315 | * pdc_io_reset - Hack to avoid overlapping range registers of Bridges devices.
|
| 1316 | * Primarily a problem on T600 (which parisc-linux doesn't support) but
|
| 1317 | * who knows what other platform firmware might do with this OS "hook".
|
| 1318 |
|
| 1319 | void pdc_io_reset(void)
|
| 1320 | {
|
| 1321 | unsigned long flags;
|
| 1322 |
|
| 1323 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1324 | mem_pdc_call(PDC_IO, PDC_IO_RESET, 0);
|
| 1325 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1326 | }
|
| 1327 |
|
| 1328 | |
| 1329 | * pdc_io_reset_devices - Hack to Stop USB controller
|
| 1330 | *
|
| 1331 | * If PDC used the usb controller, the usb controller
|
| 1332 | * is still running and will crash the machines during iommu
|
| 1333 | * setup, because of still running DMA. This PDC call
|
| 1334 | * stops the USB controller.
|
| 1335 | * Normally called after calling pdc_io_reset().
|
| 1336 |
|
| 1337 | void pdc_io_reset_devices(void)
|
| 1338 | {
|
| 1339 | unsigned long flags;
|
| 1340 |
|
| 1341 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1342 | mem_pdc_call(PDC_IO, PDC_IO_RESET_DEVICES, 0);
|
| 1343 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1344 | }
|
| 1345 |
|
| 1346 | #endif
|
| 1347 |
|
| 1348 |
|
| 1349 | static char iodc_dbuf[4096] __page_aligned_bss;
|
| 1350 |
|
| 1351 | |
| 1352 | * pdc_iodc_print - Console print using IODC.
|
| 1353 | * @str: the string to output.
|
| 1354 | * @count: length of str
|
| 1355 | *
|
| 1356 | * Note that only these special chars are architected for console IODC io:
|
| 1357 | * BEL, BS, CR, and LF. Others are passed through.
|
| 1358 | * Since the HP console requires CR+LF to perform a 'newline', we translate
|
| 1359 | * "\n" to "\r\n".
|
| 1360 |
|
| 1361 | int pdc_iodc_print(const unsigned char *str, unsigned count)
|
| 1362 | {
|
| 1363 | unsigned int i, found = 0;
|
| 1364 | unsigned long flags;
|
| 1365 |
|
| 1366 | count = min_t(unsigned int, count, sizeof(iodc_dbuf));
|
| 1367 |
|
| 1368 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1369 | for (i = 0; i < count;) {
|
| 1370 | switch(str[i]) {
|
| 1371 | case '\n':
|
| 1372 | iodc_dbuf[i+0] = '\r';
|
| 1373 | iodc_dbuf[i+1] = '\n';
|
| 1374 | i += 2;
|
| 1375 | found = 1;
|
| 1376 | goto print;
|
| 1377 | default:
|
| 1378 | iodc_dbuf[i] = str[i];
|
| 1379 | i++;
|
| 1380 | break;
|
| 1381 | }
|
| 1382 | }
|
| 1383 |
|
| 1384 | print:
|
| 1385 | real32_call(PAGE0->mem_cons.iodc_io,
|
| 1386 | (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
|
| 1387 | PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
|
| 1388 | __pa(pdc_result), 0, __pa(iodc_dbuf), i, 0);
|
| 1389 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1390 |
|
| 1391 | return i - found;
|
| 1392 | }
|
| 1393 |
|
| 1394 | #if !defined(BOOTLOADER)
|
| 1395 | |
| 1396 | * pdc_iodc_getc - Read a character (non-blocking) from the PDC console.
|
| 1397 | *
|
| 1398 | * Read a character (non-blocking) from the PDC console, returns -1 if
|
| 1399 | * key is not present.
|
| 1400 |
|
| 1401 | int pdc_iodc_getc(void)
|
| 1402 | {
|
| 1403 | int ch;
|
| 1404 | int status;
|
| 1405 | unsigned long flags;
|
| 1406 |
|
| 1407 |
|
| 1408 | if (!PAGE0->mem_kbd.iodc_io)
|
| 1409 | return 0;
|
| 1410 |
|
| 1411 |
|
| 1412 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1413 | real32_call(PAGE0->mem_kbd.iodc_io,
|
| 1414 | (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN,
|
| 1415 | PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers),
|
| 1416 | __pa(pdc_result), 0, __pa(iodc_dbuf), 1, 0);
|
| 1417 |
|
| 1418 | ch = *iodc_dbuf;
|
| 1419 |
|
| 1420 | status = *(int *)&pdc_result;
|
| 1421 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1422 |
|
| 1423 | if (status == 0)
|
| 1424 | return -1;
|
| 1425 |
|
| 1426 | return ch;
|
| 1427 | }
|
| 1428 |
|
| 1429 | int pdc_sti_call(unsigned long func, unsigned long flags,
|
| 1430 | unsigned long inptr, unsigned long outputr,
|
| 1431 | unsigned long glob_cfg, int do_call64)
|
| 1432 | {
|
| 1433 | int retval = 0;
|
| 1434 | unsigned long irqflags;
|
| 1435 |
|
| 1436 | spin_lock_irqsave(&pdc_lock, irqflags);
|
| 1437 | if (IS_ENABLED(CONFIG_64BIT) && do_call64) {
|
| 1438 | #ifdef CONFIG_64BIT
|
| 1439 | retval = real64_call(func, flags, inptr, outputr, glob_cfg);
|
| 1440 | #else
|
| 1441 | WARN_ON(1);
|
| 1442 | #endif
|
| 1443 | } else {
|
| 1444 | retval = real32_call(func, flags, inptr, outputr, glob_cfg);
|
| 1445 | }
|
| 1446 | spin_unlock_irqrestore(&pdc_lock, irqflags);
|
| 1447 |
|
| 1448 | return retval;
|
| 1449 | }
|
| 1450 | EXPORT_SYMBOL(pdc_sti_call);
|
| 1451 |
|
| 1452 | #ifdef CONFIG_64BIT
|
| 1453 | |
| 1454 | * pdc_pat_cell_get_number - Returns the cell number.
|
| 1455 | * @cell_info: The return buffer.
|
| 1456 | *
|
| 1457 | * This PDC call returns the cell number of the cell from which the call
|
| 1458 | * is made.
|
| 1459 |
|
| 1460 | int pdc_pat_cell_get_number(struct pdc_pat_cell_num *cell_info)
|
| 1461 | {
|
| 1462 | int retval;
|
| 1463 | unsigned long flags;
|
| 1464 |
|
| 1465 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1466 | retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_GET_NUMBER, __pa(pdc_result));
|
| 1467 | memcpy(cell_info, pdc_result, sizeof(*cell_info));
|
| 1468 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1469 |
|
| 1470 | return retval;
|
| 1471 | }
|
| 1472 |
|
| 1473 | |
| 1474 | * pdc_pat_cell_module - Retrieve the cell's module information.
|
| 1475 | * @actcnt: The number of bytes written to mem_addr.
|
| 1476 | * @ploc: The physical location.
|
| 1477 | * @mod: The module index.
|
| 1478 | * @view_type: The view of the address type.
|
| 1479 | * @mem_addr: The return buffer.
|
| 1480 | *
|
| 1481 | * This PDC call returns information about each module attached to the cell
|
| 1482 | * at the specified location.
|
| 1483 |
|
| 1484 | int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod,
|
| 1485 | unsigned long view_type, void *mem_addr)
|
| 1486 | {
|
| 1487 | int retval;
|
| 1488 | unsigned long flags;
|
| 1489 | static struct pdc_pat_cell_mod_maddr_block result __attribute__ ((aligned (8)));
|
| 1490 |
|
| 1491 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1492 | retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_MODULE, __pa(pdc_result),
|
| 1493 | ploc, mod, view_type, __pa(&result));
|
| 1494 | if(!retval) {
|
| 1495 | *actcnt = pdc_result[0];
|
| 1496 | memcpy(mem_addr, &result, *actcnt);
|
| 1497 | }
|
| 1498 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1499 |
|
| 1500 | return retval;
|
| 1501 | }
|
| 1502 |
|
| 1503 | |
| 1504 | * pdc_pat_cell_info - Retrieve the cell's information.
|
| 1505 | * @info: The pointer to a struct pdc_pat_cell_info_rtn_block.
|
| 1506 | * @actcnt: The number of bytes which should be written to info.
|
| 1507 | * @offset: offset of the structure.
|
| 1508 | * @cell_number: The cell number which should be asked, or -1 for current cell.
|
| 1509 | *
|
| 1510 | * This PDC call returns information about the given cell (or all cells).
|
| 1511 |
|
| 1512 | int pdc_pat_cell_info(struct pdc_pat_cell_info_rtn_block *info,
|
| 1513 | unsigned long *actcnt, unsigned long offset,
|
| 1514 | unsigned long cell_number)
|
| 1515 | {
|
| 1516 | int retval;
|
| 1517 | unsigned long flags;
|
| 1518 | struct pdc_pat_cell_info_rtn_block result;
|
| 1519 |
|
| 1520 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1521 | retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_GET_INFO,
|
| 1522 | __pa(pdc_result), __pa(&result), *actcnt,
|
| 1523 | offset, cell_number);
|
| 1524 | if (!retval) {
|
| 1525 | *actcnt = pdc_result[0];
|
| 1526 | memcpy(info, &result, *actcnt);
|
| 1527 | }
|
| 1528 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1529 |
|
| 1530 | return retval;
|
| 1531 | }
|
| 1532 |
|
| 1533 | |
| 1534 | * pdc_pat_cpu_get_number - Retrieve the cpu number.
|
| 1535 | * @cpu_info: The return buffer.
|
| 1536 | * @hpa: The Hard Physical Address of the CPU.
|
| 1537 | *
|
| 1538 | * Retrieve the cpu number for the cpu at the specified HPA.
|
| 1539 |
|
| 1540 | int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, unsigned long hpa)
|
| 1541 | {
|
| 1542 | int retval;
|
| 1543 | unsigned long flags;
|
| 1544 |
|
| 1545 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1546 | retval = mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_GET_NUMBER,
|
| 1547 | __pa(&pdc_result), hpa);
|
| 1548 | memcpy(cpu_info, pdc_result, sizeof(*cpu_info));
|
| 1549 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1550 |
|
| 1551 | return retval;
|
| 1552 | }
|
| 1553 |
|
| 1554 | |
| 1555 | * pdc_pat_get_irt_size - Retrieve the number of entries in the cell's interrupt table.
|
| 1556 | * @num_entries: The return value.
|
| 1557 | * @cell_num: The target cell.
|
| 1558 | *
|
| 1559 | * This PDC function returns the number of entries in the specified cell's
|
| 1560 | * interrupt table.
|
| 1561 |
|
| 1562 | int pdc_pat_get_irt_size(unsigned long *num_entries, unsigned long cell_num)
|
| 1563 | {
|
| 1564 | int retval;
|
| 1565 | unsigned long flags;
|
| 1566 |
|
| 1567 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1568 | retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE_SIZE,
|
| 1569 | __pa(pdc_result), cell_num);
|
| 1570 | *num_entries = pdc_result[0];
|
| 1571 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1572 |
|
| 1573 | return retval;
|
| 1574 | }
|
| 1575 |
|
| 1576 | |
| 1577 | * pdc_pat_get_irt - Retrieve the cell's interrupt table.
|
| 1578 | * @r_addr: The return buffer.
|
| 1579 | * @cell_num: The target cell.
|
| 1580 | *
|
| 1581 | * This PDC function returns the actual interrupt table for the specified cell.
|
| 1582 |
|
| 1583 | int pdc_pat_get_irt(void *r_addr, unsigned long cell_num)
|
| 1584 | {
|
| 1585 | int retval;
|
| 1586 | unsigned long flags;
|
| 1587 |
|
| 1588 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1589 | retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE,
|
| 1590 | __pa(r_addr), cell_num);
|
| 1591 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1592 |
|
| 1593 | return retval;
|
| 1594 | }
|
| 1595 |
|
| 1596 | |
| 1597 | * pdc_pat_pd_get_addr_map - Retrieve information about memory address ranges.
|
| 1598 | * @actual_len: The return buffer.
|
| 1599 | * @mem_addr: Pointer to the memory buffer.
|
| 1600 | * @count: The number of bytes to read from the buffer.
|
| 1601 | * @offset: The offset with respect to the beginning of the buffer.
|
| 1602 | *
|
| 1603 |
|
| 1604 | int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr,
|
| 1605 | unsigned long count, unsigned long offset)
|
| 1606 | {
|
| 1607 | int retval;
|
| 1608 | unsigned long flags;
|
| 1609 |
|
| 1610 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1611 | retval = mem_pdc_call(PDC_PAT_PD, PDC_PAT_PD_GET_ADDR_MAP, __pa(pdc_result),
|
| 1612 | __pa(pdc_result2), count, offset);
|
| 1613 | *actual_len = pdc_result[0];
|
| 1614 | memcpy(mem_addr, pdc_result2, *actual_len);
|
| 1615 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1616 |
|
| 1617 | return retval;
|
| 1618 | }
|
| 1619 |
|
| 1620 | |
| 1621 | * pdc_pat_pd_get_pdc_revisions - Retrieve PDC interface revisions.
|
| 1622 | * @legacy_rev: The legacy revision.
|
| 1623 | * @pat_rev: The PAT revision.
|
| 1624 | * @pdc_cap: The PDC capabilities.
|
| 1625 | *
|
| 1626 |
|
| 1627 | int pdc_pat_pd_get_pdc_revisions(unsigned long *legacy_rev,
|
| 1628 | unsigned long *pat_rev, unsigned long *pdc_cap)
|
| 1629 | {
|
| 1630 | int retval;
|
| 1631 | unsigned long flags;
|
| 1632 |
|
| 1633 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1634 | retval = mem_pdc_call(PDC_PAT_PD, PDC_PAT_PD_GET_PDC_INTERF_REV,
|
| 1635 | __pa(pdc_result));
|
| 1636 | if (retval == PDC_OK) {
|
| 1637 | *legacy_rev = pdc_result[0];
|
| 1638 | *pat_rev = pdc_result[1];
|
| 1639 | *pdc_cap = pdc_result[2];
|
| 1640 | }
|
| 1641 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1642 |
|
| 1643 | return retval;
|
| 1644 | }
|
| 1645 |
|
| 1646 | |
| 1647 | * pdc_pat_pd_get_platform_counter - Retrieve address of free-running 64-bit counter.
|
| 1648 | * @addr: The address of the 64-bit counter.
|
| 1649 | * @freq: The frequency of the counter, or -1 if unknown.
|
| 1650 | * @unique: Although monotonic growing, may it return the same number twice?
|
| 1651 | *
|
| 1652 |
|
| 1653 | int pdc_pat_pd_get_platform_counter(uint64_t **addr,
|
| 1654 | unsigned long *freq, unsigned long *unique)
|
| 1655 | {
|
| 1656 | int retval;
|
| 1657 | unsigned long flags;
|
| 1658 |
|
| 1659 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1660 | retval = mem_pdc_call(PDC_PAT_PD, PDC_PAT_PD_GET_PLATFORM_COUNTER,
|
| 1661 | __pa(pdc_result));
|
| 1662 | if (retval == PDC_OK) {
|
| 1663 | *addr = (uint64_t *)pdc_result[0];
|
| 1664 | *freq = pdc_result[1];
|
| 1665 | *unique = pdc_result[2];
|
| 1666 | }
|
| 1667 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1668 |
|
| 1669 | return retval;
|
| 1670 | }
|
| 1671 |
|
| 1672 | |
| 1673 | * pdc_pat_io_pci_cfg_read - Read PCI configuration space.
|
| 1674 | * @pci_addr: PCI configuration space address for which the read request is being made.
|
| 1675 | * @pci_size: Size of read in bytes. Valid values are 1, 2, and 4.
|
| 1676 | * @mem_addr: Pointer to return memory buffer.
|
| 1677 | *
|
| 1678 |
|
| 1679 | int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *mem_addr)
|
| 1680 | {
|
| 1681 | int retval;
|
| 1682 | unsigned long flags;
|
| 1683 |
|
| 1684 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1685 | retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_READ,
|
| 1686 | __pa(pdc_result), pci_addr, pci_size);
|
| 1687 | switch(pci_size) {
|
| 1688 | case 1: *(u8 *) mem_addr = (u8) pdc_result[0]; break;
|
| 1689 | case 2: *(u16 *)mem_addr = (u16) pdc_result[0]; break;
|
| 1690 | case 4: *(u32 *)mem_addr = (u32) pdc_result[0]; break;
|
| 1691 | }
|
| 1692 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1693 |
|
| 1694 | return retval;
|
| 1695 | }
|
| 1696 |
|
| 1697 | |
| 1698 | * pdc_pat_io_pci_cfg_write - Retrieve information about memory address ranges.
|
| 1699 | * @pci_addr: PCI configuration space address for which the write request is being made.
|
| 1700 | * @pci_size: Size of write in bytes. Valid values are 1, 2, and 4.
|
| 1701 | * @val: Pointer to 1, 2, or 4 byte value in low order end of argument to be
|
| 1702 | * written to PCI Config space.
|
| 1703 | *
|
| 1704 |
|
| 1705 | int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 val)
|
| 1706 | {
|
| 1707 | int retval;
|
| 1708 | unsigned long flags;
|
| 1709 |
|
| 1710 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1711 | retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_WRITE,
|
| 1712 | pci_addr, pci_size, val);
|
| 1713 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1714 |
|
| 1715 | return retval;
|
| 1716 | }
|
| 1717 |
|
| 1718 | |
| 1719 | * pdc_pat_mem_pdt_info - Retrieve information about page deallocation table
|
| 1720 | * @rinfo: memory pdt information
|
| 1721 | *
|
| 1722 |
|
| 1723 | int pdc_pat_mem_pdt_info(struct pdc_pat_mem_retinfo *rinfo)
|
| 1724 | {
|
| 1725 | int retval;
|
| 1726 | unsigned long flags;
|
| 1727 |
|
| 1728 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1729 | retval = mem_pdc_call(PDC_PAT_MEM, PDC_PAT_MEM_PD_INFO,
|
| 1730 | __pa(&pdc_result));
|
| 1731 | if (retval == PDC_OK)
|
| 1732 | memcpy(rinfo, &pdc_result, sizeof(*rinfo));
|
| 1733 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1734 |
|
| 1735 | return retval;
|
| 1736 | }
|
| 1737 |
|
| 1738 | |
| 1739 | * pdc_pat_mem_pdt_cell_info - Retrieve information about page deallocation
|
| 1740 | * table of a cell
|
| 1741 | * @rinfo: memory pdt information
|
| 1742 | * @cell: cell number
|
| 1743 | *
|
| 1744 |
|
| 1745 | int pdc_pat_mem_pdt_cell_info(struct pdc_pat_mem_cell_pdt_retinfo *rinfo,
|
| 1746 | unsigned long cell)
|
| 1747 | {
|
| 1748 | int retval;
|
| 1749 | unsigned long flags;
|
| 1750 |
|
| 1751 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1752 | retval = mem_pdc_call(PDC_PAT_MEM, PDC_PAT_MEM_CELL_INFO,
|
| 1753 | __pa(&pdc_result), cell);
|
| 1754 | if (retval == PDC_OK)
|
| 1755 | memcpy(rinfo, &pdc_result, sizeof(*rinfo));
|
| 1756 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1757 |
|
| 1758 | return retval;
|
| 1759 | }
|
| 1760 |
|
| 1761 | |
| 1762 | * pdc_pat_mem_read_cell_pdt - Read PDT entries from (old) PAT firmware
|
| 1763 | * @pret: array of PDT entries
|
| 1764 | * @pdt_entries_ptr: ptr to hold number of PDT entries
|
| 1765 | * @max_entries: maximum number of entries to be read
|
| 1766 | *
|
| 1767 |
|
| 1768 | int pdc_pat_mem_read_cell_pdt(struct pdc_pat_mem_read_pd_retinfo *pret,
|
| 1769 | unsigned long *pdt_entries_ptr, unsigned long max_entries)
|
| 1770 | {
|
| 1771 | int retval;
|
| 1772 | unsigned long flags, entries;
|
| 1773 |
|
| 1774 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1775 |
|
| 1776 | retval = mem_pdc_call(PDC_PAT_MEM, PDC_PAT_MEM_CELL_READ,
|
| 1777 | __pa(&pdc_result), parisc_cell_num,
|
| 1778 | __pa(pdt_entries_ptr));
|
| 1779 |
|
| 1780 | if (retval == PDC_OK) {
|
| 1781 |
|
| 1782 | entries = min(pdc_result[0], max_entries);
|
| 1783 | pret->pdt_entries = entries;
|
| 1784 | pret->actual_count_bytes = entries * sizeof(unsigned long);
|
| 1785 | }
|
| 1786 |
|
| 1787 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1788 | WARN_ON(retval == PDC_OK && pdc_result[0] > max_entries);
|
| 1789 |
|
| 1790 | return retval;
|
| 1791 | }
|
| 1792 | |
| 1793 | * pdc_pat_mem_read_pd_pdt - Read PDT entries from (newer) PAT firmware
|
| 1794 | * @pret: array of PDT entries
|
| 1795 | * @pdt_entries_ptr: ptr to hold number of PDT entries
|
| 1796 | * @count: number of bytes to read
|
| 1797 | * @offset: offset to start (in bytes)
|
| 1798 | *
|
| 1799 |
|
| 1800 | int pdc_pat_mem_read_pd_pdt(struct pdc_pat_mem_read_pd_retinfo *pret,
|
| 1801 | unsigned long *pdt_entries_ptr, unsigned long count,
|
| 1802 | unsigned long offset)
|
| 1803 | {
|
| 1804 | int retval;
|
| 1805 | unsigned long flags, entries;
|
| 1806 |
|
| 1807 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1808 | retval = mem_pdc_call(PDC_PAT_MEM, PDC_PAT_MEM_PD_READ,
|
| 1809 | __pa(&pdc_result), __pa(pdt_entries_ptr),
|
| 1810 | count, offset);
|
| 1811 |
|
| 1812 | if (retval == PDC_OK) {
|
| 1813 | entries = min(pdc_result[0], count);
|
| 1814 | pret->actual_count_bytes = entries;
|
| 1815 | pret->pdt_entries = entries / sizeof(unsigned long);
|
| 1816 | }
|
| 1817 |
|
| 1818 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1819 |
|
| 1820 | return retval;
|
| 1821 | }
|
| 1822 |
|
| 1823 | |
| 1824 | * pdc_pat_mem_get_dimm_phys_location - Get physical DIMM slot via PAT firmware
|
| 1825 | * @pret: ptr to hold returned information
|
| 1826 | * @phys_addr: physical address to examine
|
| 1827 | *
|
| 1828 |
|
| 1829 | int pdc_pat_mem_get_dimm_phys_location(
|
| 1830 | struct pdc_pat_mem_phys_mem_location *pret,
|
| 1831 | unsigned long phys_addr)
|
| 1832 | {
|
| 1833 | int retval;
|
| 1834 | unsigned long flags;
|
| 1835 |
|
| 1836 | spin_lock_irqsave(&pdc_lock, flags);
|
| 1837 | retval = mem_pdc_call(PDC_PAT_MEM, PDC_PAT_MEM_ADDRESS,
|
| 1838 | __pa(&pdc_result), phys_addr);
|
| 1839 |
|
| 1840 | if (retval == PDC_OK)
|
| 1841 | memcpy(pret, &pdc_result, sizeof(*pret));
|
| 1842 |
|
| 1843 | spin_unlock_irqrestore(&pdc_lock, flags);
|
| 1844 |
|
| 1845 | return retval;
|
| 1846 | }
|
| 1847 | #endif
|
| 1848 | #endif
|
| 1849 |
|
| 1850 |
|
| 1851 |
|
| 1852 | |
| 1853 | * to overlay real_stack (real2.S), preparing a 32-bit call frame.
|
| 1854 | * real32_call_asm() then uses this stack in narrow real mode
|
| 1855 |
|
| 1856 |
|
| 1857 | struct narrow_stack {
|
| 1858 |
|
| 1859 | unsigned int arg13;
|
| 1860 | unsigned int arg12;
|
| 1861 | unsigned int arg11;
|
| 1862 | unsigned int arg10;
|
| 1863 | unsigned int arg9;
|
| 1864 | unsigned int arg8;
|
| 1865 | unsigned int arg7;
|
| 1866 | unsigned int arg6;
|
| 1867 | unsigned int arg5;
|
| 1868 | unsigned int arg4;
|
| 1869 | unsigned int arg3;
|
| 1870 | unsigned int arg2;
|
| 1871 | unsigned int arg1;
|
| 1872 | unsigned int arg0;
|
| 1873 | unsigned int frame_marker[8];
|
| 1874 | unsigned int sp;
|
| 1875 |
|
| 1876 | };
|
| 1877 |
|
| 1878 | long real32_call(unsigned long fn, ...)
|
| 1879 | {
|
| 1880 | va_list args;
|
| 1881 | extern struct narrow_stack real_stack;
|
| 1882 | extern unsigned long real32_call_asm(unsigned int *,
|
| 1883 | unsigned int *,
|
| 1884 | unsigned int);
|
| 1885 |
|
| 1886 | va_start(args, fn);
|
| 1887 | real_stack.arg0 = va_arg(args, unsigned int);
|
| 1888 | real_stack.arg1 = va_arg(args, unsigned int);
|
| 1889 | real_stack.arg2 = va_arg(args, unsigned int);
|
| 1890 | real_stack.arg3 = va_arg(args, unsigned int);
|
| 1891 | real_stack.arg4 = va_arg(args, unsigned int);
|
| 1892 | real_stack.arg5 = va_arg(args, unsigned int);
|
| 1893 | real_stack.arg6 = va_arg(args, unsigned int);
|
| 1894 | real_stack.arg7 = va_arg(args, unsigned int);
|
| 1895 | real_stack.arg8 = va_arg(args, unsigned int);
|
| 1896 | real_stack.arg9 = va_arg(args, unsigned int);
|
| 1897 | real_stack.arg10 = va_arg(args, unsigned int);
|
| 1898 | real_stack.arg11 = va_arg(args, unsigned int);
|
| 1899 | real_stack.arg12 = va_arg(args, unsigned int);
|
| 1900 | real_stack.arg13 = va_arg(args, unsigned int);
|
| 1901 | va_end(args);
|
| 1902 |
|
| 1903 | return real32_call_asm(&real_stack.sp, &real_stack.arg0, fn);
|
| 1904 | }
|
| 1905 |
|
| 1906 | #ifdef CONFIG_64BIT
|
| 1907 |
|
| 1908 |
|
| 1909 | struct wide_stack {
|
| 1910 | unsigned long arg0;
|
| 1911 | unsigned long arg1;
|
| 1912 | unsigned long arg2;
|
| 1913 | unsigned long arg3;
|
| 1914 | unsigned long arg4;
|
| 1915 | unsigned long arg5;
|
| 1916 | unsigned long arg6;
|
| 1917 | unsigned long arg7;
|
| 1918 | unsigned long arg8;
|
| 1919 | unsigned long arg9;
|
| 1920 | unsigned long arg10;
|
| 1921 | unsigned long arg11;
|
| 1922 | unsigned long arg12;
|
| 1923 | unsigned long arg13;
|
| 1924 | unsigned long frame_marker[2];
|
| 1925 | unsigned long sp;
|
| 1926 |
|
| 1927 | };
|
| 1928 |
|
| 1929 | long real64_call(unsigned long fn, ...)
|
| 1930 | {
|
| 1931 | va_list args;
|
| 1932 | extern struct wide_stack real64_stack;
|
| 1933 | extern unsigned long real64_call_asm(unsigned long *,
|
| 1934 | unsigned long *,
|
| 1935 | unsigned long);
|
| 1936 |
|
| 1937 | va_start(args, fn);
|
| 1938 | real64_stack.arg0 = va_arg(args, unsigned long);
|
| 1939 | real64_stack.arg1 = va_arg(args, unsigned long);
|
| 1940 | real64_stack.arg2 = va_arg(args, unsigned long);
|
| 1941 | real64_stack.arg3 = va_arg(args, unsigned long);
|
| 1942 | real64_stack.arg4 = va_arg(args, unsigned long);
|
| 1943 | real64_stack.arg5 = va_arg(args, unsigned long);
|
| 1944 | real64_stack.arg6 = va_arg(args, unsigned long);
|
| 1945 | real64_stack.arg7 = va_arg(args, unsigned long);
|
| 1946 | real64_stack.arg8 = va_arg(args, unsigned long);
|
| 1947 | real64_stack.arg9 = va_arg(args, unsigned long);
|
| 1948 | real64_stack.arg10 = va_arg(args, unsigned long);
|
| 1949 | real64_stack.arg11 = va_arg(args, unsigned long);
|
| 1950 | real64_stack.arg12 = va_arg(args, unsigned long);
|
| 1951 | real64_stack.arg13 = va_arg(args, unsigned long);
|
| 1952 | va_end(args);
|
| 1953 |
|
| 1954 | return real64_call_asm(&real64_stack.sp, &real64_stack.arg0, fn);
|
| 1955 | }
|
| 1956 |
|
| 1957 | #endif
|