1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * System Abstraction Layer (SAL) interface routines. 4 * 5 * Copyright (C) 1998, 1999, 2001, 2003 Hewlett-Packard Co 6 * David Mosberger-Tang <davidm@hpl.hp.com> 7 * Copyright (C) 1999 VA Linux Systems 8 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/init.h> 13 #include <linux/module.h> 14 #include <linux/spinlock.h> 15 #include <linux/string.h> 16 17 #include <asm/delay.h> 18 #include <asm/page.h> 19 #include <asm/sal.h> 20 #include <asm/pal.h> 21 22 __cacheline_aligned DEFINE_SPINLOCK(sal_lock); 23 unsigned long sal_platform_features; 24 25 unsigned short sal_revision; 26 unsigned short sal_version; 27 28 #define SAL_MAJOR(x) ((x) >> 8) 29 #define SAL_MINOR(x) ((x) & 0xff) 30 31 static struct { 32 void *addr; /* function entry point */ 33 void *gpval; /* gp value to use */ 34 } pdesc; 35 36 static long 37 default_handler (void) 38 { 39 return -1; 40 } 41 42 ia64_sal_handler ia64_sal = (ia64_sal_handler) default_handler; 43 ia64_sal_desc_ptc_t *ia64_ptc_domain_info; 44 45 const char * 46 ia64_sal_strerror (long status) 47 { 48 const char *str; 49 switch (status) { 50 case 0: str = "Call completed without error"; break; 51 case 1: str = "Effect a warm boot of the system to complete " 52 "the update"; break; 53 case -1: str = "Not implemented"; break; 54 case -2: str = "Invalid argument"; break; 55 case -3: str = "Call completed with error"; break; 56 case -4: str = "Virtual address not registered"; break; 57 case -5: str = "No information available"; break; 58 case -6: str = "Insufficient space to add the entry"; break; 59 case -7: str = "Invalid entry_addr value"; break; 60 case -8: str = "Invalid interrupt vector"; break; 61 case -9: str = "Requested memory not available"; break; 62 case -10: str = "Unable to write to the NVM device"; break; 63 case -11: str = "Invalid partition type specified"; break; 64 case -12: str = "Invalid NVM_Object id specified"; break; 65 case -13: str = "NVM_Object already has the maximum number " 66 "of partitions"; break; 67 case -14: str = "Insufficient space in partition for the " 68 "requested write sub-function"; break; 69 case -15: str = "Insufficient data buffer space for the " 70 "requested read record sub-function"; break; 71 case -16: str = "Scratch buffer required for the write/delete " 72 "sub-function"; break; 73 case -17: str = "Insufficient space in the NVM_Object for the " 74 "requested create sub-function"; break; 75 case -18: str = "Invalid value specified in the partition_rec " 76 "argument"; break; 77 case -19: str = "Record oriented I/O not supported for this " 78 "partition"; break; 79 case -20: str = "Bad format of record to be written or " 80 "required keyword variable not " 81 "specified"; break; 82 default: str = "Unknown SAL status code"; break; 83 } 84 return str; 85 } 86 87 void __init 88 ia64_sal_handler_init (void *entry_point, void *gpval) 89 { 90 /* fill in the SAL procedure descriptor and point ia64_sal to it: */ 91 pdesc.addr = entry_point; 92 pdesc.gpval = gpval; 93 ia64_sal = (ia64_sal_handler) &pdesc; 94 } 95 96 static void __init 97 check_versions (struct ia64_sal_systab *systab) 98 { 99 sal_revision = (systab->sal_rev_major << 8) | systab->sal_rev_minor; 100 sal_version = (systab->sal_b_rev_major << 8) | systab->sal_b_rev_minor; 101 102 /* Check for broken firmware */ 103 if ((sal_revision == SAL_VERSION_CODE(49, 29)) 104 && (sal_version == SAL_VERSION_CODE(49, 29))) 105 { 106 /* 107 * Old firmware for zx2000 prototypes have this weird version number, 108 * reset it to something sane. 109 */ 110 sal_revision = SAL_VERSION_CODE(2, 8); 111 sal_version = SAL_VERSION_CODE(0, 0); 112 } 113 } 114 115 static void __init 116 sal_desc_entry_point (void *p) 117 { 118 struct ia64_sal_desc_entry_point *ep = p; 119 ia64_pal_handler_init(__va(ep->pal_proc)); 120 ia64_sal_handler_init(__va(ep->sal_proc), __va(ep->gp)); 121 } 122 123 #ifdef CONFIG_SMP 124 static void __init 125 set_smp_redirect (int flag) 126 { 127 #ifndef CONFIG_HOTPLUG_CPU 128 if (no_int_routing) 129 smp_int_redirect &= ~flag; 130 else 131 smp_int_redirect |= flag; 132 #else 133 /* 134 * For CPU Hotplug we dont want to do any chipset supported 135 * interrupt redirection. The reason is this would require that 136 * All interrupts be stopped and hard bind the irq to a cpu. 137 * Later when the interrupt is fired we need to set the redir hint 138 * on again in the vector. This is cumbersome for something that the 139 * user mode irq balancer will solve anyways. 140 */ 141 no_int_routing=1; 142 smp_int_redirect &= ~flag; 143 #endif 144 } 145 #else 146 #define set_smp_redirect(flag) do { } while (0) 147 #endif 148 149 static void __init 150 sal_desc_platform_feature (void *p) 151 { 152 struct ia64_sal_desc_platform_feature *pf = p; 153 sal_platform_features = pf->feature_mask; 154 155 printk(KERN_INFO "SAL Platform features:"); 156 if (!sal_platform_features) { 157 printk(" None\n"); 158 return; 159 } 160 161 if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_BUS_LOCK) 162 printk(" BusLock"); 163 if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT) { 164 printk(" IRQ_Redirection"); 165 set_smp_redirect(SMP_IRQ_REDIRECTION); 166 } 167 if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT) { 168 printk(" IPI_Redirection"); 169 set_smp_redirect(SMP_IPI_REDIRECTION); 170 } 171 if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT) 172 printk(" ITC_Drift"); 173 printk("\n"); 174 } 175 176 #ifdef CONFIG_SMP 177 static void __init 178 sal_desc_ap_wakeup (void *p) 179 { 180 struct ia64_sal_desc_ap_wakeup *ap = p; 181 182 switch (ap->mechanism) { 183 case IA64_SAL_AP_EXTERNAL_INT: 184 ap_wakeup_vector = ap->vector; 185 printk(KERN_INFO "SAL: AP wakeup using external interrupt " 186 "vector 0x%lx\n", ap_wakeup_vector); 187 break; 188 default: 189 printk(KERN_ERR "SAL: AP wakeup mechanism unsupported!\n"); 190 break; 191 } 192 } 193 194 static void __init 195 chk_nointroute_opt(void) 196 { 197 char *cp; 198 199 for (cp = boot_command_line; *cp; ) { 200 if (memcmp(cp, "nointroute", 10) == 0) { 201 no_int_routing = 1; 202 printk ("no_int_routing on\n"); 203 break; 204 } else { 205 while (*cp != ' ' && *cp) 206 ++cp; 207 while (*cp == ' ') 208 ++cp; 209 } 210 } 211 } 212 213 #else 214 static void __init sal_desc_ap_wakeup(void *p) { } 215 #endif 216 217 /* 218 * HP rx5670 firmware polls for interrupts during SAL_CACHE_FLUSH by reading 219 * cr.ivr, but it never writes cr.eoi. This leaves any interrupt marked as 220 * "in-service" and masks other interrupts of equal or lower priority. 221 * 222 * HP internal defect reports: F1859, F2775, F3031. 223 */ 224 static int sal_cache_flush_drops_interrupts; 225 226 static int __init 227 force_pal_cache_flush(char *str) 228 { 229 sal_cache_flush_drops_interrupts = 1; 230 return 0; 231 } 232 early_param("force_pal_cache_flush", force_pal_cache_flush); 233 234 void __init 235 check_sal_cache_flush (void) 236 { 237 unsigned long flags; 238 int cpu; 239 u64 vector, cache_type = 3; 240 struct ia64_sal_retval isrv; 241 242 if (sal_cache_flush_drops_interrupts) 243 return; 244 245 cpu = get_cpu(); 246 local_irq_save(flags); 247 248 /* 249 * Send ourselves a timer interrupt, wait until it's reported, and see 250 * if SAL_CACHE_FLUSH drops it. 251 */ 252 platform_send_ipi(cpu, IA64_TIMER_VECTOR, IA64_IPI_DM_INT, 0); 253 254 while (!ia64_get_irr(IA64_TIMER_VECTOR)) 255 cpu_relax(); 256 257 SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0); 258 259 if (isrv.status) 260 printk(KERN_ERR "SAL_CAL_FLUSH failed with %ld\n", isrv.status); 261 262 if (ia64_get_irr(IA64_TIMER_VECTOR)) { 263 vector = ia64_get_ivr(); 264 ia64_eoi(); 265 WARN_ON(vector != IA64_TIMER_VECTOR); 266 } else { 267 sal_cache_flush_drops_interrupts = 1; 268 printk(KERN_ERR "SAL: SAL_CACHE_FLUSH drops interrupts; " 269 "PAL_CACHE_FLUSH will be used instead\n"); 270 ia64_eoi(); 271 } 272 273 local_irq_restore(flags); 274 put_cpu(); 275 } 276 277 s64 278 ia64_sal_cache_flush (u64 cache_type) 279 { 280 struct ia64_sal_retval isrv; 281 282 if (sal_cache_flush_drops_interrupts) { 283 unsigned long flags; 284 u64 progress; 285 s64 rc; 286 287 progress = 0; 288 local_irq_save(flags); 289 rc = ia64_pal_cache_flush(cache_type, 290 PAL_CACHE_FLUSH_INVALIDATE, &progress, NULL); 291 local_irq_restore(flags); 292 return rc; 293 } 294 295 SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0); 296 return isrv.status; 297 } 298 EXPORT_SYMBOL_GPL(ia64_sal_cache_flush); 299 300 void __init 301 ia64_sal_init (struct ia64_sal_systab *systab) 302 { 303 char *p; 304 int i; 305 306 if (!systab) { 307 printk(KERN_WARNING "Hmm, no SAL System Table.\n"); 308 return; 309 } 310 311 if (strncmp(systab->signature, "SST_", 4) != 0) 312 printk(KERN_ERR "bad signature in system table!"); 313 314 check_versions(systab); 315 #ifdef CONFIG_SMP 316 chk_nointroute_opt(); 317 #endif 318 319 /* revisions are coded in BCD, so %x does the job for us */ 320 printk(KERN_INFO "SAL %x.%x: %.32s %.32s%sversion %x.%x\n", 321 SAL_MAJOR(sal_revision), SAL_MINOR(sal_revision), 322 systab->oem_id, systab->product_id, 323 systab->product_id[0] ? " " : "", 324 SAL_MAJOR(sal_version), SAL_MINOR(sal_version)); 325 326 p = (char *) (systab + 1); 327 for (i = 0; i < systab->entry_count; i++) { 328 /* 329 * The first byte of each entry type contains the type 330 * descriptor. 331 */ 332 switch (*p) { 333 case SAL_DESC_ENTRY_POINT: 334 sal_desc_entry_point(p); 335 break; 336 case SAL_DESC_PLATFORM_FEATURE: 337 sal_desc_platform_feature(p); 338 break; 339 case SAL_DESC_PTC: 340 ia64_ptc_domain_info = (ia64_sal_desc_ptc_t *)p; 341 break; 342 case SAL_DESC_AP_WAKEUP: 343 sal_desc_ap_wakeup(p); 344 break; 345 } 346 p += SAL_DESC_SIZE(*p); 347 } 348 349 } 350 351 int 352 ia64_sal_oemcall(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1, 353 u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7) 354 { 355 if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX) 356 return -1; 357 SAL_CALL(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, arg7); 358 return 0; 359 } 360 EXPORT_SYMBOL(ia64_sal_oemcall); 361 362 int 363 ia64_sal_oemcall_nolock(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1, 364 u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, 365 u64 arg7) 366 { 367 if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX) 368 return -1; 369 SAL_CALL_NOLOCK(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, 370 arg7); 371 return 0; 372 } 373 EXPORT_SYMBOL(ia64_sal_oemcall_nolock); 374 375 int 376 ia64_sal_oemcall_reentrant(struct ia64_sal_retval *isrvp, u64 oemfunc, 377 u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, 378 u64 arg6, u64 arg7) 379 { 380 if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX) 381 return -1; 382 SAL_CALL_REENTRANT(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, 383 arg7); 384 return 0; 385 } 386 EXPORT_SYMBOL(ia64_sal_oemcall_reentrant); 387 388 long 389 ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second, 390 unsigned long *drift_info) 391 { 392 struct ia64_sal_retval isrv; 393 394 SAL_CALL(isrv, SAL_FREQ_BASE, which, 0, 0, 0, 0, 0, 0); 395 *ticks_per_second = isrv.v0; 396 *drift_info = isrv.v1; 397 return isrv.status; 398 } 399 EXPORT_SYMBOL_GPL(ia64_sal_freq_base); 400