mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 22:21:42 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6: (25 commits) atyfb: Fix bootup hangs on sparc64. sparc: update copyright in piggyback.c sparc: unify strip command in boot/Makefile sparc: rename piggyback_32 to piggyback sparc: fix tftpboot.img for sparc64 on little-endian host sparc: add $BITS to piggyback arguments sparc: remove obsolete ELF support in piggyback_32.c sparc: additional comments to piggyback_32.c sparc: use _start for the start entry (like 64 bit does) sparc: use trapbase in setup_arch sparc: refactor piggy_32.c Added support for ampopts in APBUART driver. Used in AMP systems. APBUART: added raw AMBA vendor/device number to match against. SPARC/LEON: avoid AMBAPP name duplicates in openprom fs when REG is missing SPARC/LEON: added support for selecting Timer Core and Timer within core LEON: added raw AMBA vendor/device number to find TIMER, IRQCTRL SPARC/LEON: added support for IRQAMP IRQ Controller SPARC/LEON: find IRQCTRL and Timer via OF-Tree, instead of hardcoded. sparc: fix sparse warnings in arch/sparc/prom for 32 bit build sparc: remove unused prom tree functions ...
This commit is contained in:
commit
f70f5b9dc7
@ -6,25 +6,24 @@
|
||||
ROOT_IMG := /usr/src/root.img
|
||||
ELFTOAOUT := elftoaout
|
||||
|
||||
hostprogs-y := piggyback_32 piggyback_64 btfixupprep
|
||||
hostprogs-y := piggyback btfixupprep
|
||||
targets := tftpboot.img btfix.o btfix.S image zImage vmlinux.aout
|
||||
clean-files := System.map
|
||||
|
||||
quiet_cmd_elftoaout = ELFTOAOUT $@
|
||||
cmd_elftoaout = $(ELFTOAOUT) $(obj)/image -o $@
|
||||
quiet_cmd_piggy = PIGGY $@
|
||||
cmd_piggy = $(obj)/piggyback $(BITS) $@ System.map $(ROOT_IMG)
|
||||
quiet_cmd_strip = STRIP $@
|
||||
cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start $< -o $@
|
||||
|
||||
ifeq ($(CONFIG_SPARC32),y)
|
||||
quiet_cmd_piggy = PIGGY $@
|
||||
cmd_piggy = $(obj)/piggyback_32 $@ System.map $(ROOT_IMG)
|
||||
quiet_cmd_btfix = BTFIX $@
|
||||
cmd_btfix = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@
|
||||
quiet_cmd_sysmap = SYSMAP $(obj)/System.map
|
||||
cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
|
||||
quiet_cmd_image = LD $@
|
||||
cmd_image = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) -o $@
|
||||
quiet_cmd_strip = STRIP $@
|
||||
cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start $(obj)/image -o $@
|
||||
|
||||
|
||||
define rule_image
|
||||
$(if $($(quiet)cmd_image), \
|
||||
@ -57,10 +56,7 @@ $(obj)/image: $(obj)/btfix.o FORCE
|
||||
|
||||
$(obj)/zImage: $(obj)/image
|
||||
$(call if_changed,strip)
|
||||
|
||||
$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_32 System.map $(ROOT_IMG) FORCE
|
||||
$(call if_changed,elftoaout)
|
||||
$(call if_changed,piggy)
|
||||
@echo ' kernel: $@ is ready'
|
||||
|
||||
$(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE
|
||||
$(call if_changed,btfix)
|
||||
@ -68,11 +64,6 @@ $(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SPARC64),y)
|
||||
quiet_cmd_piggy = PIGGY $@
|
||||
cmd_piggy = $(obj)/piggyback_64 $@ System.map $(ROOT_IMG)
|
||||
quiet_cmd_strip = STRIP $@
|
||||
cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start vmlinux -o $@
|
||||
|
||||
|
||||
# Actual linking
|
||||
$(obj)/image: vmlinux FORCE
|
||||
@ -81,10 +72,6 @@ $(obj)/image: vmlinux FORCE
|
||||
|
||||
$(obj)/zImage: $(obj)/image
|
||||
$(call if_changed,gzip)
|
||||
|
||||
$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_64 System.map $(ROOT_IMG) FORCE
|
||||
$(call if_changed,elftoaout)
|
||||
$(call if_changed,piggy)
|
||||
@echo ' kernel: $@ is ready'
|
||||
|
||||
$(obj)/vmlinux.aout: vmlinux FORCE
|
||||
@ -92,3 +79,6 @@ $(obj)/vmlinux.aout: vmlinux FORCE
|
||||
@echo ' kernel: $@ is ready'
|
||||
endif
|
||||
|
||||
$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE
|
||||
$(call if_changed,elftoaout)
|
||||
$(call if_changed,piggy)
|
||||
|
272
arch/sparc/boot/piggyback.c
Normal file
272
arch/sparc/boot/piggyback.c
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
Simple utility to make a single-image install kernel with initial ramdisk
|
||||
for Sparc tftpbooting without need to set up nfs.
|
||||
|
||||
Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
|
||||
Pete Zaitcev <zaitcev@yahoo.com> endian fixes for cross-compiles, 2000.
|
||||
Copyright (C) 2011 Sam Ravnborg <sam@ravnborg.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/*
|
||||
* Note: run this on an a.out kernel (use elftoaout for it),
|
||||
* as PROM looks for a.out image only.
|
||||
*/
|
||||
|
||||
#define AOUT_TEXT_OFFSET 32
|
||||
|
||||
static int is64bit = 0;
|
||||
|
||||
/* align to power-of-two size */
|
||||
static int align(int n)
|
||||
{
|
||||
if (is64bit)
|
||||
return (n + 0x1fff) & ~0x1fff;
|
||||
else
|
||||
return (n + 0xfff) & ~0xfff;
|
||||
}
|
||||
|
||||
/* read two bytes as big endian */
|
||||
static unsigned short ld2(char *p)
|
||||
{
|
||||
return (p[0] << 8) | p[1];
|
||||
}
|
||||
|
||||
/* save 4 bytes as big endian */
|
||||
static void st4(char *p, unsigned int x)
|
||||
{
|
||||
p[0] = x >> 24;
|
||||
p[1] = x >> 16;
|
||||
p[2] = x >> 8;
|
||||
p[3] = x;
|
||||
}
|
||||
|
||||
static void die(const char *str)
|
||||
{
|
||||
perror(str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
/* fs_img.gz is an image of initial ramdisk. */
|
||||
fprintf(stderr, "Usage: piggyback bits vmlinux.aout System.map fs_img.gz\n");
|
||||
fprintf(stderr, "\tKernel image will be modified in place.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int start_line(const char *line)
|
||||
{
|
||||
if (strcmp(line + 8, " T _start\n") == 0)
|
||||
return 1;
|
||||
else if (strcmp(line + 16, " T _start\n") == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int end_line(const char *line)
|
||||
{
|
||||
if (strcmp(line + 8, " A _end\n") == 0)
|
||||
return 1;
|
||||
else if (strcmp (line + 16, " A _end\n") == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find address for start and end in System.map.
|
||||
* The file looks like this:
|
||||
* f0004000 T _start
|
||||
* f0379f79 A _end
|
||||
* 1234567890123456
|
||||
* ^coloumn 1
|
||||
* There is support for 64 bit addresses too.
|
||||
*
|
||||
* Return 0 if either start or end is not found
|
||||
*/
|
||||
static int get_start_end(const char *filename, unsigned int *start,
|
||||
unsigned int *end)
|
||||
{
|
||||
FILE *map;
|
||||
char buffer[1024];
|
||||
|
||||
*start = 0;
|
||||
*end = 0;
|
||||
map = fopen(filename, "r");
|
||||
if (!map)
|
||||
die(filename);
|
||||
while (fgets(buffer, 1024, map)) {
|
||||
if (start_line(buffer))
|
||||
*start = strtoul(buffer, NULL, 16);
|
||||
else if (end_line(buffer))
|
||||
*end = strtoul(buffer, NULL, 16);
|
||||
}
|
||||
fclose (map);
|
||||
|
||||
if (*start == 0 || *end == 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define LOOKBACK (128 * 4)
|
||||
#define BUFSIZE 1024
|
||||
/*
|
||||
* Find the HdrS entry from head_32/head_64.
|
||||
* We check if it is at the beginning of the file (sparc64 case)
|
||||
* and if not we search for it.
|
||||
* When we search do so in steps of 4 as HdrS is on a 4-byte aligned
|
||||
* address (it is on same alignment as sparc instructions)
|
||||
* Return the offset to the HdrS entry (as off_t)
|
||||
*/
|
||||
static off_t get_hdrs_offset(int kernelfd, const char *filename)
|
||||
{
|
||||
char buffer[BUFSIZE];
|
||||
off_t offset;
|
||||
int i;
|
||||
|
||||
if (lseek(kernelfd, 0, SEEK_SET) < 0)
|
||||
die("lseek");
|
||||
if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE)
|
||||
die(filename);
|
||||
|
||||
if (buffer[40] == 'H' && buffer[41] == 'd' &&
|
||||
buffer[42] == 'r' && buffer[43] == 'S') {
|
||||
return 40;
|
||||
} else {
|
||||
/* Find the gokernel label */
|
||||
/* Decode offset from branch instruction */
|
||||
offset = ld2(buffer + AOUT_TEXT_OFFSET + 2) << 2;
|
||||
/* Go back 512 bytes so we do not miss HdrS */
|
||||
offset -= LOOKBACK;
|
||||
/* skip a.out header */
|
||||
offset += AOUT_TEXT_OFFSET;
|
||||
if (lseek(kernelfd, offset, SEEK_SET) < 0)
|
||||
die("lseek");
|
||||
if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE)
|
||||
die(filename);
|
||||
|
||||
for (i = 0; i < LOOKBACK; i += 4) {
|
||||
if (buffer[i + 0] == 'H' && buffer[i + 1] == 'd' &&
|
||||
buffer[i + 2] == 'r' && buffer[i + 3] == 'S') {
|
||||
return offset + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf (stderr, "Couldn't find headers signature in %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 };
|
||||
char buffer[1024];
|
||||
unsigned int i, start, end;
|
||||
off_t offset;
|
||||
struct stat s;
|
||||
int image, tail;
|
||||
|
||||
if (argc != 5)
|
||||
usage();
|
||||
if (strcmp(argv[1], "64") == 0)
|
||||
is64bit = 1;
|
||||
if (stat (argv[4], &s) < 0)
|
||||
die(argv[4]);
|
||||
|
||||
if (!get_start_end(argv[3], &start, &end)) {
|
||||
fprintf(stderr, "Could not determine start and end from %s\n",
|
||||
argv[3]);
|
||||
exit(1);
|
||||
}
|
||||
if ((image = open(argv[2], O_RDWR)) < 0)
|
||||
die(argv[2]);
|
||||
if (read(image, buffer, 512) != 512)
|
||||
die(argv[2]);
|
||||
if (memcmp(buffer, aout_magic, 4) != 0) {
|
||||
fprintf (stderr, "Not a.out. Don't blame me.\n");
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
* We need to fill in values for
|
||||
* sparc_ramdisk_image + sparc_ramdisk_size
|
||||
* To locate these symbols search for the "HdrS" text which appear
|
||||
* in the image a little before the gokernel symbol.
|
||||
* See definition of these in init_32.S
|
||||
*/
|
||||
|
||||
offset = get_hdrs_offset(image, argv[2]);
|
||||
/* skip HdrS + LINUX_VERSION_CODE + HdrS version */
|
||||
offset += 10;
|
||||
|
||||
if (lseek(image, offset, 0) < 0)
|
||||
die("lseek");
|
||||
|
||||
/*
|
||||
* root_flags = 0
|
||||
* root_dev = 1 (RAMDISK_MAJOR)
|
||||
* ram_flags = 0
|
||||
* sparc_ramdisk_image = "PAGE aligned address after _end")
|
||||
* sparc_ramdisk_size = size of image
|
||||
*/
|
||||
st4(buffer, 0);
|
||||
st4(buffer + 4, 0x01000000);
|
||||
st4(buffer + 8, align(end + 32));
|
||||
st4(buffer + 12, s.st_size);
|
||||
|
||||
if (write(image, buffer + 2, 14) != 14)
|
||||
die(argv[2]);
|
||||
|
||||
/* For sparc64 update a_text and clear a_data + a_bss */
|
||||
if (is64bit)
|
||||
{
|
||||
if (lseek(image, 4, 0) < 0)
|
||||
die("lseek");
|
||||
/* a_text */
|
||||
st4(buffer, align(end + 32 + 8191) - (start & ~0x3fffffUL) +
|
||||
s.st_size);
|
||||
/* a_data */
|
||||
st4(buffer + 4, 0);
|
||||
/* a_bss */
|
||||
st4(buffer + 8, 0);
|
||||
if (write(image, buffer, 12) != 12)
|
||||
die(argv[2]);
|
||||
}
|
||||
|
||||
/* seek page aligned boundary in the image file and add boot image */
|
||||
if (lseek(image, AOUT_TEXT_OFFSET - start + align(end + 32), 0) < 0)
|
||||
die("lseek");
|
||||
if ((tail = open(argv[4], O_RDONLY)) < 0)
|
||||
die(argv[4]);
|
||||
while ((i = read(tail, buffer, 1024)) > 0)
|
||||
if (write(image, buffer, i) != i)
|
||||
die(argv[2]);
|
||||
if (close(image) < 0)
|
||||
die("close");
|
||||
if (close(tail) < 0)
|
||||
die("close");
|
||||
return 0;
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
/*
|
||||
Simple utility to make a single-image install kernel with initial ramdisk
|
||||
for Sparc tftpbooting without need to set up nfs.
|
||||
|
||||
Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
|
||||
Pete Zaitcev <zaitcev@yahoo.com> endian fixes for cross-compiles, 2000.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/*
|
||||
* Note: run this on an a.out kernel (use elftoaout for it),
|
||||
* as PROM looks for a.out image only.
|
||||
*/
|
||||
|
||||
static unsigned short ld2(char *p)
|
||||
{
|
||||
return (p[0] << 8) | p[1];
|
||||
}
|
||||
|
||||
static unsigned int ld4(char *p)
|
||||
{
|
||||
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
|
||||
}
|
||||
|
||||
static void st4(char *p, unsigned int x)
|
||||
{
|
||||
p[0] = x >> 24;
|
||||
p[1] = x >> 16;
|
||||
p[2] = x >> 8;
|
||||
p[3] = x;
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
/* fs_img.gz is an image of initial ramdisk. */
|
||||
fprintf(stderr, "Usage: piggyback vmlinux.aout System.map fs_img.gz\n");
|
||||
fprintf(stderr, "\tKernel image will be modified in place.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void die(char *str)
|
||||
{
|
||||
perror (str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 };
|
||||
char buffer[1024], *q, *r;
|
||||
unsigned int i, j, k, start, end, offset;
|
||||
FILE *map;
|
||||
struct stat s;
|
||||
int image, tail;
|
||||
|
||||
if (argc != 4) usage();
|
||||
start = end = 0;
|
||||
if (stat (argv[3], &s) < 0) die (argv[3]);
|
||||
map = fopen (argv[2], "r");
|
||||
if (!map) die(argv[2]);
|
||||
while (fgets (buffer, 1024, map)) {
|
||||
if (!strcmp (buffer + 8, " T start\n") || !strcmp (buffer + 16, " T start\n"))
|
||||
start = strtoul (buffer, NULL, 16);
|
||||
else if (!strcmp (buffer + 8, " A _end\n") || !strcmp (buffer + 16, " A _end\n"))
|
||||
end = strtoul (buffer, NULL, 16);
|
||||
}
|
||||
fclose (map);
|
||||
if (!start || !end) {
|
||||
fprintf (stderr, "Could not determine start and end from System.map\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]);
|
||||
if (read(image,buffer,512) != 512) die(argv[1]);
|
||||
if (memcmp (buffer, "\177ELF", 4) == 0) {
|
||||
q = buffer + ld4(buffer + 28);
|
||||
i = ld4(q + 4) + ld4(buffer + 24) - ld4(q + 8);
|
||||
if (lseek(image,i,0) < 0) die("lseek");
|
||||
if (read(image,buffer,512) != 512) die(argv[1]);
|
||||
j = 0;
|
||||
} else if (memcmp(buffer, aout_magic, 4) == 0) {
|
||||
i = j = 32;
|
||||
} else {
|
||||
fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n");
|
||||
exit(1);
|
||||
}
|
||||
k = i;
|
||||
i += (ld2(buffer + j + 2)<<2) - 512;
|
||||
if (lseek(image,i,0) < 0) die("lseek");
|
||||
if (read(image,buffer,1024) != 1024) die(argv[1]);
|
||||
for (q = buffer, r = q + 512; q < r; q += 4) {
|
||||
if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S')
|
||||
break;
|
||||
}
|
||||
if (q == r) {
|
||||
fprintf (stderr, "Couldn't find headers signature in the kernel.\n");
|
||||
exit(1);
|
||||
}
|
||||
offset = i + (q - buffer) + 10;
|
||||
if (lseek(image, offset, 0) < 0) die ("lseek");
|
||||
|
||||
st4(buffer, 0);
|
||||
st4(buffer + 4, 0x01000000);
|
||||
st4(buffer + 8, (end + 32 + 4095) & ~4095);
|
||||
st4(buffer + 12, s.st_size);
|
||||
|
||||
if (write(image,buffer+2,14) != 14) die (argv[1]);
|
||||
if (lseek(image, k - start + ((end + 32 + 4095) & ~4095), 0) < 0) die ("lseek");
|
||||
if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]);
|
||||
while ((i = read (tail,buffer,1024)) > 0)
|
||||
if (write(image,buffer,i) != i) die (argv[1]);
|
||||
if (close(image) < 0) die("close");
|
||||
if (close(tail) < 0) die("close");
|
||||
return 0;
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
/*
|
||||
Simple utility to make a single-image install kernel with initial ramdisk
|
||||
for Sparc64 tftpbooting without need to set up nfs.
|
||||
|
||||
Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* Note: run this on an a.out kernel (use elftoaout for it), as PROM looks for a.out image onlly
|
||||
usage: piggyback vmlinux System.map tail, where tail is gzipped fs of the initial ramdisk */
|
||||
|
||||
static void die(char *str)
|
||||
{
|
||||
perror (str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
char buffer [1024], *q, *r;
|
||||
unsigned int i, j, k, start, end, offset;
|
||||
FILE *map;
|
||||
struct stat s;
|
||||
int image, tail;
|
||||
|
||||
start = end = 0;
|
||||
if (stat (argv[3], &s) < 0) die (argv[3]);
|
||||
map = fopen (argv[2], "r");
|
||||
if (!map) die(argv[2]);
|
||||
while (fgets (buffer, 1024, map)) {
|
||||
if (!strcmp (buffer + 19, "_start\n"))
|
||||
start = strtoul (buffer + 8, NULL, 16);
|
||||
else if (!strcmp (buffer + 19, "_end\n"))
|
||||
end = strtoul (buffer + 8, NULL, 16);
|
||||
}
|
||||
fclose (map);
|
||||
if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]);
|
||||
if (read(image,buffer,512) != 512) die(argv[1]);
|
||||
if (!memcmp (buffer, "\177ELF", 4)) {
|
||||
unsigned int *p = (unsigned int *)(buffer + *(unsigned int *)(buffer + 28));
|
||||
|
||||
i = p[1] + *(unsigned int *)(buffer + 24) - p[2];
|
||||
if (lseek(image,i,0) < 0) die("lseek");
|
||||
if (read(image,buffer,512) != 512) die(argv[1]);
|
||||
j = 0;
|
||||
} else if (*(unsigned int *)buffer == 0x01030107) {
|
||||
i = j = 32;
|
||||
} else {
|
||||
fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n");
|
||||
exit(1);
|
||||
}
|
||||
k = i;
|
||||
if (j == 32 && buffer[40] == 'H' && buffer[41] == 'd' && buffer[42] == 'r' && buffer[43] == 'S') {
|
||||
offset = 40 + 10;
|
||||
} else {
|
||||
i += ((*(unsigned short *)(buffer + j + 2))<<2) - 512;
|
||||
if (lseek(image,i,0) < 0) die("lseek");
|
||||
if (read(image,buffer,1024) != 1024) die(argv[1]);
|
||||
for (q = buffer, r = q + 512; q < r; q += 4) {
|
||||
if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S')
|
||||
break;
|
||||
}
|
||||
if (q == r) {
|
||||
fprintf (stderr, "Couldn't find headers signature in the kernel.\n");
|
||||
exit(1);
|
||||
}
|
||||
offset = i + (q - buffer) + 10;
|
||||
}
|
||||
if (lseek(image, offset, 0) < 0) die ("lseek");
|
||||
*(unsigned *)buffer = 0;
|
||||
*(unsigned *)(buffer + 4) = 0x01000000;
|
||||
*(unsigned *)(buffer + 8) = ((end + 32 + 8191) & ~8191);
|
||||
*(unsigned *)(buffer + 12) = s.st_size;
|
||||
if (write(image,buffer+2,14) != 14) die (argv[1]);
|
||||
if (lseek(image, 4, 0) < 0) die ("lseek");
|
||||
*(unsigned *)buffer = ((end + 32 + 8191) & ~8191) - (start & ~0x3fffffUL) + s.st_size;
|
||||
*(unsigned *)(buffer + 4) = 0;
|
||||
*(unsigned *)(buffer + 8) = 0;
|
||||
if (write(image,buffer,12) != 12) die (argv[1]);
|
||||
if (lseek(image, k - start + ((end + 32 + 8191) & ~8191), 0) < 0) die ("lseek");
|
||||
if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]);
|
||||
while ((i = read (tail,buffer,1024)) > 0)
|
||||
if (write(image,buffer,i) != i) die (argv[1]);
|
||||
if (close(image) < 0) die("close");
|
||||
if (close(tail) < 0) die("close");
|
||||
return 0;
|
||||
}
|
@ -224,6 +224,18 @@ static inline void sparc_leon3_disable_cache(void)
|
||||
"sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2");
|
||||
};
|
||||
|
||||
static inline unsigned long sparc_leon3_asr17(void)
|
||||
{
|
||||
u32 asr17;
|
||||
__asm__ __volatile__ ("rd %%asr17, %0\n\t" : "=r"(asr17));
|
||||
return asr17;
|
||||
};
|
||||
|
||||
static inline int sparc_leon3_cpuid(void)
|
||||
{
|
||||
return sparc_leon3_asr17() >> 28;
|
||||
}
|
||||
|
||||
#endif /*!__ASSEMBLY__*/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -100,9 +100,8 @@ struct leon3_irqctrl_regs_map {
|
||||
u32 mpbroadcast;
|
||||
u32 notused02;
|
||||
u32 notused03;
|
||||
u32 notused10;
|
||||
u32 notused11;
|
||||
u32 notused12;
|
||||
u32 ampctrl;
|
||||
u32 icsel[2];
|
||||
u32 notused13;
|
||||
u32 notused20;
|
||||
u32 notused21;
|
||||
@ -112,6 +111,7 @@ struct leon3_irqctrl_regs_map {
|
||||
u32 force[16];
|
||||
/* Extended IRQ registers */
|
||||
u32 intid[16]; /* 0xc0 */
|
||||
u32 unused[(0x1000-0x100)/4];
|
||||
};
|
||||
|
||||
struct leon3_apbuart_regs_map {
|
||||
|
@ -48,18 +48,6 @@ extern void prom_init(struct linux_romvec *rom_ptr);
|
||||
/* Boot argument acquisition, returns the boot command line string. */
|
||||
extern char *prom_getbootargs(void);
|
||||
|
||||
/* Device utilities. */
|
||||
|
||||
/* Map and unmap devices in IO space at virtual addresses. Note that the
|
||||
* virtual address you pass is a request and the prom may put your mappings
|
||||
* somewhere else, so check your return value as that is where your new
|
||||
* mappings really are!
|
||||
*
|
||||
* Another note, these are only available on V2 or higher proms!
|
||||
*/
|
||||
extern char *prom_mapio(char *virt_hint, int io_space, unsigned int phys_addr, unsigned int num_bytes);
|
||||
extern void prom_unmapio(char *virt_addr, unsigned int num_bytes);
|
||||
|
||||
/* Miscellaneous routines, don't really fit in any category per se. */
|
||||
|
||||
/* Reboot the machine with the command line passed. */
|
||||
@ -76,7 +64,7 @@ extern void prom_cmdline(void);
|
||||
/* Enter the prom, with no chance of continuation for the stand-alone
|
||||
* which calls this.
|
||||
*/
|
||||
extern void prom_halt(void) __attribute__ ((noreturn));
|
||||
extern void __noreturn prom_halt(void);
|
||||
|
||||
/* Set the PROM 'sync' callback function to the passed function pointer.
|
||||
* When the user gives the 'sync' command at the prom prompt while the
|
||||
@ -117,25 +105,6 @@ extern void prom_write(const char *buf, unsigned int len);
|
||||
extern int prom_startcpu(int cpunode, struct linux_prom_registers *context_table,
|
||||
int context, char *program_counter);
|
||||
|
||||
/* Stop the CPU with the passed device tree node. */
|
||||
extern int prom_stopcpu(int cpunode);
|
||||
|
||||
/* Idle the CPU with the passed device tree node. */
|
||||
extern int prom_idlecpu(int cpunode);
|
||||
|
||||
/* Re-Start the CPU with the passed device tree node. */
|
||||
extern int prom_restartcpu(int cpunode);
|
||||
|
||||
/* PROM memory allocation facilities... */
|
||||
|
||||
/* Allocated at possibly the given virtual address a chunk of the
|
||||
* indicated size.
|
||||
*/
|
||||
extern char *prom_alloc(char *virt_hint, unsigned int size);
|
||||
|
||||
/* Free a previously allocated chunk. */
|
||||
extern void prom_free(char *virt_addr, unsigned int size);
|
||||
|
||||
/* Sun4/sun4c specific memory-management startup hook. */
|
||||
|
||||
/* Map the passed segment in the given context at the passed
|
||||
@ -144,6 +113,8 @@ extern void prom_free(char *virt_addr, unsigned int size);
|
||||
extern void prom_putsegment(int context, unsigned long virt_addr,
|
||||
int physical_segment);
|
||||
|
||||
/* Initialize the memory lists based upon the prom version. */
|
||||
void prom_meminit(void);
|
||||
|
||||
/* PROM device tree traversal functions... */
|
||||
|
||||
@ -178,19 +149,11 @@ extern int prom_getbool(phandle node, char *prop);
|
||||
/* Acquire a string property, null string on error. */
|
||||
extern void prom_getstring(phandle node, char *prop, char *buf, int bufsize);
|
||||
|
||||
/* Does the passed node have the given "name"? YES=1 NO=0 */
|
||||
extern int prom_nodematch(phandle thisnode, char *name);
|
||||
|
||||
/* Search all siblings starting at the passed node for "name" matching
|
||||
* the given string. Returns the node on success, zero on failure.
|
||||
*/
|
||||
extern phandle prom_searchsiblings(phandle node_start, char *name);
|
||||
|
||||
/* Return the first property type, as a string, for the given node.
|
||||
* Returns a null string on error.
|
||||
*/
|
||||
extern char *prom_firstprop(phandle node, char *buffer);
|
||||
|
||||
/* Returns the next property after the passed property for the given
|
||||
* node. Returns null string on failure.
|
||||
*/
|
||||
@ -199,9 +162,6 @@ extern char *prom_nextprop(phandle node, char *prev_property, char *buffer);
|
||||
/* Returns phandle of the path specified */
|
||||
extern phandle prom_finddevice(char *name);
|
||||
|
||||
/* Returns 1 if the specified node has given property. */
|
||||
extern int prom_node_has_property(phandle node, char *property);
|
||||
|
||||
/* Set the indicated property at the given node with the passed value.
|
||||
* Returns the number of bytes of your value that the prom took.
|
||||
*/
|
||||
@ -219,6 +179,8 @@ extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nr
|
||||
extern void prom_apply_generic_ranges(phandle node, phandle parent,
|
||||
struct linux_prom_registers *sbusregs, int nregs);
|
||||
|
||||
void prom_ranges_init(void);
|
||||
|
||||
/* CPU probing helpers. */
|
||||
int cpu_find_by_instance(int instance, phandle *prom_node, int *mid);
|
||||
int cpu_find_by_mid(int mid, phandle *prom_node);
|
||||
|
@ -18,8 +18,8 @@ extern char prom_version[];
|
||||
*/
|
||||
extern phandle prom_root_node;
|
||||
|
||||
/* PROM stdin and stdout */
|
||||
extern int prom_stdin, prom_stdout;
|
||||
/* PROM stdout */
|
||||
extern int prom_stdout;
|
||||
|
||||
/* /chosen node of the prom device tree, this stays constant after
|
||||
* initialization is complete.
|
||||
|
@ -73,12 +73,11 @@ sun4e_notsup:
|
||||
|
||||
/* The Sparc trap table, bootloader gives us control at _start. */
|
||||
__HEAD
|
||||
.globl start, _stext, _start, __stext
|
||||
.globl _stext, _start, __stext
|
||||
.globl trapbase
|
||||
_start: /* danger danger */
|
||||
__stext:
|
||||
_stext:
|
||||
start:
|
||||
trapbase:
|
||||
#ifdef CONFIG_SMP
|
||||
trapbase_cpu0:
|
||||
|
@ -23,15 +23,16 @@
|
||||
#include "prom.h"
|
||||
#include "irq.h"
|
||||
|
||||
struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address, initialized by amba_init() */
|
||||
struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address, initialized by amba_init() */
|
||||
struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */
|
||||
struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */
|
||||
struct amba_apb_device leon_percpu_timer_dev[16];
|
||||
|
||||
int leondebug_irq_disable;
|
||||
int leon_debug_irqout;
|
||||
static int dummy_master_l10_counter;
|
||||
|
||||
unsigned long leon3_gptimer_irq; /* interrupt controller irq number, initialized by amba_init() */
|
||||
unsigned long leon3_gptimer_irq; /* interrupt controller irq number */
|
||||
unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */
|
||||
unsigned int sparc_leon_eirq;
|
||||
#define LEON_IMASK ((&leon3_irqctrl_regs->mask[0]))
|
||||
|
||||
@ -105,21 +106,79 @@ static void leon_disable_irq(unsigned int irq_nr)
|
||||
void __init leon_init_timers(irq_handler_t counter_fn)
|
||||
{
|
||||
int irq;
|
||||
struct device_node *rootnp, *np, *nnp;
|
||||
struct property *pp;
|
||||
int len;
|
||||
int cpu, icsel;
|
||||
int ampopts;
|
||||
|
||||
leondebug_irq_disable = 0;
|
||||
leon_debug_irqout = 0;
|
||||
master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
|
||||
dummy_master_l10_counter = 0;
|
||||
|
||||
if (leon3_gptimer_regs && leon3_irqctrl_regs) {
|
||||
LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0);
|
||||
LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld,
|
||||
(((1000000 / HZ) - 1)));
|
||||
LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0);
|
||||
/*Find IRQMP IRQ Controller Registers base address otherwise bail out.*/
|
||||
rootnp = of_find_node_by_path("/ambapp0");
|
||||
if (!rootnp)
|
||||
goto bad;
|
||||
np = of_find_node_by_name(rootnp, "GAISLER_IRQMP");
|
||||
if (!np) {
|
||||
np = of_find_node_by_name(rootnp, "01_00d");
|
||||
if (!np)
|
||||
goto bad;
|
||||
}
|
||||
pp = of_find_property(np, "reg", &len);
|
||||
if (!pp)
|
||||
goto bad;
|
||||
leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value;
|
||||
|
||||
/* Find GPTIMER Timer Registers base address otherwise bail out. */
|
||||
nnp = rootnp;
|
||||
do {
|
||||
np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
|
||||
if (!np) {
|
||||
np = of_find_node_by_name(nnp, "01_011");
|
||||
if (!np)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
ampopts = 0;
|
||||
pp = of_find_property(np, "ampopts", &len);
|
||||
if (pp) {
|
||||
ampopts = *(int *)pp->value;
|
||||
if (ampopts == 0) {
|
||||
/* Skip this instance, resource already
|
||||
* allocated by other OS */
|
||||
nnp = np;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Select Timer-Instance on Timer Core. Default is zero */
|
||||
leon3_gptimer_idx = ampopts & 0x7;
|
||||
|
||||
pp = of_find_property(np, "reg", &len);
|
||||
if (pp)
|
||||
leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)
|
||||
pp->value;
|
||||
pp = of_find_property(np, "interrupts", &len);
|
||||
if (pp)
|
||||
leon3_gptimer_irq = *(unsigned int *)pp->value;
|
||||
} while (0);
|
||||
|
||||
if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) {
|
||||
LEON3_BYPASS_STORE_PA(
|
||||
&leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0);
|
||||
LEON3_BYPASS_STORE_PA(
|
||||
&leon3_gptimer_regs->e[leon3_gptimer_idx].rld,
|
||||
(((1000000 / HZ) - 1)));
|
||||
LEON3_BYPASS_STORE_PA(
|
||||
&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs;
|
||||
leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1;
|
||||
leon_percpu_timer_dev[0].irq = leon3_gptimer_irq + 1 +
|
||||
leon3_gptimer_idx;
|
||||
|
||||
if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) &
|
||||
(1<<LEON3_GPTIMER_SEPIRQ))) {
|
||||
@ -127,17 +186,33 @@ void __init leon_init_timers(irq_handler_t counter_fn)
|
||||
BUG();
|
||||
}
|
||||
|
||||
LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].val, 0);
|
||||
LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/HZ) - 1)));
|
||||
LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0);
|
||||
LEON3_BYPASS_STORE_PA(
|
||||
&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0);
|
||||
LEON3_BYPASS_STORE_PA(
|
||||
&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld,
|
||||
(((1000000/HZ) - 1)));
|
||||
LEON3_BYPASS_STORE_PA(
|
||||
&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0);
|
||||
# endif
|
||||
|
||||
/*
|
||||
* The IRQ controller may (if implemented) consist of multiple
|
||||
* IRQ controllers, each mapped on a 4Kb boundary.
|
||||
* Each CPU may be routed to different IRQCTRLs, however
|
||||
* we assume that all CPUs (in SMP system) is routed to the
|
||||
* same IRQ Controller, and for non-SMP only one IRQCTRL is
|
||||
* accessed anyway.
|
||||
* In AMP systems, Linux must run on CPU0 for the time being.
|
||||
*/
|
||||
cpu = sparc_leon3_cpuid();
|
||||
icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]);
|
||||
icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf;
|
||||
leon3_irqctrl_regs += icsel;
|
||||
} else {
|
||||
printk(KERN_ERR "No Timer/irqctrl found\n");
|
||||
BUG();
|
||||
goto bad;
|
||||
}
|
||||
|
||||
irq = request_irq(leon3_gptimer_irq,
|
||||
irq = request_irq(leon3_gptimer_irq+leon3_gptimer_idx,
|
||||
counter_fn,
|
||||
(IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL);
|
||||
|
||||
@ -169,13 +244,13 @@ void __init leon_init_timers(irq_handler_t counter_fn)
|
||||
# endif
|
||||
|
||||
if (leon3_gptimer_regs) {
|
||||
LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl,
|
||||
LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
|
||||
LEON3_GPTIMER_EN |
|
||||
LEON3_GPTIMER_RL |
|
||||
LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl,
|
||||
LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl,
|
||||
LEON3_GPTIMER_EN |
|
||||
LEON3_GPTIMER_RL |
|
||||
LEON3_GPTIMER_LD |
|
||||
@ -183,6 +258,11 @@ void __init leon_init_timers(irq_handler_t counter_fn)
|
||||
#endif
|
||||
|
||||
}
|
||||
return;
|
||||
bad:
|
||||
printk(KERN_ERR "No Timer/irqctrl found\n");
|
||||
BUG();
|
||||
return;
|
||||
}
|
||||
|
||||
void leon_clear_clock_irq(void)
|
||||
|
@ -136,18 +136,29 @@ static void __init ebus_path_component(struct device_node *dp, char *tmp_buf)
|
||||
/* "name:vendor:device@irq,addrlo" */
|
||||
static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf)
|
||||
{
|
||||
struct amba_prom_registers *regs; unsigned int *intr;
|
||||
unsigned int *device, *vendor;
|
||||
struct amba_prom_registers *regs;
|
||||
unsigned int *intr, *device, *vendor, reg0;
|
||||
struct property *prop;
|
||||
int interrupt = 0;
|
||||
|
||||
/* In order to get a unique ID in the device tree (multiple AMBA devices
|
||||
* may have the same name) the node number is printed
|
||||
*/
|
||||
prop = of_find_property(dp, "reg", NULL);
|
||||
if (!prop)
|
||||
return;
|
||||
regs = prop->value;
|
||||
if (!prop) {
|
||||
reg0 = (unsigned int)dp->phandle;
|
||||
} else {
|
||||
regs = prop->value;
|
||||
reg0 = regs->phys_addr;
|
||||
}
|
||||
|
||||
/* Not all cores have Interrupt */
|
||||
prop = of_find_property(dp, "interrupts", NULL);
|
||||
if (!prop)
|
||||
return;
|
||||
intr = prop->value;
|
||||
intr = &interrupt; /* IRQ0 does not exist */
|
||||
else
|
||||
intr = prop->value;
|
||||
|
||||
prop = of_find_property(dp, "vendor", NULL);
|
||||
if (!prop)
|
||||
return;
|
||||
@ -159,7 +170,7 @@ static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf)
|
||||
|
||||
sprintf(tmp_buf, "%s:%d:%d@%x,%x",
|
||||
dp->name, *vendor, *device,
|
||||
*intr, regs->phys_addr);
|
||||
*intr, reg0);
|
||||
}
|
||||
|
||||
static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
|
||||
|
@ -185,7 +185,6 @@ static void __init boot_flags_init(char *commands)
|
||||
|
||||
extern void sun4c_probe_vac(void);
|
||||
extern char cputypval;
|
||||
extern unsigned long start, end;
|
||||
|
||||
extern unsigned short root_flags;
|
||||
extern unsigned short root_dev;
|
||||
@ -210,7 +209,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
int i;
|
||||
unsigned long highest_paddr;
|
||||
|
||||
sparc_ttable = (struct tt_entry *) &start;
|
||||
sparc_ttable = (struct tt_entry *) &trapbase;
|
||||
|
||||
/* Initialize PROM console and command line. */
|
||||
*cmdline_p = prom_getbootargs();
|
||||
|
@ -435,16 +435,14 @@ void __init sun4c_probe_memerr_reg(void)
|
||||
|
||||
static inline void sun4c_init_ss2_cache_bug(void)
|
||||
{
|
||||
extern unsigned long start;
|
||||
|
||||
if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) ||
|
||||
(idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) ||
|
||||
(idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) {
|
||||
/* Whee.. */
|
||||
printk("SS2 cache bug detected, uncaching trap table page\n");
|
||||
sun4c_flush_page((unsigned int) &start);
|
||||
sun4c_put_pte(((unsigned long) &start),
|
||||
(sun4c_get_pte((unsigned long) &start) | _SUN4C_PAGE_NOCACHE));
|
||||
sun4c_flush_page((unsigned int) &_start);
|
||||
sun4c_put_pte(((unsigned long) &_start),
|
||||
(sun4c_get_pte((unsigned long) &_start) | _SUN4C_PAGE_NOCACHE));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,12 +5,10 @@ asflags := -ansi
|
||||
ccflags := -Werror
|
||||
|
||||
lib-y := bootstr_$(BITS).o
|
||||
lib-$(CONFIG_SPARC32) += devmap.o
|
||||
lib-y += init_$(BITS).o
|
||||
lib-$(CONFIG_SPARC32) += memory.o
|
||||
lib-y += misc_$(BITS).o
|
||||
lib-$(CONFIG_SPARC32) += mp.o
|
||||
lib-$(CONFIG_SPARC32) += palloc.o
|
||||
lib-$(CONFIG_SPARC32) += ranges.o
|
||||
lib-$(CONFIG_SPARC32) += segment.o
|
||||
lib-y += console_$(BITS).o
|
||||
|
@ -29,7 +29,8 @@ prom_getbootargs(void)
|
||||
/* Start from 1 and go over fd(0,0,0)kernel */
|
||||
for(iter = 1; iter < 8; iter++) {
|
||||
arg = (*(romvec->pv_v0bootargs))->argv[iter];
|
||||
if(arg == 0) break;
|
||||
if (arg == NULL)
|
||||
break;
|
||||
while(*arg != 0) {
|
||||
/* Leave place for space and null. */
|
||||
if(cp >= barg_buf + BARG_LEN-2){
|
||||
|
@ -27,13 +27,14 @@ static int prom_nbputchar(const char *buf)
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
switch(prom_vers) {
|
||||
case PROM_V0:
|
||||
i = (*(romvec->pv_nbputchar))(*buf);
|
||||
if ((*(romvec->pv_nbputchar))(*buf))
|
||||
i = 1;
|
||||
break;
|
||||
case PROM_V2:
|
||||
case PROM_V3:
|
||||
if ((*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout,
|
||||
buf, 0x1) == 1)
|
||||
i = 0;
|
||||
i = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -47,7 +48,7 @@ void prom_console_write_buf(const char *buf, int len)
|
||||
{
|
||||
while (len) {
|
||||
int n = prom_nbputchar(buf);
|
||||
if (n)
|
||||
if (n < 0)
|
||||
continue;
|
||||
len--;
|
||||
buf++;
|
||||
|
@ -13,8 +13,6 @@
|
||||
#include <asm/system.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
extern int prom_stdin, prom_stdout;
|
||||
|
||||
static int __prom_console_write_buf(const char *buf, int len)
|
||||
{
|
||||
unsigned long args[7];
|
||||
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* promdevmap.c: Map device/IO areas to virtual addresses.
|
||||
*
|
||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <asm/openprom.h>
|
||||
#include <asm/oplib.h>
|
||||
|
||||
extern void restore_current(void);
|
||||
|
||||
/* Just like the routines in palloc.c, these should not be used
|
||||
* by the kernel at all. Bootloader facility mainly. And again,
|
||||
* this is only available on V2 proms and above.
|
||||
*/
|
||||
|
||||
/* Map physical device address 'paddr' in IO space 'ios' of size
|
||||
* 'num_bytes' to a virtual address, with 'vhint' being a hint to
|
||||
* the prom as to where you would prefer the mapping. We return
|
||||
* where the prom actually mapped it.
|
||||
*/
|
||||
char *
|
||||
prom_mapio(char *vhint, int ios, unsigned int paddr, unsigned int num_bytes)
|
||||
{
|
||||
unsigned long flags;
|
||||
char *ret;
|
||||
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
if((num_bytes == 0) || (paddr == 0)) ret = (char *) 0x0;
|
||||
else
|
||||
ret = (*(romvec->pv_v2devops.v2_dumb_mmap))(vhint, ios, paddr,
|
||||
num_bytes);
|
||||
restore_current();
|
||||
spin_unlock_irqrestore(&prom_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Unmap an IO/device area that was mapped using the above routine. */
|
||||
void
|
||||
prom_unmapio(char *vaddr, unsigned int num_bytes)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if(num_bytes == 0x0) return;
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
(*(romvec->pv_v2devops.v2_dumb_munmap))(vaddr, num_bytes);
|
||||
restore_current();
|
||||
spin_unlock_irqrestore(&prom_lock, flags);
|
||||
}
|
@ -18,7 +18,7 @@
|
||||
char prom_version[80];
|
||||
|
||||
/* The root node of the prom device tree. */
|
||||
int prom_stdin, prom_stdout;
|
||||
int prom_stdout;
|
||||
phandle prom_chosen_node;
|
||||
|
||||
/* You must call prom_init() before you attempt to use any of the
|
||||
@ -38,7 +38,6 @@ void __init prom_init(void *cif_handler, void *cif_stack)
|
||||
if (!prom_chosen_node || prom_chosen_node == -1)
|
||||
prom_halt();
|
||||
|
||||
prom_stdin = prom_getint(prom_chosen_node, "stdin");
|
||||
prom_stdout = prom_getint(prom_chosen_node, "stdout");
|
||||
|
||||
node = prom_finddevice("/openprom");
|
||||
|
@ -70,7 +70,7 @@ prom_cmdline(void)
|
||||
/* Drop into the prom, but completely terminate the program.
|
||||
* No chance of continuing.
|
||||
*/
|
||||
void
|
||||
void __noreturn
|
||||
prom_halt(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -41,81 +41,3 @@ prom_startcpu(int cpunode, struct linux_prom_registers *ctable_reg, int ctx, cha
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Stop CPU with device prom-tree node 'cpunode'.
|
||||
* XXX Again, what does the return value really mean? XXX
|
||||
*/
|
||||
int
|
||||
prom_stopcpu(int cpunode)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
switch(prom_vers) {
|
||||
case PROM_V0:
|
||||
case PROM_V2:
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
case PROM_V3:
|
||||
ret = (*(romvec->v3_cpustop))(cpunode);
|
||||
break;
|
||||
};
|
||||
restore_current();
|
||||
spin_unlock_irqrestore(&prom_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Make CPU with device prom-tree node 'cpunode' idle.
|
||||
* XXX Return value, anyone? XXX
|
||||
*/
|
||||
int
|
||||
prom_idlecpu(int cpunode)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
switch(prom_vers) {
|
||||
case PROM_V0:
|
||||
case PROM_V2:
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
case PROM_V3:
|
||||
ret = (*(romvec->v3_cpuidle))(cpunode);
|
||||
break;
|
||||
};
|
||||
restore_current();
|
||||
spin_unlock_irqrestore(&prom_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Resume the execution of CPU with nodeid 'cpunode'.
|
||||
* XXX Come on, somebody has to know... XXX
|
||||
*/
|
||||
int
|
||||
prom_restartcpu(int cpunode)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
switch(prom_vers) {
|
||||
case PROM_V0:
|
||||
case PROM_V2:
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
case PROM_V3:
|
||||
ret = (*(romvec->v3_cpuresume))(cpunode);
|
||||
break;
|
||||
};
|
||||
restore_current();
|
||||
spin_unlock_irqrestore(&prom_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* palloc.c: Memory allocation from the Sun PROM.
|
||||
*
|
||||
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
|
||||
*/
|
||||
|
||||
#include <asm/openprom.h>
|
||||
#include <asm/oplib.h>
|
||||
|
||||
/* You should not call these routines after memory management
|
||||
* has been initialized in the kernel, if fact you should not
|
||||
* use these if at all possible in the kernel. They are mainly
|
||||
* to be used for a bootloader for temporary allocations which
|
||||
* it will free before jumping into the kernel it has loaded.
|
||||
*
|
||||
* Also, these routines don't work on V0 proms, only V2 and later.
|
||||
*/
|
||||
|
||||
/* Allocate a chunk of memory of size 'num_bytes' giving a suggestion
|
||||
* of virtual_hint as the preferred virtual base address of this chunk.
|
||||
* There are no guarantees that you will get the allocation, or that
|
||||
* the prom will abide by your "hint". So check your return value.
|
||||
*/
|
||||
char *
|
||||
prom_alloc(char *virtual_hint, unsigned int num_bytes)
|
||||
{
|
||||
if(prom_vers == PROM_V0) return (char *) 0x0;
|
||||
if(num_bytes == 0x0) return (char *) 0x0;
|
||||
return (*(romvec->pv_v2devops.v2_dumb_mem_alloc))(virtual_hint, num_bytes);
|
||||
}
|
||||
|
||||
/* Free a previously allocated chunk back to the prom at virtual address
|
||||
* 'vaddr' of size 'num_bytes'. NOTE: This vaddr is not the hint you
|
||||
* used for the allocation, but the virtual address the prom actually
|
||||
* returned to you. They may be have been the same, they may have not,
|
||||
* doesn't matter.
|
||||
*/
|
||||
void
|
||||
prom_free(char *vaddr, unsigned int num_bytes)
|
||||
{
|
||||
if((prom_vers == PROM_V0) || (num_bytes == 0x0)) return;
|
||||
(*(romvec->pv_v2devops.v2_dumb_mem_free))(vaddr, num_bytes);
|
||||
}
|
@ -13,8 +13,8 @@
|
||||
#include <asm/types.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX];
|
||||
int num_obio_ranges;
|
||||
static struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX];
|
||||
static int num_obio_ranges;
|
||||
|
||||
/* Adjust register values based upon the ranges parameters. */
|
||||
static void
|
||||
@ -35,7 +35,7 @@ prom_adjust_regs(struct linux_prom_registers *regp, int nregs,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1,
|
||||
struct linux_prom_ranges *ranges2, int nranges2)
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ extern void restore_current(void);
|
||||
static char promlib_buf[128];
|
||||
|
||||
/* Internal version of prom_getchild that does not alter return values. */
|
||||
phandle __prom_getchild(phandle node)
|
||||
static phandle __prom_getchild(phandle node)
|
||||
{
|
||||
unsigned long flags;
|
||||
phandle cnode;
|
||||
@ -52,7 +52,7 @@ phandle prom_getchild(phandle node)
|
||||
EXPORT_SYMBOL(prom_getchild);
|
||||
|
||||
/* Internal version of prom_getsibling that does not alter return values. */
|
||||
phandle __prom_getsibling(phandle node)
|
||||
static phandle __prom_getsibling(phandle node)
|
||||
{
|
||||
unsigned long flags;
|
||||
phandle cnode;
|
||||
@ -177,20 +177,6 @@ void prom_getstring(phandle node, char *prop, char *user_buf, int ubuf_size)
|
||||
EXPORT_SYMBOL(prom_getstring);
|
||||
|
||||
|
||||
/* Does the device at node 'node' have name 'name'?
|
||||
* YES = 1 NO = 0
|
||||
*/
|
||||
int prom_nodematch(phandle node, char *name)
|
||||
{
|
||||
int error;
|
||||
|
||||
static char namebuf[128];
|
||||
error = prom_getproperty(node, "name", namebuf, sizeof(namebuf));
|
||||
if (error == -1) return 0;
|
||||
if(strcmp(namebuf, name) == 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Search siblings at 'node_start' for a node with name
|
||||
* 'nodename'. Return node if successful, zero if not.
|
||||
*/
|
||||
@ -214,7 +200,7 @@ phandle prom_searchsiblings(phandle node_start, char *nodename)
|
||||
EXPORT_SYMBOL(prom_searchsiblings);
|
||||
|
||||
/* Interal version of nextprop that does not alter return values. */
|
||||
char *__prom_nextprop(phandle node, char * oprop)
|
||||
static char *__prom_nextprop(phandle node, char * oprop)
|
||||
{
|
||||
unsigned long flags;
|
||||
char *prop;
|
||||
@ -227,17 +213,6 @@ char *__prom_nextprop(phandle node, char * oprop)
|
||||
return prop;
|
||||
}
|
||||
|
||||
/* Return the first property name for node 'node'. */
|
||||
/* buffer is unused argument, but as v9 uses it, we need to have the same interface */
|
||||
char *prom_firstprop(phandle node, char *bufer)
|
||||
{
|
||||
if (node == 0 || node == -1)
|
||||
return "";
|
||||
|
||||
return __prom_nextprop(node, "");
|
||||
}
|
||||
EXPORT_SYMBOL(prom_firstprop);
|
||||
|
||||
/* Return the property type string after property type 'oprop'
|
||||
* at node 'node' . Returns empty string if no more
|
||||
* property types for this node.
|
||||
@ -299,19 +274,6 @@ phandle prom_finddevice(char *name)
|
||||
}
|
||||
EXPORT_SYMBOL(prom_finddevice);
|
||||
|
||||
int prom_node_has_property(phandle node, char *prop)
|
||||
{
|
||||
char *current_property = "";
|
||||
|
||||
do {
|
||||
current_property = prom_nextprop(node, current_property, NULL);
|
||||
if(!strcmp(current_property, prop))
|
||||
return 1;
|
||||
} while (*current_property);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(prom_node_has_property);
|
||||
|
||||
/* Set property 'pname' at node 'node' to value 'value' which has a length
|
||||
* of 'size' bytes. Return the number of bytes the prom accepted.
|
||||
*/
|
||||
@ -320,8 +282,10 @@ int prom_setprop(phandle node, const char *pname, char *value, int size)
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if(size == 0) return 0;
|
||||
if((pname == 0) || (value == 0)) return 0;
|
||||
if (size == 0)
|
||||
return 0;
|
||||
if ((pname == NULL) || (value == NULL))
|
||||
return 0;
|
||||
spin_lock_irqsave(&prom_lock, flags);
|
||||
ret = prom_nodeops->no_setprop(node, pname, value, size);
|
||||
restore_current();
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/serial_core.h>
|
||||
@ -573,13 +574,15 @@ static int __devinit apbuart_probe(struct platform_device *op,
|
||||
printk(KERN_INFO "grlib-apbuart at 0x%llx, irq %d\n",
|
||||
(unsigned long long) port->mapbase, port->irq);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static struct of_device_id __initdata apbuart_match[] = {
|
||||
{
|
||||
.name = "GAISLER_APBUART",
|
||||
},
|
||||
{
|
||||
.name = "01_00c",
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
@ -620,9 +623,12 @@ static void grlib_apbuart_configure(void)
|
||||
int *vendor = (int *) of_get_property(np, "vendor", NULL);
|
||||
int *device = (int *) of_get_property(np, "device", NULL);
|
||||
int *irqs = (int *) of_get_property(np, "interrupts", NULL);
|
||||
int *ampopts = (int *) of_get_property(np, "ampopts", NULL);
|
||||
regs = (struct amba_prom_registers *)
|
||||
of_get_property(np, "reg", NULL);
|
||||
|
||||
if (ampopts && (*ampopts == 0))
|
||||
continue; /* Ignore if used by another OS instance */
|
||||
if (vendor)
|
||||
v = *vendor;
|
||||
if (device)
|
||||
|
@ -2969,10 +2969,8 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
|
||||
{
|
||||
struct atyfb_par *par = info->par;
|
||||
struct device_node *dp;
|
||||
char prop[128];
|
||||
phandle node;
|
||||
int len, i, j, ret;
|
||||
u32 mem, chip_id;
|
||||
int i, j, ret;
|
||||
|
||||
/*
|
||||
* Map memory-mapped registers.
|
||||
@ -3088,23 +3086,8 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
|
||||
aty_st_le32(MEM_CNTL, mem, par);
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is the console device, we will set default video
|
||||
* settings to what the PROM left us with.
|
||||
*/
|
||||
node = prom_getchild(prom_root_node);
|
||||
node = prom_searchsiblings(node, "aliases");
|
||||
if (node) {
|
||||
len = prom_getproperty(node, "screen", prop, sizeof(prop));
|
||||
if (len > 0) {
|
||||
prop[len] = '\0';
|
||||
node = prom_finddevice(prop);
|
||||
} else
|
||||
node = 0;
|
||||
}
|
||||
|
||||
dp = pci_device_to_OF_node(pdev);
|
||||
if (node == dp->phandle) {
|
||||
if (dp == of_console_device) {
|
||||
struct fb_var_screeninfo *var = &default_var;
|
||||
unsigned int N, P, Q, M, T, R;
|
||||
u32 v_total, h_total;
|
||||
@ -3112,9 +3095,9 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
|
||||
u8 pll_regs[16];
|
||||
u8 clock_cntl;
|
||||
|
||||
crtc.vxres = prom_getintdefault(node, "width", 1024);
|
||||
crtc.vyres = prom_getintdefault(node, "height", 768);
|
||||
var->bits_per_pixel = prom_getintdefault(node, "depth", 8);
|
||||
crtc.vxres = of_getintprop_default(dp, "width", 1024);
|
||||
crtc.vyres = of_getintprop_default(dp, "height", 768);
|
||||
var->bits_per_pixel = of_getintprop_default(dp, "depth", 8);
|
||||
var->xoffset = var->yoffset = 0;
|
||||
crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
|
||||
crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
|
||||
|
Loading…
Reference in New Issue
Block a user