diff options
| author | Russ Anderson <rja@sgi.com> | 2008-07-09 16:27:19 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-07-18 08:35:14 -0400 |
| commit | 7019cc2dd6fafcdc6b104005482dc910dcdbb797 (patch) | |
| tree | 0f8e67c0b5146543d407dc9f07ace6aeb4b0bd12 | |
| parent | 5b664cb235e97afbf34db9c4d77f08ebd725335e (diff) | |
x86 BIOS interface for RTC on SGI UV
Real-time code needs to know the number of cycles per second
on SGI UV. The information is provided via a run time BIOS
call. This patch provides the linux side of that interface.
This is the first of several run time BIOS calls to be defined
in uv/bios.h and bios_uv.c.
Note that BIOS_CALL() is just a stub for now. The bios
side is being worked on.
Signed-off-by: Russ Anderson <rja@sgi.com>
Cc: Jack Steiner <steiner@sgi.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
| -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 da140611bb57..b78a17b12810 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-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o | 106 | obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o |
| 106 | obj-$(CONFIG_AUDIT) += audit_64.o | 107 | obj-$(CONFIG_AUDIT) += audit_64.o |
| 107 | 108 | ||
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 711f11c30b06..3c3929340692 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <asm/pgtable.h> | 24 | #include <asm/pgtable.h> |
| 25 | #include <asm/uv/uv_mmrs.h> | 25 | #include <asm/uv/uv_mmrs.h> |
| 26 | #include <asm/uv/uv_hub.h> | 26 | #include <asm/uv/uv_hub.h> |
| 27 | #include <asm/uv/bios.h> | ||
| 27 | 28 | ||
| 28 | DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); | 29 | DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); |
| 29 | EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info); | 30 | EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info); |
| @@ -40,6 +41,9 @@ EXPORT_SYMBOL_GPL(uv_cpu_to_blade); | |||
| 40 | short uv_possible_blades; | 41 | short uv_possible_blades; |
| 41 | EXPORT_SYMBOL_GPL(uv_possible_blades); | 42 | EXPORT_SYMBOL_GPL(uv_possible_blades); |
| 42 | 43 | ||
| 44 | unsigned long sn_rtc_cycles_per_second; | ||
| 45 | EXPORT_SYMBOL(sn_rtc_cycles_per_second); | ||
| 46 | |||
| 43 | /* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ | 47 | /* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ |
| 44 | 48 | ||
| 45 | static cpumask_t uv_target_cpus(void) | 49 | static cpumask_t uv_target_cpus(void) |
| @@ -272,6 +276,23 @@ static __init void map_mmioh_high(int max_pnode) | |||
| 272 | map_high("MMIOH", mmioh.s.base, shift, map_uc); | 276 | map_high("MMIOH", mmioh.s.base, shift, map_uc); |
| 273 | } | 277 | } |
| 274 | 278 | ||
| 279 | static __init void uv_rtc_init(void) | ||
| 280 | { | ||
| 281 | long status, ticks_per_sec, drift; | ||
| 282 | |||
| 283 | status = | ||
| 284 | x86_bios_freq_base(BIOS_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec, | ||
| 285 | &drift); | ||
| 286 | if (status != 0 || ticks_per_sec < 100000) { | ||
| 287 | printk(KERN_WARNING | ||
| 288 | "unable to determine platform RTC clock frequency, " | ||
| 289 | "guessing.\n"); | ||
| 290 | /* BIOS gives wrong value for clock freq. so guess */ | ||
| 291 | sn_rtc_cycles_per_second = 1000000000000UL / 30000UL; | ||
| 292 | } else | ||
| 293 | sn_rtc_cycles_per_second = ticks_per_sec; | ||
| 294 | } | ||
| 295 | |||
| 275 | static __init void uv_system_init(void) | 296 | static __init void uv_system_init(void) |
| 276 | { | 297 | { |
| 277 | union uvh_si_addr_map_config_u m_n_config; | 298 | union uvh_si_addr_map_config_u m_n_config; |
| @@ -326,6 +347,8 @@ static __init void uv_system_init(void) | |||
| 326 | gnode_upper = (((unsigned long)node_id.s.node_id) & | 347 | gnode_upper = (((unsigned long)node_id.s.node_id) & |
| 327 | ~((1 << n_val) - 1)) << m_val; | 348 | ~((1 << n_val) - 1)) << m_val; |
| 328 | 349 | ||
| 350 | uv_rtc_init(); | ||
| 351 | |||
| 329 | for_each_present_cpu(cpu) { | 352 | for_each_present_cpu(cpu) { |
| 330 | nid = cpu_to_node(cpu); | 353 | nid = cpu_to_node(cpu); |
| 331 | pnode = uv_apicid_to_pnode(per_cpu(x86_cpu_to_apicid, cpu)); | 354 | 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 */ | ||
