11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * System Abstraction Layer (SAL) interface routines. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1998, 1999, 2001, 2003 Hewlett-Packard Co 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * David Mosberger-Tang <davidm@hpl.hp.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999 VA Linux Systems 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas#include <asm/delay.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/page.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sal.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pal.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __cacheline_aligned DEFINE_SPINLOCK(sal_lock); 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned long sal_platform_features; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned short sal_revision; 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsunsigned short sal_version; 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SAL_MAJOR(x) ((x) >> 8) 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SAL_MINOR(x) ((x) & 0xff) 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct { 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *addr; /* function entry point */ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *gpval; /* gp value to use */ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} pdesc; 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic long 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdefault_handler (void) 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsia64_sal_handler ia64_sal = (ia64_sal_handler) default_handler; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsia64_sal_desc_ptc_t *ia64_ptc_domain_info; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsconst char * 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsia64_sal_strerror (long status) 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *str; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (status) { 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: str = "Call completed without error"; break; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: str = "Effect a warm boot of the system to complete " 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "the update"; break; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -1: str = "Not implemented"; break; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -2: str = "Invalid argument"; break; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -3: str = "Call completed with error"; break; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -4: str = "Virtual address not registered"; break; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -5: str = "No information available"; break; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -6: str = "Insufficient space to add the entry"; break; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -7: str = "Invalid entry_addr value"; break; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -8: str = "Invalid interrupt vector"; break; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -9: str = "Requested memory not available"; break; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -10: str = "Unable to write to the NVM device"; break; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -11: str = "Invalid partition type specified"; break; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -12: str = "Invalid NVM_Object id specified"; break; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -13: str = "NVM_Object already has the maximum number " 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "of partitions"; break; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -14: str = "Insufficient space in partition for the " 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "requested write sub-function"; break; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -15: str = "Insufficient data buffer space for the " 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "requested read record sub-function"; break; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -16: str = "Scratch buffer required for the write/delete " 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "sub-function"; break; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -17: str = "Insufficient space in the NVM_Object for the " 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "requested create sub-function"; break; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -18: str = "Invalid value specified in the partition_rec " 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "argument"; break; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -19: str = "Record oriented I/O not supported for this " 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "partition"; break; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case -20: str = "Bad format of record to be written or " 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "required keyword variable not " 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "specified"; break; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: str = "Unknown SAL status code"; break; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return str; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsia64_sal_handler_init (void *entry_point, void *gpval) 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* fill in the SAL procedure descriptor and point ia64_sal to it: */ 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdesc.addr = entry_point; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdesc.gpval = gpval; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ia64_sal = (ia64_sal_handler) &pdesc; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscheck_versions (struct ia64_sal_systab *systab) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sal_revision = (systab->sal_rev_major << 8) | systab->sal_rev_minor; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sal_version = (systab->sal_b_rev_major << 8) | systab->sal_b_rev_minor; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check for broken firmware */ 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((sal_revision == SAL_VERSION_CODE(49, 29)) 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && (sal_version == SAL_VERSION_CODE(49, 29))) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Old firmware for zx2000 prototypes have this weird version number, 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reset it to something sane. 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sal_revision = SAL_VERSION_CODE(2, 8); 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sal_version = SAL_VERSION_CODE(0, 0); 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1126ed0dc5ba811ce682f48988bf114669265e1120dAlex Chiang 1136ed0dc5ba811ce682f48988bf114669265e1120dAlex Chiang if (ia64_platform_is("sn2") && (sal_revision == SAL_VERSION_CODE(2, 9))) 1146ed0dc5ba811ce682f48988bf114669265e1120dAlex Chiang /* 1156ed0dc5ba811ce682f48988bf114669265e1120dAlex Chiang * SGI Altix has hard-coded version 2.9 in their prom 1166ed0dc5ba811ce682f48988bf114669265e1120dAlex Chiang * but they actually implement 3.2, so let's fix it here. 1176ed0dc5ba811ce682f48988bf114669265e1120dAlex Chiang */ 1186ed0dc5ba811ce682f48988bf114669265e1120dAlex Chiang sal_revision = SAL_VERSION_CODE(3, 2); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssal_desc_entry_point (void *p) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ia64_sal_desc_entry_point *ep = p; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ia64_pal_handler_init(__va(ep->pal_proc)); 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ia64_sal_handler_init(__va(ep->sal_proc), __va(ep->gp)); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsset_smp_redirect (int flag) 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_HOTPLUG_CPU 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (no_int_routing) 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds smp_int_redirect &= ~flag; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds smp_int_redirect |= flag; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For CPU Hotplug we dont want to do any chipset supported 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * interrupt redirection. The reason is this would require that 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All interrupts be stopped and hard bind the irq to a cpu. 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Later when the interrupt is fired we need to set the redir hint 14472fdbdce3d52282f8ea95f512e871791256754e6Simon Arlott * on again in the vector. This is cumbersome for something that the 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user mode irq balancer will solve anyways. 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds no_int_routing=1; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds smp_int_redirect &= ~flag; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define set_smp_redirect(flag) do { } while (0) 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssal_desc_platform_feature (void *p) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ia64_sal_desc_platform_feature *pf = p; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sal_platform_features = pf->feature_mask; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "SAL Platform features:"); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sal_platform_features) { 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" None\n"); 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_BUS_LOCK) 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" BusLock"); 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT) { 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" IRQ_Redirection"); 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_smp_redirect(SMP_IRQ_REDIRECTION); 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT) { 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" IPI_Redirection"); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_smp_redirect(SMP_IPI_REDIRECTION); 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" ITC_Drift"); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\n"); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssal_desc_ap_wakeup (void *p) 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ia64_sal_desc_ap_wakeup *ap = p; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ap->mechanism) { 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IA64_SAL_AP_EXTERNAL_INT: 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ap_wakeup_vector = ap->vector; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "SAL: AP wakeup using external interrupt " 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "vector 0x%lx\n", ap_wakeup_vector); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "SAL: AP wakeup mechanism unsupported!\n"); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschk_nointroute_opt(void) 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *cp; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 205a8d91b8477aa433ee0131b031d782411976e1726Alon Bar-Lev for (cp = boot_command_line; *cp; ) { 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (memcmp(cp, "nointroute", 10) == 0) { 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds no_int_routing = 1; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk ("no_int_routing on\n"); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (*cp != ' ' && *cp) 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++cp; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (*cp == ' ') 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++cp; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init sal_desc_ap_wakeup(void *p) { } 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 223a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas/* 224a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas * HP rx5670 firmware polls for interrupts during SAL_CACHE_FLUSH by reading 225a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas * cr.ivr, but it never writes cr.eoi. This leaves any interrupt marked as 226a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas * "in-service" and masks other interrupts of equal or lower priority. 227a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas * 228a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas * HP internal defect reports: F1859, F2775, F3031. 229a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas */ 230a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaasstatic int sal_cache_flush_drops_interrupts; 231a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas 232f13ae30e1397e3bfb38feb3b6e889af5d021f13dAlex Chiangstatic int __init 233f13ae30e1397e3bfb38feb3b6e889af5d021f13dAlex Chiangforce_pal_cache_flush(char *str) 234f13ae30e1397e3bfb38feb3b6e889af5d021f13dAlex Chiang{ 235f13ae30e1397e3bfb38feb3b6e889af5d021f13dAlex Chiang sal_cache_flush_drops_interrupts = 1; 236f13ae30e1397e3bfb38feb3b6e889af5d021f13dAlex Chiang return 0; 237f13ae30e1397e3bfb38feb3b6e889af5d021f13dAlex Chiang} 238f13ae30e1397e3bfb38feb3b6e889af5d021f13dAlex Chiangearly_param("force_pal_cache_flush", force_pal_cache_flush); 239f13ae30e1397e3bfb38feb3b6e889af5d021f13dAlex Chiang 240fa1d19e5d9a94120f31e5783ab44758f46892d94Troy Hebervoid __init 241a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaascheck_sal_cache_flush (void) 242a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas{ 2439ba89334552b96e2127dcafb1c46ce255ecf2667Ian Wienand unsigned long flags; 244a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas int cpu; 245fa1d19e5d9a94120f31e5783ab44758f46892d94Troy Heber u64 vector, cache_type = 3; 246fa1d19e5d9a94120f31e5783ab44758f46892d94Troy Heber struct ia64_sal_retval isrv; 247a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas 248f13ae30e1397e3bfb38feb3b6e889af5d021f13dAlex Chiang if (sal_cache_flush_drops_interrupts) 249f13ae30e1397e3bfb38feb3b6e889af5d021f13dAlex Chiang return; 250f13ae30e1397e3bfb38feb3b6e889af5d021f13dAlex Chiang 251a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas cpu = get_cpu(); 252a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas local_irq_save(flags); 253a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas 254a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas /* 2553463a93def55c309f3c0d0a8aaf216be3be42d64Alex Chiang * Send ourselves a timer interrupt, wait until it's reported, and see 2563463a93def55c309f3c0d0a8aaf216be3be42d64Alex Chiang * if SAL_CACHE_FLUSH drops it. 257a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas */ 2583463a93def55c309f3c0d0a8aaf216be3be42d64Alex Chiang platform_send_ipi(cpu, IA64_TIMER_VECTOR, IA64_IPI_DM_INT, 0); 259a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas 260a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas while (!ia64_get_irr(IA64_TIMER_VECTOR)) 261a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas cpu_relax(); 262a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas 263fa1d19e5d9a94120f31e5783ab44758f46892d94Troy Heber SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0); 264fa1d19e5d9a94120f31e5783ab44758f46892d94Troy Heber 265fa1d19e5d9a94120f31e5783ab44758f46892d94Troy Heber if (isrv.status) 266fa1d19e5d9a94120f31e5783ab44758f46892d94Troy Heber printk(KERN_ERR "SAL_CAL_FLUSH failed with %ld\n", isrv.status); 267a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas 268a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas if (ia64_get_irr(IA64_TIMER_VECTOR)) { 269a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas vector = ia64_get_ivr(); 270a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas ia64_eoi(); 271a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas WARN_ON(vector != IA64_TIMER_VECTOR); 272a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas } else { 273a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas sal_cache_flush_drops_interrupts = 1; 274a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas printk(KERN_ERR "SAL: SAL_CACHE_FLUSH drops interrupts; " 275a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas "PAL_CACHE_FLUSH will be used instead\n"); 276a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas ia64_eoi(); 277a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas } 278a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas 279a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas local_irq_restore(flags); 280a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas put_cpu(); 281a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas} 282a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas 283a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaass64 284a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaasia64_sal_cache_flush (u64 cache_type) 285a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas{ 286a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas struct ia64_sal_retval isrv; 287a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas 288a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas if (sal_cache_flush_drops_interrupts) { 289a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas unsigned long flags; 290a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas u64 progress; 291a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas s64 rc; 292a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas 293a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas progress = 0; 294a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas local_irq_save(flags); 295a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas rc = ia64_pal_cache_flush(cache_type, 296a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas PAL_CACHE_FLUSH_INVALIDATE, &progress, NULL); 297a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas local_irq_restore(flags); 298a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas return rc; 299a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas } 300a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas 301a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0); 302a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas return isrv.status; 303a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas} 304a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, XiantaoEXPORT_SYMBOL_GPL(ia64_sal_cache_flush); 305a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsia64_sal_init (struct ia64_sal_systab *systab) 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *p; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!systab) { 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "Hmm, no SAL System Table.\n"); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (strncmp(systab->signature, "SST_", 4) != 0) 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "bad signature in system table!"); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds check_versions(systab); 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chk_nointroute_opt(); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* revisions are coded in BCD, so %x does the job for us */ 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "SAL %x.%x: %.32s %.32s%sversion %x.%x\n", 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SAL_MAJOR(sal_revision), SAL_MINOR(sal_revision), 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds systab->oem_id, systab->product_id, 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds systab->product_id[0] ? " " : "", 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SAL_MAJOR(sal_version), SAL_MINOR(sal_version)); 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = (char *) (systab + 1); 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < systab->entry_count; i++) { 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The first byte of each entry type contains the type 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * descriptor. 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (*p) { 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SAL_DESC_ENTRY_POINT: 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sal_desc_entry_point(p); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SAL_DESC_PLATFORM_FEATURE: 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sal_desc_platform_feature(p); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SAL_DESC_PTC: 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ia64_ptc_domain_info = (ia64_sal_desc_ptc_t *)p; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SAL_DESC_AP_WAKEUP: 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sal_desc_ap_wakeup(p); 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p += SAL_DESC_SIZE(*p); 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 354a58786917ce23c2a26c3e099c3cdba32a35eecebBjorn Helgaas 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsia64_sal_oemcall(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1, 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7) 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX) 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SAL_CALL(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, arg7); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(ia64_sal_oemcall); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsia64_sal_oemcall_nolock(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1, 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u64 arg7) 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX) 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SAL_CALL_NOLOCK(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg7); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(ia64_sal_oemcall_nolock); 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsia64_sal_oemcall_reentrant(struct ia64_sal_retval *isrvp, u64 oemfunc, 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u64 arg6, u64 arg7) 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX) 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SAL_CALL_REENTRANT(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg7); 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(ia64_sal_oemcall_reentrant); 393a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, Xiantao 394a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, Xiantaolong 395a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, Xiantaoia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second, 396a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, Xiantao unsigned long *drift_info) 397a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, Xiantao{ 398a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, Xiantao struct ia64_sal_retval isrv; 399a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, Xiantao 400a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, Xiantao SAL_CALL(isrv, SAL_FREQ_BASE, which, 0, 0, 0, 0, 0, 0); 401a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, Xiantao *ticks_per_second = isrv.v0; 402a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, Xiantao *drift_info = isrv.v1; 403a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, Xiantao return isrv.status; 404a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, Xiantao} 405a7d57ecf4216ed29328f8e701bd65ebb66a0284cZhang, XiantaoEXPORT_SYMBOL_GPL(ia64_sal_freq_base); 406