diff options
| -rw-r--r-- | arch/x86/kernel/Makefile | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/bios_uv.c | 48 | ||||
| -rw-r--r-- | arch/x86/kernel/genx2apic_uv_x.c | 23 | ||||
| -rw-r--r-- | include/asm-x86/uv/bios.h | 68 |
4 files changed, 140 insertions, 0 deletions
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 673f1d12b420..ea000467553f 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
| @@ -102,6 +102,7 @@ obj-$(CONFIG_OLPC) += olpc.o | |||
| 102 | # 64 bit specific files | 102 | # 64 bit specific files |
| 103 | ifeq ($(CONFIG_X86_64),y) | 103 | ifeq ($(CONFIG_X86_64),y) |
| 104 | obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o | 104 | obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o |
| 105 | obj-y += bios_uv.o | ||
| 105 | obj-y += genx2apic_cluster.o | 106 | obj-y += genx2apic_cluster.o |
| 106 | obj-y += genx2apic_phys.o | 107 | obj-y += genx2apic_phys.o |
| 107 | obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o | 108 | obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o |
diff --git a/arch/x86/kernel/bios_uv.c b/arch/x86/kernel/bios_uv.c new file mode 100644 index 000000000000..c639bd55391c --- /dev/null +++ b/arch/x86/kernel/bios_uv.c | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /* | ||
| 2 | * BIOS run time interface routines. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <asm/uv/bios.h> | ||
| 22 | |||
| 23 | const char * | ||
| 24 | x86_bios_strerror(long status) | ||
| 25 | { | ||
| 26 | const char *str; | ||
| 27 | switch (status) { | ||
| 28 | case 0: str = "Call completed without error"; break; | ||
| 29 | case -1: str = "Not implemented"; break; | ||
| 30 | case -2: str = "Invalid argument"; break; | ||
| 31 | case -3: str = "Call completed with error"; break; | ||
| 32 | default: str = "Unknown BIOS status code"; break; | ||
| 33 | } | ||
| 34 | return str; | ||
| 35 | } | ||
| 36 | |||
| 37 | long | ||
| 38 | x86_bios_freq_base(unsigned long which, unsigned long *ticks_per_second, | ||
| 39 | unsigned long *drift_info) | ||
| 40 | { | ||
| 41 | struct uv_bios_retval isrv; | ||
| 42 | |||
| 43 | BIOS_CALL(isrv, BIOS_FREQ_BASE, which, 0, 0, 0, 0, 0, 0); | ||
| 44 | *ticks_per_second = isrv.v0; | ||
| 45 | *drift_info = isrv.v1; | ||
| 46 | return isrv.status; | ||
| 47 | } | ||
| 48 | EXPORT_SYMBOL_GPL(x86_bios_freq_base); | ||
diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index 3ca29cd8c23c..a8e5cb4c4d43 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <asm/pgtable.h> | 25 | #include <asm/pgtable.h> |
| 26 | #include <asm/uv/uv_mmrs.h> | 26 | #include <asm/uv/uv_mmrs.h> |
| 27 | #include <asm/uv/uv_hub.h> | 27 | #include <asm/uv/uv_hub.h> |
| 28 | #include <asm/uv/bios.h> | ||
| 28 | 29 | ||
| 29 | DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); | 30 | DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); |
| 30 | EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info); | 31 | EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info); |
| @@ -41,6 +42,9 @@ EXPORT_SYMBOL_GPL(uv_cpu_to_blade); | |||
| 41 | short uv_possible_blades; | 42 | short uv_possible_blades; |
| 42 | EXPORT_SYMBOL_GPL(uv_possible_blades); | 43 | EXPORT_SYMBOL_GPL(uv_possible_blades); |
| 43 | 44 | ||
| 45 | unsigned long sn_rtc_cycles_per_second; | ||
| 46 | EXPORT_SYMBOL(sn_rtc_cycles_per_second); | ||
| 47 | |||
| 44 | /* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ | 48 | /* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ |
| 45 | 49 | ||
| 46 | static cpumask_t uv_target_cpus(void) | 50 | static cpumask_t uv_target_cpus(void) |
| @@ -306,6 +310,23 @@ static __init void map_mmioh_high(int max_pnode) | |||
| 306 | map_high("MMIOH", mmioh.s.base, shift, map_uc); | 310 | map_high("MMIOH", mmioh.s.base, shift, map_uc); |
| 307 | } | 311 | } |
| 308 | 312 | ||
| 313 | static __init void uv_rtc_init(void) | ||
| 314 | { | ||
| 315 | long status, ticks_per_sec, drift; | ||
| 316 | |||
| 317 | status = | ||
| 318 | x86_bios_freq_base(BIOS_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec, | ||
| 319 | &drift); | ||
| 320 | if (status != 0 || ticks_per_sec < 100000) { | ||
| 321 | printk(KERN_WARNING | ||
| 322 | "unable to determine platform RTC clock frequency, " | ||
| 323 | "guessing.\n"); | ||
| 324 | /* BIOS gives wrong value for clock freq. so guess */ | ||
| 325 | sn_rtc_cycles_per_second = 1000000000000UL / 30000UL; | ||
| 326 | } else | ||
| 327 | sn_rtc_cycles_per_second = ticks_per_sec; | ||
| 328 | } | ||
| 329 | |||
| 309 | static __init void uv_system_init(void) | 330 | static __init void uv_system_init(void) |
| 310 | { | 331 | { |
| 311 | union uvh_si_addr_map_config_u m_n_config; | 332 | union uvh_si_addr_map_config_u m_n_config; |
| @@ -360,6 +381,8 @@ static __init void uv_system_init(void) | |||
| 360 | gnode_upper = (((unsigned long)node_id.s.node_id) & | 381 | gnode_upper = (((unsigned long)node_id.s.node_id) & |
| 361 | ~((1 << n_val) - 1)) << m_val; | 382 | ~((1 << n_val) - 1)) << m_val; |
| 362 | 383 | ||
| 384 | uv_rtc_init(); | ||
| 385 | |||
| 363 | for_each_present_cpu(cpu) { | 386 | for_each_present_cpu(cpu) { |
| 364 | nid = cpu_to_node(cpu); | 387 | nid = cpu_to_node(cpu); |
| 365 | pnode = uv_apicid_to_pnode(per_cpu(x86_cpu_to_apicid, cpu)); | 388 | pnode = uv_apicid_to_pnode(per_cpu(x86_cpu_to_apicid, cpu)); |
diff --git a/include/asm-x86/uv/bios.h b/include/asm-x86/uv/bios.h new file mode 100644 index 000000000000..aa73362ff5df --- /dev/null +++ b/include/asm-x86/uv/bios.h | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | #ifndef _ASM_X86_BIOS_H | ||
| 2 | #define _ASM_X86_BIOS_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | * BIOS layer definitions. | ||
| 6 | * | ||
| 7 | * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/rtc.h> | ||
| 25 | |||
| 26 | #define BIOS_FREQ_BASE 0x01000001 | ||
| 27 | |||
| 28 | enum { | ||
| 29 | BIOS_FREQ_BASE_PLATFORM = 0, | ||
| 30 | BIOS_FREQ_BASE_INTERVAL_TIMER = 1, | ||
| 31 | BIOS_FREQ_BASE_REALTIME_CLOCK = 2 | ||
| 32 | }; | ||
| 33 | |||
| 34 | # define BIOS_CALL(result, a0, a1, a2, a3, a4, a5, a6, a7) \ | ||
| 35 | do { \ | ||
| 36 | /* XXX - the real call goes here */ \ | ||
| 37 | result.status = BIOS_STATUS_UNIMPLEMENTED; \ | ||
| 38 | isrv.v0 = 0; \ | ||
| 39 | isrv.v1 = 0; \ | ||
| 40 | } while (0) | ||
| 41 | |||
| 42 | enum { | ||
| 43 | BIOS_STATUS_SUCCESS = 0, | ||
| 44 | BIOS_STATUS_UNIMPLEMENTED = -1, | ||
| 45 | BIOS_STATUS_EINVAL = -2, | ||
| 46 | BIOS_STATUS_ERROR = -3 | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct uv_bios_retval { | ||
| 50 | /* | ||
| 51 | * A zero status value indicates call completed without error. | ||
| 52 | * A negative status value indicates reason of call failure. | ||
| 53 | * A positive status value indicates success but an | ||
| 54 | * informational value should be printed (e.g., "reboot for | ||
| 55 | * change to take effect"). | ||
| 56 | */ | ||
| 57 | s64 status; | ||
| 58 | u64 v0; | ||
| 59 | u64 v1; | ||
| 60 | u64 v2; | ||
| 61 | }; | ||
| 62 | |||
| 63 | extern long | ||
| 64 | x86_bios_freq_base(unsigned long which, unsigned long *ticks_per_second, | ||
| 65 | unsigned long *drift_info); | ||
| 66 | extern const char *x86_bios_strerror(long status); | ||
| 67 | |||
| 68 | #endif /* _ASM_X86_BIOS_H */ | ||
