Linux Audio

Check our new training course

Loading...
v3.1
 
  1/*
  2 * BIOS run time interface routines.
  3 *
  4 *  This program is free software; you can redistribute it and/or modify
  5 *  it under the terms of the GNU General Public License as published by
  6 *  the Free Software Foundation; either version 2 of the License, or
  7 *  (at your option) any later version.
  8 *
  9 *  This program is distributed in the hope that it will be useful,
 10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 *  GNU General Public License for more details.
 13 *
 14 *  You should have received a copy of the GNU General Public License
 15 *  along with this program; if not, write to the Free Software
 16 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 17 *
 18 *  Copyright (c) 2008-2009 Silicon Graphics, Inc.  All Rights Reserved.
 19 *  Copyright (c) Russ Anderson <rja@sgi.com>
 20 */
 21
 22#include <linux/efi.h>
 
 
 23#include <asm/efi.h>
 24#include <linux/io.h>
 25#include <asm/uv/bios.h>
 26#include <asm/uv/uv_hub.h>
 27
 28static struct uv_systab uv_systab;
 29
 30s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
 
 
 
 31{
 32	struct uv_systab *tab = &uv_systab;
 33	s64 ret;
 34
 35	if (!tab->function)
 36		/*
 37		 * BIOS does not support UV systab
 38		 */
 39		return BIOS_STATUS_UNIMPLEMENTED;
 40
 41	ret = efi_call6((void *)__va(tab->function), (u64)which,
 42			a1, a2, a3, a4, a5);
 
 
 
 
 
 
 
 43	return ret;
 44}
 45EXPORT_SYMBOL_GPL(uv_bios_call);
 46
 47s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
 48					u64 a4, u64 a5)
 49{
 50	unsigned long bios_flags;
 51	s64 ret;
 52
 53	local_irq_save(bios_flags);
 54	ret = uv_bios_call(which, a1, a2, a3, a4, a5);
 55	local_irq_restore(bios_flags);
 
 
 56
 57	return ret;
 58}
 
 59
 60s64 uv_bios_call_reentrant(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
 61					u64 a4, u64 a5)
 62{
 
 63	s64 ret;
 64
 65	preempt_disable();
 66	ret = uv_bios_call(which, a1, a2, a3, a4, a5);
 67	preempt_enable();
 
 
 
 
 
 68
 69	return ret;
 70}
 71
 72
 73long sn_partition_id;
 74EXPORT_SYMBOL_GPL(sn_partition_id);
 75long sn_coherency_id;
 76EXPORT_SYMBOL_GPL(sn_coherency_id);
 77long sn_region_size;
 78EXPORT_SYMBOL_GPL(sn_region_size);
 79long system_serial_number;
 80EXPORT_SYMBOL_GPL(system_serial_number);
 81int uv_type;
 82EXPORT_SYMBOL_GPL(uv_type);
 83
 84
 85s64 uv_bios_get_sn_info(int fc, int *uvtype, long *partid, long *coher,
 86		long *region, long *ssn)
 87{
 88	s64 ret;
 89	u64 v0, v1;
 90	union partition_info_u part;
 91
 92	ret = uv_bios_call_irqsave(UV_BIOS_GET_SN_INFO, fc,
 93				(u64)(&v0), (u64)(&v1), 0, 0);
 94	if (ret != BIOS_STATUS_SUCCESS)
 95		return ret;
 96
 97	part.val = v0;
 98	if (uvtype)
 99		*uvtype = part.hub_version;
100	if (partid)
101		*partid = part.partition_id;
102	if (coher)
103		*coher = part.coherence_id;
104	if (region)
105		*region = part.region_size;
106	if (ssn)
107		*ssn = v1;
108	return ret;
109}
110EXPORT_SYMBOL_GPL(uv_bios_get_sn_info);
111
112int
113uv_bios_mq_watchlist_alloc(unsigned long addr, unsigned int mq_size,
114			   unsigned long *intr_mmr_offset)
115{
116	u64 watchlist;
117	s64 ret;
118
119	/*
120	 * bios returns watchlist number or negative error number.
121	 */
122	ret = (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_ALLOC, addr,
123			mq_size, (u64)intr_mmr_offset,
124			(u64)&watchlist, 0);
125	if (ret < BIOS_STATUS_SUCCESS)
126		return ret;
127
128	return watchlist;
129}
130EXPORT_SYMBOL_GPL(uv_bios_mq_watchlist_alloc);
131
132int
133uv_bios_mq_watchlist_free(int blade, int watchlist_num)
134{
135	return (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_FREE,
136				blade, watchlist_num, 0, 0, 0);
137}
138EXPORT_SYMBOL_GPL(uv_bios_mq_watchlist_free);
139
140s64
141uv_bios_change_memprotect(u64 paddr, u64 len, enum uv_memprotect perms)
142{
143	return uv_bios_call_irqsave(UV_BIOS_MEMPROTECT, paddr, len,
144					perms, 0, 0);
145}
146EXPORT_SYMBOL_GPL(uv_bios_change_memprotect);
147
148s64
149uv_bios_reserved_page_pa(u64 buf, u64 *cookie, u64 *addr, u64 *len)
150{
151	s64 ret;
152
153	ret = uv_bios_call_irqsave(UV_BIOS_GET_PARTITION_ADDR, (u64)cookie,
154					(u64)addr, buf, (u64)len, 0);
155	return ret;
156}
157EXPORT_SYMBOL_GPL(uv_bios_reserved_page_pa);
158
159s64 uv_bios_freq_base(u64 clock_type, u64 *ticks_per_second)
160{
161	return uv_bios_call(UV_BIOS_FREQ_BASE, clock_type,
162			   (u64)ticks_per_second, 0, 0, 0);
163}
164EXPORT_SYMBOL_GPL(uv_bios_freq_base);
165
166/*
167 * uv_bios_set_legacy_vga_target - Set Legacy VGA I/O Target
168 * @decode: true to enable target, false to disable target
169 * @domain: PCI domain number
170 * @bus: PCI bus number
171 *
172 * Returns:
173 *    0: Success
174 *    -EINVAL: Invalid domain or bus number
175 *    -ENOSYS: Capability not available
176 *    -EBUSY: Legacy VGA I/O cannot be retargeted at this time
177 */
178int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus)
179{
180	return uv_bios_call(UV_BIOS_SET_LEGACY_VGA_TARGET,
181				(u64)decode, (u64)domain, (u64)bus, 0, 0);
182}
183EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target);
184
185
186#ifdef CONFIG_EFI
187void uv_bios_init(void)
188{
189	struct uv_systab *tab;
190
191	if ((efi.uv_systab == EFI_INVALID_TABLE_ADDR) ||
192	    (efi.uv_systab == (unsigned long)NULL)) {
193		printk(KERN_CRIT "No EFI UV System Table.\n");
194		uv_systab.function = (unsigned long)NULL;
195		return;
196	}
197
198	tab = (struct uv_systab *)ioremap(efi.uv_systab,
199					sizeof(struct uv_systab));
200	if (strncmp(tab->signature, "UVST", 4) != 0)
201		printk(KERN_ERR "bad signature in UV system table!");
202
203	/*
204	 * Copy table to permanent spot for later use.
205	 */
206	memcpy(&uv_systab, tab, sizeof(struct uv_systab));
207	iounmap(tab);
208
209	printk(KERN_INFO "EFI UV System Table Revision %d\n",
210					uv_systab.revision);
 
 
 
 
 
 
 
 
 
 
211}
212#else	/* !CONFIG_EFI */
213
214void uv_bios_init(void) { }
215#endif
v5.4
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * BIOS run time interface routines.
  4 *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  5 *  Copyright (c) 2008-2009 Silicon Graphics, Inc.  All Rights Reserved.
  6 *  Copyright (c) Russ Anderson <rja@sgi.com>
  7 */
  8
  9#include <linux/efi.h>
 10#include <linux/export.h>
 11#include <linux/slab.h>
 12#include <asm/efi.h>
 13#include <linux/io.h>
 14#include <asm/uv/bios.h>
 15#include <asm/uv/uv_hub.h>
 16
 17unsigned long uv_systab_phys __ro_after_init = EFI_INVALID_TABLE_ADDR;
 18
 19struct uv_systab *uv_systab;
 20
 21static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
 22			u64 a4, u64 a5)
 23{
 24	struct uv_systab *tab = uv_systab;
 25	s64 ret;
 26
 27	if (!tab || !tab->function)
 28		/*
 29		 * BIOS does not support UV systab
 30		 */
 31		return BIOS_STATUS_UNIMPLEMENTED;
 32
 33	/*
 34	 * If EFI_OLD_MEMMAP is set, we need to fall back to using our old EFI
 35	 * callback method, which uses efi_call() directly, with the kernel page tables:
 36	 */
 37	if (unlikely(efi_enabled(EFI_OLD_MEMMAP)))
 38		ret = efi_call((void *)__va(tab->function), (u64)which, a1, a2, a3, a4, a5);
 39	else
 40		ret = efi_call_virt_pointer(tab, function, (u64)which, a1, a2, a3, a4, a5);
 41
 42	return ret;
 43}
 
 44
 45s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
 
 46{
 
 47	s64 ret;
 48
 49	if (down_interruptible(&__efi_uv_runtime_lock))
 50		return BIOS_STATUS_ABORT;
 51
 52	ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
 53	up(&__efi_uv_runtime_lock);
 54
 55	return ret;
 56}
 57EXPORT_SYMBOL_GPL(uv_bios_call);
 58
 59s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
 60					u64 a4, u64 a5)
 61{
 62	unsigned long bios_flags;
 63	s64 ret;
 64
 65	if (down_interruptible(&__efi_uv_runtime_lock))
 66		return BIOS_STATUS_ABORT;
 67
 68	local_irq_save(bios_flags);
 69	ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
 70	local_irq_restore(bios_flags);
 71
 72	up(&__efi_uv_runtime_lock);
 73
 74	return ret;
 75}
 76
 77
 78long sn_partition_id;
 79EXPORT_SYMBOL_GPL(sn_partition_id);
 80long sn_coherency_id;
 81EXPORT_SYMBOL_GPL(sn_coherency_id);
 82long sn_region_size;
 83EXPORT_SYMBOL_GPL(sn_region_size);
 84long system_serial_number;
 85EXPORT_SYMBOL_GPL(system_serial_number);
 86int uv_type;
 87EXPORT_SYMBOL_GPL(uv_type);
 88
 89
 90s64 uv_bios_get_sn_info(int fc, int *uvtype, long *partid, long *coher,
 91		long *region, long *ssn)
 92{
 93	s64 ret;
 94	u64 v0, v1;
 95	union partition_info_u part;
 96
 97	ret = uv_bios_call_irqsave(UV_BIOS_GET_SN_INFO, fc,
 98				(u64)(&v0), (u64)(&v1), 0, 0);
 99	if (ret != BIOS_STATUS_SUCCESS)
100		return ret;
101
102	part.val = v0;
103	if (uvtype)
104		*uvtype = part.hub_version;
105	if (partid)
106		*partid = part.partition_id;
107	if (coher)
108		*coher = part.coherence_id;
109	if (region)
110		*region = part.region_size;
111	if (ssn)
112		*ssn = v1;
113	return ret;
114}
115EXPORT_SYMBOL_GPL(uv_bios_get_sn_info);
116
117int
118uv_bios_mq_watchlist_alloc(unsigned long addr, unsigned int mq_size,
119			   unsigned long *intr_mmr_offset)
120{
121	u64 watchlist;
122	s64 ret;
123
124	/*
125	 * bios returns watchlist number or negative error number.
126	 */
127	ret = (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_ALLOC, addr,
128			mq_size, (u64)intr_mmr_offset,
129			(u64)&watchlist, 0);
130	if (ret < BIOS_STATUS_SUCCESS)
131		return ret;
132
133	return watchlist;
134}
135EXPORT_SYMBOL_GPL(uv_bios_mq_watchlist_alloc);
136
137int
138uv_bios_mq_watchlist_free(int blade, int watchlist_num)
139{
140	return (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_FREE,
141				blade, watchlist_num, 0, 0, 0);
142}
143EXPORT_SYMBOL_GPL(uv_bios_mq_watchlist_free);
144
145s64
146uv_bios_change_memprotect(u64 paddr, u64 len, enum uv_memprotect perms)
147{
148	return uv_bios_call_irqsave(UV_BIOS_MEMPROTECT, paddr, len,
149					perms, 0, 0);
150}
151EXPORT_SYMBOL_GPL(uv_bios_change_memprotect);
152
153s64
154uv_bios_reserved_page_pa(u64 buf, u64 *cookie, u64 *addr, u64 *len)
155{
156	return uv_bios_call_irqsave(UV_BIOS_GET_PARTITION_ADDR, (u64)cookie,
157				    (u64)addr, buf, (u64)len, 0);
 
 
 
158}
159EXPORT_SYMBOL_GPL(uv_bios_reserved_page_pa);
160
161s64 uv_bios_freq_base(u64 clock_type, u64 *ticks_per_second)
162{
163	return uv_bios_call(UV_BIOS_FREQ_BASE, clock_type,
164			   (u64)ticks_per_second, 0, 0, 0);
165}
166EXPORT_SYMBOL_GPL(uv_bios_freq_base);
167
168/*
169 * uv_bios_set_legacy_vga_target - Set Legacy VGA I/O Target
170 * @decode: true to enable target, false to disable target
171 * @domain: PCI domain number
172 * @bus: PCI bus number
173 *
174 * Returns:
175 *    0: Success
176 *    -EINVAL: Invalid domain or bus number
177 *    -ENOSYS: Capability not available
178 *    -EBUSY: Legacy VGA I/O cannot be retargeted at this time
179 */
180int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus)
181{
182	return uv_bios_call(UV_BIOS_SET_LEGACY_VGA_TARGET,
183				(u64)decode, (u64)domain, (u64)bus, 0, 0);
184}
185EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target);
186
 
 
187void uv_bios_init(void)
188{
189	uv_systab = NULL;
190	if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) ||
191	    !uv_systab_phys || efi_runtime_disabled()) {
192		pr_crit("UV: UVsystab: missing\n");
 
 
193		return;
194	}
195
196	uv_systab = ioremap(uv_systab_phys, sizeof(struct uv_systab));
197	if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) {
198		pr_err("UV: UVsystab: bad signature!\n");
199		iounmap(uv_systab);
200		return;
201	}
 
 
 
 
202
203	/* Starting with UV4 the UV systab size is variable */
204	if (uv_systab->revision >= UV_SYSTAB_VERSION_UV4) {
205		int size = uv_systab->size;
206
207		iounmap(uv_systab);
208		uv_systab = ioremap(uv_systab_phys, size);
209		if (!uv_systab) {
210			pr_err("UV: UVsystab: ioremap(%d) failed!\n", size);
211			return;
212		}
213	}
214	pr_info("UV: UVsystab: Revision:%x\n", uv_systab->revision);
215}