Commit 87530db5 authored by Linus Torvalds's avatar Linus Torvalds
parents a148058c d5f07900
......@@ -139,17 +139,14 @@ drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/
drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
defaultimage-$(CONFIG_PPC32) := zImage
# Default to zImage, override when needed
defaultimage-y := zImage
defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
defaultimage-$(CONFIG_PPC_PSERIES) := zImage
KBUILD_IMAGE := $(defaultimage-y)
all: $(KBUILD_IMAGE)
CPPFLAGS_vmlinux.lds := -Upowerpc
# All the instructions talk about "make bzImage".
bzImage: zImage
BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage
.PHONY: $(BOOT_TARGETS)
......
......@@ -25,8 +25,8 @@ HOSTCC := gcc
BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \
$(shell $(CROSS32CC) -print-file-name=include) -fPIC
BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
BOOTLFLAGS := -T $(srctree)/$(src)/zImage.lds
OBJCOPYFLAGS := contents,alloc,load,readonly,data
OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000
zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h
......@@ -35,7 +35,7 @@ zliblinuxheader := zlib.h zconf.h zutil.h
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
#$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
src-boot := string.S prom.c main.c div64.S crt0.S
src-boot := crt0.S string.S prom.c stdio.c main.c div64.S
src-boot += $(zlib)
src-boot := $(addprefix $(obj)/, $(src-boot))
obj-boot := $(addsuffix .o, $(basename $(src-boot)))
......@@ -70,7 +70,7 @@ quiet_cmd_bootas = BOOTAS $@
cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
quiet_cmd_bootld = BOOTLD $@
cmd_bootld = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(2)
cmd_bootld = $(CROSS32LD) -T $(srctree)/$(src)/$(3) -o $@ $(2)
$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c
$(call if_changed_dep,bootcc)
......@@ -87,12 +87,14 @@ obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section)))
src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section)))
gz-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section)))
hostprogs-y := addnote addRamDisk
targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \
$(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
$(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
$(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
vmlinux.initrd
hostprogs-y := addnote addRamDisk hack-coff
targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \
zImage.coff zImage.initrd.coff \
$(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
$(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
$(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
vmlinux.initrd
extra-y := initrd.o
quiet_cmd_ramdisk = RAMDISK $@
......@@ -114,6 +116,10 @@ quiet_cmd_addsection = ADDSEC $@
quiet_cmd_addnote = ADDNOTE $@
cmd_addnote = $(obj)/addnote $@
quiet_cmd_gencoff = COFF $@
cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $@ && \
$(obj)/hack-coff $@
$(call gz-sec, $(required)): $(obj)/kernel-%.gz: %
$(call if_changed,gzip)
......@@ -127,22 +133,35 @@ $(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c
$(call if_changed_dep,bootcc)
$(call cmd,addsection)
$(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required))
$(obj)/zImage.vmode $(obj)/zImage.coff: obj-boot += $(call obj-sec, $(required))
$(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds
$(call cmd,bootld,$(obj-boot))
$(call cmd,bootld,$(obj-boot),zImage.lds)
$(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd))
$(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec, $(required) $(initrd))
$(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds
$(call cmd,bootld,$(obj-boot))
$(call cmd,bootld,$(obj-boot),zImage.lds)
# For 32-bit powermacs, build the COFF images as well as the ELF images.
coffimage-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.coff
coffrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.initrd.coff
$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote
$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y)
@cp -f $< $@
$(call if_changed,addnote)
$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote
$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote $(coffrdimg-y-y)
@cp -f $< $@
$(call if_changed,addnote)
$(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff
$(call cmd,bootld,$(obj-boot),zImage.coff.lds)
$(call cmd,gencoff)
$(obj)/zImage.initrd.coff: $(call obj-sec, $(required) $(initrd)) $(obj-boot) \
$(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff
$(call cmd,bootld,$(obj-boot),zImage.coff.lds)
$(call cmd,gencoff)
#-----------------------------------------------------------
# build u-boot images
#-----------------------------------------------------------
......
......@@ -12,17 +12,23 @@
#include "ppc_asm.h"
.text
/* a procedure descriptor used when booting this as a COFF file */
_zimage_start_opd:
.long _zimage_start, 0, 0, 0
.globl _zimage_start
_zimage_start:
/* Work out the offset between the address we were linked at
and the address where we're running. */
bl 1f
1:
mflr r0
1: mflr r0
lis r9,1b@ha
addi r9,r9,1b@l
subf. r0,r9,r0
beq 3f
beq 3f /* if running at same address as linked */
/* The .got2 section contains a list of addresses, so add
the address offset onto each entry. */
lis r9,__got2_start@ha
addi r9,r9,__got2_start@l
lis r8,__got2_end@ha
......@@ -32,15 +38,14 @@ _zimage_start:
srwi. r8,r8,2
mtctr r8
add r9,r0,r9
2:
lwz r8,0(r9)
2: lwz r8,0(r9)
add r8,r8,r0
stw r8,0(r9)
addi r9,r9,4
bdnz 2b
3:
lis r9,_start@h
/* Do a cache flush for our text, in case OF didn't */
3: lis r9,_start@h
add r9,r0,r9
lis r8,_etext@ha
addi r8,r8,_etext@l
......
/*
* hack-coff.c - hack the header of an xcoff file to fill in
* a few fields needed by the Open Firmware xcoff loader on
* Power Macs but not initialized by objcopy.
*
* Copyright (C) Paul Mackerras 1997.
*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include "rs6000.h"
#define AOUT_MAGIC 0x010b
#define get_16be(x) ((((unsigned char *)(x))[0] << 8) \
+ ((unsigned char *)(x))[1])
#define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \
((unsigned char *)(x))[1] = (v) & 0xff)
#define get_32be(x) ((((unsigned char *)(x))[0] << 24) \
+ (((unsigned char *)(x))[1] << 16) \
+ (((unsigned char *)(x))[2] << 8) \
+ ((unsigned char *)(x))[3])
int
main(int ac, char **av)
{
int fd;
int i, nsect;
int aoutsz;
struct external_filehdr fhdr;
AOUTHDR aout;
struct external_scnhdr shdr;
if (ac != 2) {
fprintf(stderr, "Usage: hack-coff coff-file\n");
exit(1);
}
if ((fd = open(av[1], 2)) == -1) {
perror(av[2]);
exit(1);
}
if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr))
goto readerr;
i = get_16be(fhdr.f_magic);
if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) {
fprintf(stderr, "%s: not an xcoff file\n", av[1]);
exit(1);
}
aoutsz = get_16be(fhdr.f_opthdr);
if (read(fd, &aout, aoutsz) != aoutsz)
goto readerr;
nsect = get_16be(fhdr.f_nscns);
for (i = 0; i < nsect; ++i) {
if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr))
goto readerr;
if (strcmp(shdr.s_name, ".text") == 0) {
put_16be(aout.o_snentry, i+1);
put_16be(aout.o_sntext, i+1);
} else if (strcmp(shdr.s_name, ".data") == 0) {
put_16be(aout.o_sndata, i+1);
} else if (strcmp(shdr.s_name, ".bss") == 0) {
put_16be(aout.o_snbss, i+1);
}
}
put_16be(aout.magic, AOUT_MAGIC);
if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1
|| write(fd, &aout, aoutsz) != aoutsz) {
fprintf(stderr, "%s: write error\n", av[1]);
exit(1);
}
close(fd);
exit(0);
readerr:
fprintf(stderr, "%s: read error or file too short\n", av[1]);
exit(1);
}
......@@ -21,8 +21,8 @@ extern void flush_cache(void *, unsigned long);
/* Value picked to match that used by yaboot */
#define PROG_START 0x01400000
#define RAM_END (512<<20) // Fixme: use OF */
#define PROG_START 0x01400000 /* only used on 64-bit systems */
#define RAM_END (512<<20) /* Fixme: use OF */
#define ONE_MB 0x100000
extern char _start[];
......@@ -160,6 +160,17 @@ static int is_elf64(void *hdr)
elfoffset = (unsigned long)elf64ph->p_offset;
vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
#if defined(PROG_START)
/*
* Maintain a "magic" minimum address. This keeps some older
* firmware platforms running.
*/
if (claim_base < PROG_START)
claim_base = PROG_START;
#endif
return 1;
}
......@@ -206,12 +217,18 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
exit();
if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
exit();
stderr = stdout;
if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
exit();
printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
/*
* The first available claim_base must be above the end of the
* the loaded kernel wrapper file (_start to _end includes the
* initrd image if it is present) and rounded up to a nice
* 1 MB boundary for good measure.
*/
claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
vmlinuz.addr = (unsigned long)_vmlinux_start;
vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
......@@ -228,25 +245,6 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
exit();
}
/*
* The first available claim_base must be above the end of the
* the loaded kernel wrapper file (_start to _end includes the
* initrd image if it is present) and rounded up to a nice
* 1 MB boundary for good measure.
*/
claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
#if defined(PROG_START)
/*
* Maintain a "magic" minimum address. This keeps some older
* firmware platforms running.
*/
if (claim_base < PROG_START)
claim_base = PROG_START;
#endif
/* We need to claim the memsize plus the file offset since gzip
* will expand the header (file offset), then the kernel, then
* possible rubbish we don't care about. But the kernel bss must
......
This diff is collapsed.
#ifndef _PPC_BOOT_PROM_H_
#define _PPC_BOOT_PROM_H_
typedef void *phandle;
typedef void *ihandle;
extern int (*prom) (void *);
extern void *chosen_handle;
extern phandle chosen_handle;
extern ihandle stdout;
extern void *stdin;
extern void *stdout;
extern void *stderr;
int call_prom(const char *service, int nargs, int nret, ...);
int call_prom_ret(const char *service, int nargs, int nret,
unsigned int *rets, ...);
extern int write(void *handle, void *ptr, int nb);
extern int read(void *handle, void *ptr, int nb);
extern void exit(void);
extern void pause(void);
extern void *finddevice(const char *);
extern void *claim(unsigned long virt, unsigned long size, unsigned long align);
extern int getprop(void *phandle, const char *name, void *buf, int buflen);
extern void *claim(unsigned long virt, unsigned long size, unsigned long aln);
static inline void exit(void)
{
call_prom("exit", 0, 0);
}
static inline phandle finddevice(const char *name)
{
return (phandle) call_prom("finddevice", 1, 1, name);
}
static inline int getprop(void *phandle, const char *name,
void *buf, int buflen)
{
return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
}
#endif /* _PPC_BOOT_PROM_H_ */
/* IBM RS/6000 "XCOFF" file definitions for BFD.
Copyright (C) 1990, 1991 Free Software Foundation, Inc.
FIXME: Can someone provide a transliteration of this name into ASCII?
Using the following chars caused a compiler warning on HIUX (so I replaced
them with octal escapes), and isn't useful without an understanding of what
character set it is.
Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM
and John Gilmore of Cygnus Support. */
/********************** FILE HEADER **********************/
struct external_filehdr {
char f_magic[2]; /* magic number */
char f_nscns[2]; /* number of sections */
char f_timdat[4]; /* time & date stamp */
char f_symptr[4]; /* file pointer to symtab */
char f_nsyms[4]; /* number of symtab entries */
char f_opthdr[2]; /* sizeof(optional hdr) */
char f_flags[2]; /* flags */
};
/* IBM RS/6000 */
#define U802WRMAGIC 0730 /* writeable text segments **chh** */
#define U802ROMAGIC 0735 /* readonly sharable text segments */
#define U802TOCMAGIC 0737 /* readonly text segments and TOC */
#define BADMAG(x) \
((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \
(x).f_magic != U802TOCMAGIC)
#define FILHDR struct external_filehdr
#define FILHSZ 20
/********************** AOUT "OPTIONAL HEADER" **********************/
typedef struct
{
unsigned char magic[2]; /* type of file */
unsigned char vstamp[2]; /* version stamp */
unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */
unsigned char dsize[4]; /* initialized data " " */
unsigned char bsize[4]; /* uninitialized data " " */
unsigned char entry[4]; /* entry pt. */
unsigned char text_start[4]; /* base of text used for this file */
unsigned char data_start[4]; /* base of data used for this file */
unsigned char o_toc[4]; /* address of TOC */
unsigned char o_snentry[2]; /* section number of entry point */
unsigned char o_sntext[2]; /* section number of .text section */
unsigned char o_sndata[2]; /* section number of .data section */
unsigned char o_sntoc[2]; /* section number of TOC */
unsigned char o_snloader[2]; /* section number of .loader section */
unsigned char o_snbss[2]; /* section number of .bss section */
unsigned char o_algntext[2]; /* .text alignment */
unsigned char o_algndata[2]; /* .data alignment */
unsigned char o_modtype[2]; /* module type (??) */
unsigned char o_cputype[2]; /* cpu type */
unsigned char o_maxstack[4]; /* max stack size (??) */
unsigned char o_maxdata[4]; /* max data size (??) */
unsigned char o_resv2[12]; /* reserved */
}
AOUTHDR;
#define AOUTSZ 72
#define SMALL_AOUTSZ (28)
#define AOUTHDRSZ 72
#define RS6K_AOUTHDR_OMAGIC 0x0107 /* old: text & data writeable */
#define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */
#define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */
/********************** SECTION HEADER **********************/
struct external_scnhdr {
char s_name[8]; /* section name */
char s_paddr[4]; /* physical address, aliased s_nlib */
char s_vaddr[4]; /* virtual address */
char s_size[4]; /* section size */
char s_scnptr[4]; /* file ptr to raw data for section */
char s_relptr[4]; /* file ptr to relocation */
char s_lnnoptr[4]; /* file ptr to line numbers */
char s_nreloc[2]; /* number of relocation entries */
char s_nlnno[2]; /* number of line number entries*/
char s_flags[4]; /* flags */
};
/*
* names of "special" sections
*/
#define _TEXT ".text"
#define _DATA ".data"
#define _BSS ".bss"
#define _PAD ".pad"
#define _LOADER ".loader"
#define SCNHDR struct external_scnhdr
#define SCNHSZ 40
/* XCOFF uses a special .loader section with type STYP_LOADER. */
#define STYP_LOADER 0x1000
/* XCOFF uses a special .debug section with type STYP_DEBUG. */
#define STYP_DEBUG 0x2000
/* XCOFF handles line number or relocation overflow by creating
another section header with STYP_OVRFLO set. */
#define STYP_OVRFLO 0x8000
/********************** LINE NUMBERS **********************/
/* 1 line number entry for every "breakpointable" source line in a section.
* Line numbers are grouped on a per function basis; first entry in a function
* grouping will have l_lnno = 0 and in place of physical address will be the
* symbol table index of the function name.
*/
struct external_lineno {
union {
char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
char l_paddr[4]; /* (physical) address of line number */
} l_addr;
char l_lnno[2]; /* line number */
};
#define LINENO struct external_lineno
#define LINESZ 6
/********************** SYMBOLS **********************/
#define E_SYMNMLEN 8 /* # characters in a symbol name */
#define E_FILNMLEN 14 /* # characters in a file name */
#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
struct external_syment
{
union {
char e_name[E_SYMNMLEN];
struct {
char e_zeroes[4];
char e_offset[4];
} e;
} e;
char e_value[4];
char e_scnum[2];
char e_type[2];
char e_sclass[1];
char e_numaux[1];
};
#define N_BTMASK (017)
#define N_TMASK (060)
#define N_BTSHFT (4)
#define N_TSHIFT (2)
union external_auxent {
struct {
char x_tagndx[4]; /* str, un, or enum tag indx */
union {
struct {
char x_lnno[2]; /* declaration line number */
char x_size[2]; /* str/union/array size */
} x_lnsz;
char x_fsize[4]; /* size of function */
} x_misc;
union {
struct { /* if ISFCN, tag, or .bb */
char x_lnnoptr[4]; /* ptr to fcn line # */
char x_endndx[4]; /* entry ndx past block end */
} x_fcn;
struct { /* if ISARY, up to 4 dimen. */
char x_dimen[E_DIMNUM][2];
} x_ary;
} x_fcnary;
char x_tvndx[2]; /* tv index */
} x_sym;
union {
char x_fname[E_FILNMLEN];
struct {
char x_zeroes[4];
char x_offset[4];
} x_n;
} x_file;
struct {
char x_scnlen[4]; /* section length */
char x_nreloc[2]; /* # relocation entries */
char x_nlinno[2]; /* # line numbers */
} x_scn;
struct {
char x_tvfill[4]; /* tv fill value */
char x_tvlen[2]; /* length of .tv */
char x_tvran[2][2]; /* tv range */
} x_tv; /* info about .tv section (in auxent of symbol .tv)) */
struct {
unsigned char x_scnlen[4];
unsigned char x_parmhash[4];
unsigned char x_snhash[2];
unsigned char x_smtyp[1];
unsigned char x_smclas[1];
unsigned char x_stab[4];
unsigned char x_snstab[2];
} x_csect;
};
#define SYMENT struct external_syment
#define SYMESZ 18
#define AUXENT union external_auxent
#define AUXESZ 18
#define DBXMASK 0x80 /* for dbx storage mask */
#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK)
/********************** RELOCATION DIRECTIVES **********************/
struct external_reloc {
char r_vaddr[4];
char r_symndx[4];
char r_size[1];
char r_type[1];
};
#define RELOC struct external_reloc
#define RELSZ 10
#define DEFAULT_DATA_SECTION_ALIGNMENT 4
#define DEFAULT_BSS_SECTION_ALIGNMENT 4
#define DEFAULT_TEXT_SECTION_ALIGNMENT 4
/* For new sections we havn't heard of before */
#define DEFAULT_SECTION_ALIGNMENT 4
/*
* Copyright (C) Paul Mackerras 1997.
*
* 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.
*/
#include <stdarg.h>
#include <stddef.h>
#include "string.h"
#include "stdio.h"
#include "prom.h"
size_t strnlen(const char * s, size_t count)
{
const char *sc;
for (sc = s; count-- && *sc != '\0'; ++sc)
/* nothing */;
return sc - s;
}
extern unsigned int __div64_32(unsigned long long *dividend,
unsigned int divisor);
/* The unnecessary pointer compare is there
* to check for type safety (n must be 64bit)
*/
# define do_div(n,base) ({ \
unsigned int __base = (base); \
unsigned int __rem; \
(void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \
if (((n) >> 32) == 0) { \
__rem = (unsigned int)(n) % __base; \
(n) = (unsigned int)(n) / __base; \
} else \
__rem = __div64_32(&(n), __base); \
__rem; \
})
static int skip_atoi(const char **s)
{
int i, c;
for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
i = i*10 + c - '0';
return i;
}
#define ZEROPAD 1 /* pad with zero */
#define SIGN 2 /* unsigned/signed long */
#define PLUS 4 /* show plus */
#define SPACE 8 /* space if plus */
#define LEFT 16 /* left justified */
#define SPECIAL 32 /* 0x */
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
{
char c,sign,tmp[66];
const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
int i;
if (type & LARGE)
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (type & LEFT)
type &= ~ZEROPAD;
if (base < 2 || base > 36)
return 0;
c = (type & ZEROPAD) ? '0' : ' ';
sign = 0;
if (type & SIGN) {
if ((signed long long)num < 0) {
sign = '-';
num = - (signed long long)num;
size--;
} else if (type & PLUS) {
sign = '+';
size--;
} else if (type & SPACE) {
sign = ' ';
size--;
}
}
if (type & SPECIAL) {
if (base == 16)
size -= 2;
else if (base == 8)
size--;
}
i = 0;
if (num == 0)
tmp[i++]='0';
else while (num != 0) {
tmp[i++] = digits[do_div(num, base)];
}
if (i > precision)
precision = i;
size -= precision;
if (!(type&(ZEROPAD+LEFT)))
while(size-->0)
*str++ = ' ';
if (sign)
*str++ = sign;
if (type & SPECIAL) {
if (base==8)
*str++ = '0';
else if (base==16) {
*str++ = '0';
*str++ = digits[33];
}
}
if (!(type & LEFT))
while (size-- > 0)
*str++ = c;
while (i < precision--)
*str++ = '0';
while (i-- > 0)
*str++ = tmp[i];
while (size-- > 0)
*str++ = ' ';
return str;
}
int vsprintf(char *buf, const char *fmt, va_list args)
{
int len;
unsigned long long num;
int i, base;
char * str;
const char *s;
int flags; /* flags to number() */
int field_width; /* width of output field */
int precision; /* min. # of digits for integers; max
number of chars for from string */
int qualifier; /* 'h', 'l', or 'L' for integer fields */
/* 'z' support added 23/7/1999 S.H. */
/* 'z' changed to 'Z' --davidm 1/25/99 */
for (str=buf ; *fmt ; ++fmt) {
if (*fmt != '%') {
*str++ = *fmt;
continue;
}
/* process flags */
flags = 0;
repeat:
++fmt; /* this also skips first '%' */
switch (*fmt) {
case '-': flags |= LEFT; goto repeat;
case '+': flags |= PLUS; goto repeat;
case ' ': flags |= SPACE; goto repeat;
case '#': flags |= SPECIAL; goto repeat;
case '0': flags |= ZEROPAD; goto repeat;
}
/* get field width */
field_width = -1;
if ('0' <= *fmt && *fmt <= '9')
field_width = skip_atoi(&fmt);
else if (*fmt == '*') {
++fmt;
/* it's the next argument */
field_width = va_arg(args, int);
if (field_width < 0) {
field_width = -field_width;
flags |= LEFT;
}
}
/* get the precision */
precision = -1;
if (*fmt == '.') {
++fmt;
if ('0' <= *fmt && *fmt <= '9')
precision = skip_atoi(&fmt);
else if (*fmt == '*') {
++fmt;
/* it's the next argument */
precision = va_arg(args, int);
}
if (precision < 0)
precision = 0;
}
/* get the conversion qualifier */
qualifier = -1;
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
qualifier = *fmt;
++fmt;
}
/* default base */
base = 10;
switch (*fmt) {
case 'c':
if (!(flags & LEFT))
while (--field_width > 0)
*str++ = ' ';
*str++ = (unsigned char) va_arg(args, int);
while (--field_width > 0)
*str++ = ' ';
continue;
case 's':
s = va_arg(args, char *);
if (!s)
s = "<NULL>";
len = strnlen(s, precision);
if (!(flags & LEFT))
while (len < field_width--)
*str++ = ' ';
for (i = 0; i < len; ++i)
*str++ = *s++;
while (len < field_width--)
*str++ = ' ';
continue;
case 'p':
if (field_width == -1) {
field_width = 2*sizeof(void *);
flags |= ZEROPAD;
}
str = number(str,
(unsigned long) va_arg(args, void *), 16,
field_width, precision, flags);
continue;
case 'n':
if (qualifier == 'l') {
long * ip = va_arg(args, long *);
*ip = (str - buf);
} else if (qualifier == 'Z') {
size_t * ip = va_arg(args, size_t *);
*ip = (str - buf);
} else {
int * ip = va_arg(args, int *);
*ip = (str - buf);
}
continue;
case '%':
*str++ = '%';
continue;
/* integer number formats - set up the flags and "break" */
case 'o':
base = 8;
break;
case 'X':
flags |= LARGE;
case 'x':
base = 16;
break;
case 'd':
case 'i':
flags |= SIGN;
case 'u':
break;
default:
*str++ = '%';
if (*fmt)
*str++ = *fmt;
else
--fmt;
continue;
}
if (qualifier == 'l') {
num = va_arg(args, unsigned long);
if (flags & SIGN)
num = (signed long) num;
} else if (qualifier == 'Z') {
num = va_arg(args, size_t);
} else if (qualifier == 'h') {
num = (unsigned short) va_arg(args, int);
if (flags & SIGN)
num = (signed short) num;
} else {
num = va_arg(args, unsigned int);
if (flags & SIGN)
num = (signed int) num;
}
str = number(str, num, base, field_width, precision, flags);
}
*str = '\0';
return str-buf;
}
int sprintf(char * buf, const char *fmt, ...)
{
va_list args;
int i;
va_start(args, fmt);
i=vsprintf(buf,fmt,args);
va_end(args);
return i;
}
static char sprint_buf[1024];
int
printf(const char *fmt, ...)
{
va_list args;
int n;
va_start(args, fmt);
n = vsprintf(sprint_buf, fmt, args);
va_end(args);
write(stdout, sprint_buf, n);
return n;
}
......@@ -7,10 +7,4 @@ extern int sprintf(char *buf, const char *fmt, ...);
extern int vsprintf(char *buf, const char *fmt, va_list args);
extern int putc(int c, void *f);
extern int putchar(int c);
extern int getchar(void);
extern int fputs(char *str, void *f);
#endif /* _PPC_BOOT_STDIO_H_ */
......@@ -107,10 +107,12 @@ memcpy:
rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */
addi r6,r3,-4
addi r4,r4,-4
beq 2f /* if less than 8 bytes to do */
beq 3f /* if less than 8 bytes to do */
andi. r0,r6,3 /* get dest word aligned */
mtctr r7
bne 5f
andi. r0,r4,3 /* check src word aligned too */
bne 3f
1: lwz r7,4(r4)
lwzu r8,8(r4)
stw r7,4(r6)
......@@ -132,6 +134,11 @@ memcpy:
bdnz 4b
blr
5: subfic r0,r0,4
cmpw cr1,r0,r5
add r7,r0,r4
andi. r7,r7,3 /* will source be word-aligned too? */
ble cr1,3b
bne 3b /* do byte-by-byte if not */
mtctr r0
6: lbz r7,4(r4)
addi r4,r4,1
......@@ -149,10 +156,12 @@ backwards_memcpy:
rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */
add r6,r3,r5
add r4,r4,r5
beq 2f
beq 3f
andi. r0,r6,3
mtctr r7
bne 5f
andi. r0,r4,3
bne 3f
1: lwz r7,-4(r4)
lwzu r8,-8(r4)
stw r7,-4(r6)
......@@ -171,7 +180,12 @@ backwards_memcpy:
stbu r0,-1(r6)
bdnz 4b
blr
5: mtctr r0
5: cmpw cr1,r0,r5
subf r7,r0,r4
andi. r7,r7,3
ble cr1,3b
bne 3b
mtctr r0
6: lbzu r7,-1(r4)
stbu r7,-1(r6)
bdnz 6b
......
OUTPUT_ARCH(powerpc:common)
ENTRY(_start)
SECTIONS
{
. = (5*1024*1024);
_start = .;
.text :
{
*(.text)
*(.fixup)
}
_etext = .;
. = ALIGN(4096);
.data :
{
*(.rodata*)
*(.data*)
*(.sdata*)
__got2_start = .;
*(.got2)
__got2_end = .;
_vmlinux_start = .;
*(.kernel:vmlinux.strip)
_vmlinux_end = .;
_initrd_start = .;
*(.kernel:initrd)
_initrd_end = .;
}
. = ALIGN(4096);
_edata = .;
__bss_start = .;
.bss :
{
*(.sbss)
*(.bss)
}
_end = . ;
/DISCARD/ :
{
*(.comment)
}
}
This diff is collapsed.
......@@ -135,7 +135,7 @@ int main(void)
DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb));
DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca));
DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr));
DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0));
......
......@@ -130,7 +130,7 @@ _GLOBAL(__save_cpu_setup)
mfcr r7
/* Get storage ptr */
LOADADDR(r5,cpu_state_storage)
LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
/* We only deal with 970 for now */
mfspr r0,SPRN_PVR
......@@ -164,7 +164,7 @@ _GLOBAL(__restore_cpu_setup)
/* Get storage ptr (FIXME when using anton reloc as we
* are running with translation disabled here
*/
LOADADDR(r5,cpu_state_storage)
LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
/* We only deal with 970 for now */
mfspr r0,SPRN_PVR
......
This diff is collapsed.
......@@ -988,7 +988,7 @@ _GLOBAL(enter_rtas)
stwu r1,-INT_FRAME_SIZE(r1)
mflr r0
stw r0,INT_FRAME_SIZE+4(r1)
LOADADDR(r4, rtas)
LOAD_REG_ADDR(r4, rtas)
lis r6,1f@ha /* physical return address for rtas */
addi r6,r6,1f@l
tophys(r6,r6)
......
......@@ -511,7 +511,8 @@ restore:
cmpdi 0,r5,0
beq 4f
/* Check for pending interrupts (iSeries) */
ld r3,PACALPPACA+LPPACAANYINT(r13)
ld r3,PACALPPACAPTR(r13)
ld r3,LPPACAANYINT(r3)
cmpdi r3,0
beq+ 4f /* skip do_IRQ if no interrupts */
......@@ -689,9 +690,8 @@ _GLOBAL(enter_rtas)
std r6,PACASAVEDMSR(r13)
/* Setup our real return addr */
SET_REG_TO_LABEL(r4,.rtas_return_loc)
SET_REG_TO_CONST(r9,PAGE_OFFSET)
sub r4,r4,r9
LOAD_REG_ADDR(r4,.rtas_return_loc)
clrldi r4,r4,2 /* convert to realmode address */
mtlr r4
li r0,0
......@@ -706,7 +706,7 @@ _GLOBAL(enter_rtas)
sync /* disable interrupts so SRR0/1 */
mtmsrd r0 /* don't get trashed */
SET_REG_TO_LABEL(r4,rtas)
LOAD_REG_ADDR(r4, rtas)
ld r5,RTASENTRY(r4) /* get the rtas->entry value */
ld r4,RTASBASE(r4) /* get the rtas->base value */
......@@ -718,8 +718,7 @@ _GLOBAL(enter_rtas)
_STATIC(rtas_return_loc)
/* relocation is off at this point */
mfspr r4,SPRN_SPRG3 /* Get PACA */
SET_REG_TO_CONST(r5, PAGE_OFFSET)
sub r4,r4,r5 /* RELOC the PACA base pointer */
clrldi r4,r4,2 /* convert to realmode address */
mfmsr r6
li r0,MSR_RI
......@@ -728,7 +727,7 @@ _STATIC(rtas_return_loc)
mtmsrd r6
ld r1,PACAR1(r4) /* Restore our SP */
LOADADDR(r3,.rtas_restore_regs)
LOAD_REG_IMMEDIATE(r3,.rtas_restore_regs)
ld r4,PACASAVEDMSR(r4) /* Restore our MSR */
mtspr SPRN_SRR0,r3
......
......@@ -39,9 +39,9 @@ _GLOBAL(load_up_fpu)
* to another. Instead we call giveup_fpu in switch_to.
*/
#ifndef CONFIG_SMP
LOADBASE(r3, last_task_used_math)
LOAD_REG_ADDRBASE(r3, last_task_used_math)
toreal(r3)
PPC_LL r4,OFF(last_task_used_math)(r3)
PPC_LL r4,ADDROFF(last_task_used_math)(r3)
PPC_LCMPI 0,r4,0
beq 1f
toreal(r4)
......@@ -77,7 +77,7 @@ _GLOBAL(load_up_fpu)
#ifndef CONFIG_SMP
subi r4,r5,THREAD
fromreal(r4)
PPC_STL r4,OFF(last_task_used_math)(r3)
PPC_STL r4,ADDROFF(last_task_used_math)(r3)
#endif /* CONFIG_SMP */
/* restore registers and return */
/* we haven't used ctr or xer or lr */
......@@ -113,8 +113,8 @@ _GLOBAL(giveup_fpu)
1:
#ifndef CONFIG_SMP
li r5,0
LOADBASE(r4,last_task_used_math)
PPC_STL r5,OFF(last_task_used_math)(r4)
LOAD_REG_ADDRBASE(r4,last_task_used_math)
PPC_STL r5,ADDROFF(last_task_used_math)(r4)
#endif /* CONFIG_SMP */
blr
......
This diff is collapsed.
......@@ -38,14 +38,14 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
/* We must dynamically check for the NAP feature as it
* can be cleared by CPU init after the fixups are done
*/
LOADBASE(r3,cur_cpu_spec)
ld r4,OFF(cur_cpu_spec)(r3)
LOAD_REG_ADDRBASE(r3,cur_cpu_spec)
ld r4,ADDROFF(cur_cpu_spec)(r3)
ld r4,CPU_SPEC_FEATURES(r4)
andi. r0,r4,CPU_FTR_CAN_NAP
beqlr
/* Now check if user or arch enabled NAP mode */
LOADBASE(r3,powersave_nap)
lwz r4,OFF(powersave_nap)(r3)
LOAD_REG_ADDRBASE(r3,powersave_nap)
lwz r4,ADDROFF(powersave_nap)(r3)
cmpwi 0,r4,0
beqlr
......
......@@ -238,14 +238,10 @@ void do_IRQ(struct pt_regs *regs)
irq_exit();
#ifdef CONFIG_PPC_ISERIES
{
struct paca_struct *lpaca = get_paca();
if (lpaca->lppaca.int_dword.fields.decr_int) {
lpaca->lppaca.int_dword.fields.decr_int = 0;
/* Signal a fake decrementer interrupt */
timer_interrupt(regs);
}
if (get_lppaca()->int_dword.fields.decr_int) {
get_lppaca()->int_dword.fields.decr_int = 0;
/* Signal a fake decrementer interrupt */
timer_interrupt(regs);
}
#endif
}
......
......@@ -55,15 +55,13 @@ static unsigned long get_purr(void)
{
unsigned long sum_purr = 0;
int cpu;
struct paca_struct *lpaca;
for_each_cpu(cpu) {
lpaca = paca + cpu;
sum_purr += lpaca->lppaca.emulated_time_base;
sum_purr += lppaca[cpu].emulated_time_base;
#ifdef PURR_DEBUG
printk(KERN_INFO "get_purr for cpu (%d) has value (%ld) \n",
cpu, lpaca->lppaca.emulated_time_base);
cpu, lppaca[cpu].emulated_time_base);
#endif
}
return sum_purr;
......@@ -79,12 +77,11 @@ static int lparcfg_data(struct seq_file *m, void *v)
unsigned long pool_id, lp_index;
int shared, entitled_capacity, max_entitled_capacity;
int processors, max_processors;
struct paca_struct *lpaca = get_paca();
unsigned long purr = get_purr();
seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
shared = (int)(lpaca->lppaca_ptr->shared_proc);
shared = (int)(get_lppaca()->shared_proc);
seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n",
e2a(xItExtVpdPanel.mfgID[2]),
e2a(xItExtVpdPanel.mfgID[3]),
......@@ -402,7 +399,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
(h_resource >> 0 * 8) & 0xffff);
/* pool related entries are apropriate for shared configs */
if (paca[0].lppaca.shared_proc) {
if (lppaca[0].shared_proc) {
h_pic(&pool_idle_time, &pool_procs);
......@@ -451,7 +448,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
seq_printf(m, "partition_potential_processors=%d\n",
partition_potential_processors);
seq_printf(m, "shared_processor_mode=%d\n", paca[0].lppaca.shared_proc);
seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc);
return 0;
}
......
......@@ -68,7 +68,7 @@ _GLOBAL(reloc_offset)
mflr r0
bl 1f
1: mflr r3
LOADADDR(r4,1b)
LOAD_REG_IMMEDIATE(r4,1b)
subf r3,r4,r3
mtlr r0
blr
......@@ -80,7 +80,7 @@ _GLOBAL(add_reloc_offset)
mflr r0
bl 1f
1: mflr r5
LOADADDR(r4,1b)
LOAD_REG_IMMEDIATE(r4,1b)
subf r5,r4,r5
add r3,r3,r5
mtlr r0
......
......@@ -39,7 +39,7 @@ _GLOBAL(reloc_offset)
mflr r0
bl 1f
1: mflr r3
LOADADDR(r4,1b)
LOAD_REG_IMMEDIATE(r4,1b)
subf r3,r4,r3
mtlr r0
blr
......@@ -51,7 +51,7 @@ _GLOBAL(add_reloc_offset)
mflr r0
bl 1f
1: mflr r5
LOADADDR(r4,1b)
LOAD_REG_IMMEDIATE(r4,1b)
subf r5,r4,r5
add r3,r3,r5
mtlr r0
......@@ -498,15 +498,15 @@ _GLOBAL(identify_cpu)
*/
_GLOBAL(do_cpu_ftr_fixups)
/* Get CPU 0 features */
LOADADDR(r6,cur_cpu_spec)
LOAD_REG_IMMEDIATE(r6,cur_cpu_spec)
sub r6,r6,r3
ld r4,0(r6)
sub r4,r4,r3
ld r4,CPU_SPEC_FEATURES(r4)
/* Get the fixup table */
LOADADDR(r6,__start___ftr_fixup)
LOAD_REG_IMMEDIATE(r6,__start___ftr_fixup)
sub r6,r6,r3
LOADADDR(r7,__stop___ftr_fixup)
LOAD_REG_IMMEDIATE(r7,__stop___ftr_fixup)
sub r7,r7,r3
/* Do the fixup */
1: cmpld r6,r7
......
......@@ -25,6 +25,28 @@
* field correctly */
extern unsigned long __toc_start;
/*
* iSeries structure which the hypervisor knows about - this structure
* should not cross a page boundary. The vpa_init/register_vpa call
* is now known to fail if the lppaca structure crosses a page
* boundary. The lppaca is also used on POWER5 pSeries boxes. The
* lppaca is 640 bytes long, and cannot readily change since the
* hypervisor knows its layout, so a 1kB alignment will suffice to
* ensure that it doesn't cross a page boundary.
*/
struct lppaca lppaca[] = {
[0 ... (NR_CPUS-1)] = {
.desc = 0xd397d781, /* "LpPa" */
.size = sizeof(struct lppaca),
.dyn_proc_status = 2,
.decr_val = 0x00ff0000,
.fpregs_in_use = 1,
.end_of_quantum = 0xfffffffffffffffful,
.slb_count = 64,
.vmxregs_in_use = 0,
},
};
/* The Paca is an array with one entry per processor. Each contains an
* lppaca, which contains the information shared between the
* hypervisor and Linux.
......@@ -35,27 +57,17 @@ extern unsigned long __toc_start;
* processor (not thread).
*/
#define PACA_INIT_COMMON(number, start, asrr, asrv) \
.lppaca_ptr = &lppaca[number], \
.lock_token = 0x8000, \
.paca_index = (number), /* Paca Index */ \
.kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \
.stab_real = (asrr), /* Real pointer to segment table */ \
.stab_addr = (asrv), /* Virt pointer to segment table */ \
.cpu_start = (start), /* Processor start */ \
.hw_cpu_id = 0xffff, \
.lppaca = { \
.desc = 0xd397d781, /* "LpPa" */ \
.size = sizeof(struct lppaca), \
.dyn_proc_status = 2, \
.decr_val = 0x00ff0000, \
.fpregs_in_use = 1, \
.end_of_quantum = 0xfffffffffffffffful, \
.slb_count = 64, \
.vmxregs_in_use = 0, \
}, \
.hw_cpu_id = 0xffff,
#ifdef CONFIG_PPC_ISERIES
#define PACA_INIT_ISERIES(number) \
.lppaca_ptr = &paca[number].lppaca, \
.reg_save_ptr = &iseries_reg_save[number],
#define PACA_INIT(number) \
......
......@@ -230,8 +230,7 @@ EXPORT_SYMBOL(__down_interruptible);
EXPORT_SYMBOL(cpm_install_handler);
EXPORT_SYMBOL(cpm_free_handler);
#endif /* CONFIG_8xx */
#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx) ||\
defined(CONFIG_83xx)
#if defined(CONFIG_8xx) || defined(CONFIG_40x)
EXPORT_SYMBOL(__res);
#endif
......
......@@ -1627,6 +1627,11 @@ static void of_node_release(struct kref *kref)
kfree(prop->value);
kfree(prop);
prop = next;
if (!prop) {
prop = node->deadprops;
node->deadprops = NULL;
}
}
kfree(node->intrs);
kfree(node->full_name);
......@@ -1774,22 +1779,32 @@ static int __init prom_reconfig_setup(void)
__initcall(prom_reconfig_setup);
#endif
/*
* Find a property with a given name for a given node
* and return the value.
*/
unsigned char *get_property(struct device_node *np, const char *name,
int *lenp)
struct property *of_find_property(struct device_node *np, const char *name,
int *lenp)
{
struct property *pp;
read_lock(&devtree_lock);
for (pp = np->properties; pp != 0; pp = pp->next)
if (strcmp(pp->name, name) == 0) {
if (lenp != 0)
*lenp = pp->length;
return pp->value;
break;
}
return NULL;
read_unlock(&devtree_lock);
return pp;
}
/*
* Find a property with a given name for a given node
* and return the value.
*/
unsigned char *get_property(struct device_node *np, const char *name,
int *lenp)
{
struct property *pp = of_find_property(np,name,lenp);
return pp ? pp->value : NULL;
}
EXPORT_SYMBOL(get_property);
......@@ -1823,4 +1838,82 @@ int prom_add_property(struct device_node* np, struct property* prop)
return 0;
}
/*
* Remove a property from a node. Note that we don't actually
* remove it, since we have given out who-knows-how-many pointers
* to the data using get-property. Instead we just move the property
* to the "dead properties" list, so it won't be found any more.
*/
int prom_remove_property(struct device_node *np, struct property *prop)
{
struct property **next;
int found = 0;
write_lock(&devtree_lock);
next = &np->properties;
while (*next) {
if (*next == prop) {
/* found the node */
*next = prop->next;
prop->next = np->deadprops;
np->deadprops = prop;
found = 1;
break;
}
next = &(*next)->next;
}
write_unlock(&devtree_lock);
if (!found)
return -ENODEV;
#ifdef CONFIG_PROC_DEVICETREE
/* try to remove the proc node as well */
if (np->pde)
proc_device_tree_remove_prop(np->pde, prop);
#endif /* CONFIG_PROC_DEVICETREE */
return 0;
}
/*
* Update a property in a node. Note that we don't actually
* remove it, since we have given out who-knows-how-many pointers
* to the data using get-property. Instead we just move the property
* to the "dead properties" list, and add the new property to the
* property list
*/
int prom_update_property(struct device_node *np,
struct property *newprop,
struct property *oldprop)
{
struct property **next;
int found = 0;
write_lock(&devtree_lock);
next = &np->properties;
while (*next) {
if (*next == oldprop) {
/* found the node */
newprop->next = oldprop->next;
*next = newprop;
oldprop->next = np->deadprops;
np->deadprops = oldprop;
found = 1;
break;
}
next = &(*next)->next;
}
write_unlock(&devtree_lock);
if (!found)
return -ENODEV;
#ifdef CONFIG_PROC_DEVICETREE
/* try to add to proc as well if it was initialized */
if (np->pde)
proc_device_tree_update_prop(np->pde, newprop, oldprop);
#endif /* CONFIG_PROC_DEVICETREE */
return 0;
}
......@@ -113,7 +113,8 @@ static unsigned int of_bus_default_get_flags(u32 *addr)
static int of_bus_pci_match(struct device_node *np)
{
return !strcmp(np->type, "pci");
/* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */
return !strcmp(np->type, "pci") || !strcmp(np->type, "vci");
}
static void of_bus_pci_count_cells(struct device_node *np,
......
......@@ -36,6 +36,11 @@ struct rtas_t rtas = {
.lock = SPIN_LOCK_UNLOCKED
};
struct rtas_suspend_me_data {
long waiting;
struct rtas_args *args;
};
EXPORT_SYMBOL(rtas);
DEFINE_SPINLOCK(rtas_data_buf_lock);
......@@ -556,6 +561,80 @@ void rtas_os_term(char *str)
} while (status == RTAS_BUSY);
}
static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE;
#ifdef CONFIG_PPC_PSERIES
static void rtas_percpu_suspend_me(void *info)
{
long rc;
long flags;
struct rtas_suspend_me_data *data =
(struct rtas_suspend_me_data *)info;
/*
* We use "waiting" to indicate our state. As long
* as it is >0, we are still trying to all join up.
* If it goes to 0, we have successfully joined up and
* one thread got H_Continue. If any error happens,
* we set it to <0.
*/
local_irq_save(flags);
do {
rc = plpar_hcall_norets(H_JOIN);
smp_rmb();
} while (rc == H_Success && data->waiting > 0);
if (rc == H_Success)
goto out;
if (rc == H_Continue) {
data->waiting = 0;
rtas_call(ibm_suspend_me_token, 0, 1,
data->args->args);
} else {
data->waiting = -EBUSY;
printk(KERN_ERR "Error on H_Join hypervisor call\n");
}
out:
/* before we restore interrupts, make sure we don't
* generate a spurious soft lockup errors
*/
touch_softlockup_watchdog();
local_irq_restore(flags);
return;
}
static int rtas_ibm_suspend_me(struct rtas_args *args)
{
int i;
struct rtas_suspend_me_data data;
data.waiting = 1;
data.args = args;
/* Call function on all CPUs. One of us will make the
* rtas call
*/
if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0))
data.waiting = -EINVAL;
if (data.waiting != 0)
printk(KERN_ERR "Error doing global join\n");
/* Prod each CPU. This won't hurt, and will wake
* anyone we successfully put to sleep with H_Join
*/
for_each_cpu(i)
plpar_hcall_norets(H_PROD, i);
return data.waiting;
}
#else /* CONFIG_PPC_PSERIES */
static int rtas_ibm_suspend_me(struct rtas_args *args)
{
return -ENOSYS;
}
#endif
asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
{
......@@ -563,6 +642,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
unsigned long flags;
char *buff_copy, *errbuf = NULL;
int nargs;
int rc;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
......@@ -581,6 +661,17 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
nargs * sizeof(rtas_arg_t)) != 0)
return -EFAULT;
if (args.token == RTAS_UNKNOWN_SERVICE)
return -EINVAL;
/* Need to handle ibm,suspend_me call specially */
if (args.token == ibm_suspend_me_token) {
rc = rtas_ibm_suspend_me(&args);
if (rc)
return rc;
goto copy_return;
}
buff_copy = get_errorlog_buffer();
spin_lock_irqsave(&rtas.lock, flags);
......@@ -604,6 +695,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
kfree(buff_copy);
}
copy_return:
/* Copy out args. */
if (copy_to_user(uargs->args + nargs,
args.args + nargs,
......@@ -675,8 +767,10 @@ void __init rtas_initialize(void)
* the stop-self token if any
*/
#ifdef CONFIG_PPC64
if (_machine == PLATFORM_PSERIES_LPAR)
if (_machine == PLATFORM_PSERIES_LPAR) {
rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
ibm_suspend_me_token = rtas_token("ibm,suspend-me");
}
#endif
rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region);
......
......@@ -100,7 +100,8 @@ void machine_shutdown(void)
void machine_restart(char *cmd)
{
machine_shutdown();
ppc_md.restart(cmd);
if (ppc_md.restart)
ppc_md.restart(cmd);
#ifdef CONFIG_SMP
smp_send_stop();
#endif
......@@ -112,7 +113,8 @@ void machine_restart(char *cmd)
void machine_power_off(void)
{
machine_shutdown();
ppc_md.power_off();
if (ppc_md.power_off)
ppc_md.power_off();
#ifdef CONFIG_SMP
smp_send_stop();
#endif
......@@ -129,7 +131,8 @@ EXPORT_SYMBOL_GPL(pm_power_off);
void machine_halt(void)
{
machine_shutdown();
ppc_md.halt();
if (ppc_md.halt)
ppc_md.halt();
#ifdef CONFIG_SMP
smp_send_stop();
#endif
......
......@@ -431,7 +431,7 @@ void timer_interrupt(struct pt_regs * regs)
profile_tick(CPU_PROFILING, regs);
#ifdef CONFIG_PPC_ISERIES
get_paca()->lppaca.int_dword.fields.decr_int = 0;
get_lppaca()->int_dword.fields.decr_int = 0;
#endif
while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu)))
......
......@@ -28,15 +28,13 @@
void __spin_yield(raw_spinlock_t *lock)
{
unsigned int lock_value, holder_cpu, yield_count;
struct paca_struct *holder_paca;
lock_value = lock->slock;
if (lock_value == 0)
return;
holder_cpu = lock_value & 0xffff;
BUG_ON(holder_cpu >= NR_CPUS);
holder_paca = &paca[holder_cpu];
yield_count = holder_paca->lppaca.yield_count;
yield_count = lppaca[holder_cpu].yield_count;
if ((yield_count & 1) == 0)
return; /* virtual cpu is currently running */
rmb();
......@@ -60,15 +58,13 @@ void __rw_yield(raw_rwlock_t *rw)
{
int lock_value;
unsigned int holder_cpu, yield_count;
struct paca_struct *holder_paca;
lock_value = rw->lock;
if (lock_value >= 0)
return; /* no write lock at present */
holder_cpu = lock_value & 0xffff;
BUG_ON(holder_cpu >= NR_CPUS);
holder_paca = &paca[holder_cpu];
yield_count = holder_paca->lppaca.yield_count;
yield_count = lppaca[holder_cpu].yield_count;
if ((yield_count & 1) == 0)
return; /* virtual cpu is currently running */
rmb();
......
......@@ -140,19 +140,19 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
switch (cur_cpu_spec->oprofile_type) {
#ifdef CONFIG_PPC64
case RS64:
case PPC_OPROFILE_RS64:
model = &op_model_rs64;
break;
case POWER4:
case PPC_OPROFILE_POWER4:
model = &op_model_power4;
break;
#else
case G4:
case PPC_OPROFILE_G4:
model = &op_model_7450;
break;
#endif
#ifdef CONFIG_FSL_BOOKE
case BOOKE:
case PPC_OPROFILE_BOOKE:
model = &op_model_fsl_booke;
break;
#endif
......
......@@ -7,6 +7,7 @@ choice
config MPC834x_SYS
bool "Freescale MPC834x SYS"
select DEFAULT_UIMAGE
help
This option enables support for the MPC 834x SYS evaluation board.
......
/*
* arch/powerpc/platforms/83xx/mpc834x_sys.c
*
* MPC834x SYS board specific routines
*
* Maintainer: Kumar Gala <galak@kernel.crashing.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.
*/
#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/reboot.h>
#include <linux/pci.h>
#include <linux/kdev_t.h>
#include <linux/major.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/root_dev.h>
#include <linux/module.h>
#include <linux/fsl_devices.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/atomic.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
#include <asm/ipic.h>
#include <asm/bootinfo.h>
#include <asm/pci-bridge.h>
#include <asm/mpc83xx.h>
#include <asm/irq.h>
#include <mm/mmu_decl.h>
#include <asm/prom.h>
#include <asm/udbg.h>
#include <sysdev/fsl_soc.h>
#include "mpc83xx.h"
#ifndef CONFIG_PCI
unsigned long isa_io_base = 0;
unsigned long isa_mem_base = 0;
#endif
#ifdef CONFIG_PCI
extern int mpc83xx_pci2_busno;
static int
mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
{
static char pci_irq_table[][4] =
/*
* PCI IDSEL/INTPIN->INTLINE
* A B C D
*/
{
{PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */
{PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */
{PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x13 */
{0, 0, 0, 0},
{PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */
{PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */
{PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */
{PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */
{0, 0, 0, 0}, /* idsel 0x19 */
{0, 0, 0, 0}, /* idsel 0x20 */
};
const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4;
return PCI_IRQ_TABLE_LOOKUP;
}
static int
mpc83xx_exclude_device(u_char bus, u_char devfn)
{
if (bus == 0 && PCI_SLOT(devfn) == 0)
return PCIBIOS_DEVICE_NOT_FOUND;
if (mpc83xx_pci2_busno)
if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0)
return PCIBIOS_DEVICE_NOT_FOUND;
return PCIBIOS_SUCCESSFUL;
}
#endif /* CONFIG_PCI */
/* ************************************************************************
*
* Setup the architecture
*
*/
static void __init
mpc834x_sys_setup_arch(void)
{
struct device_node *np;
if (ppc_md.progress)
ppc_md.progress("mpc834x_sys_setup_arch()", 0);
np = of_find_node_by_type(NULL, "cpu");
if (np != 0) {
unsigned int *fp = (int *) get_property(np, "clock-frequency", NULL);
if (fp != 0)
loops_per_jiffy = *fp / HZ;
else
loops_per_jiffy = 50000000 / HZ;
of_node_put(np);
}
#ifdef CONFIG_PCI
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
add_bridge(np);
ppc_md.pci_swizzle = common_swizzle;
ppc_md.pci_map_irq = mpc83xx_map_irq;
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
#endif
#ifdef CONFIG_ROOT_NFS
ROOT_DEV = Root_NFS;
#else
ROOT_DEV = Root_HDA1;
#endif
}
void __init
mpc834x_sys_init_IRQ(void)
{
u8 senses[8] = {
0, /* EXT 0 */
IRQ_SENSE_LEVEL, /* EXT 1 */
IRQ_SENSE_LEVEL, /* EXT 2 */
0, /* EXT 3 */
#ifdef CONFIG_PCI
IRQ_SENSE_LEVEL, /* EXT 4 */
IRQ_SENSE_LEVEL, /* EXT 5 */
IRQ_SENSE_LEVEL, /* EXT 6 */
IRQ_SENSE_LEVEL, /* EXT 7 */
#else
0, /* EXT 4 */
0, /* EXT 5 */
0, /* EXT 6 */
0, /* EXT 7 */
#endif
};
ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8);
/* Initialize the default interrupt mapping priorities,
* in case the boot rom changed something on us.
*/
ipic_set_default_priority();
}
#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
extern ulong ds1374_get_rtc_time(void);
extern int ds1374_set_rtc_time(ulong);
static int __init
mpc834x_rtc_hookup(void)
{
struct timespec tv;
ppc_md.get_rtc_time = ds1374_get_rtc_time;
ppc_md.set_rtc_time = ds1374_set_rtc_time;
tv.tv_nsec = 0;
tv.tv_sec = (ppc_md.get_rtc_time)();
do_settimeofday(&tv);
return 0;
}
late_initcall(mpc834x_rtc_hookup);
#endif
static void
mpc83xx_restart(char *cmd)
{
#define RST_OFFSET 0x00000900
#define RST_PROT_REG 0x00000018
#define RST_CTRL_REG 0x0000001c
__be32 __iomem *reg;
// map reset register space
reg = ioremap(get_immrbase() + 0x900, 0xff);
local_irq_disable();
/* enable software reset "RSTE" */
out_be32(reg + (RST_PROT_REG >> 2), 0x52535445);
/* set software hard reset */
out_be32(reg + (RST_CTRL_REG >> 2), 0x52535445);
for(;;);
}
static long __init
mpc83xx_time_init(void)
{
#define SPCR_OFFSET 0x00000110
#define SPCR_TBEN 0x00400000
__be32 __iomem *spcr = ioremap(get_immrbase() + SPCR_OFFSET, 4);
__be32 tmp;
tmp = in_be32(spcr);
out_be32(spcr, tmp|SPCR_TBEN);
iounmap(spcr);
return 0;
}
void __init
platform_init(void)
{
/* setup the PowerPC module struct */
ppc_md.setup_arch = mpc834x_sys_setup_arch;
ppc_md.init_IRQ = mpc834x_sys_init_IRQ;
ppc_md.get_irq = ipic_get_irq;
ppc_md.restart = mpc83xx_restart;
ppc_md.time_init = mpc83xx_time_init;
ppc_md.set_rtc_time = NULL;
ppc_md.get_rtc_time = NULL;
ppc_md.calibrate_decr = generic_calibrate_decr;
ppc_md.progress = udbg_progress;
if (ppc_md.progress)
ppc_md.progress("mpc834x_sys_init(): exit", 0);
return;
}
/*
* arch/powerppc/platforms/83xx/mpc834x_sys.h
*
* MPC834X SYS common board definitions
*
* Maintainer: Kumar Gala <galak@kernel.crashing.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.
*
*/
#ifndef __MACH_MPC83XX_SYS_H__
#define __MACH_MPC83XX_SYS_H__
#define PIRQA MPC83xx_IRQ_EXT4
#define PIRQB MPC83xx_IRQ_EXT5
#define PIRQC MPC83xx_IRQ_EXT6
#define PIRQD MPC83xx_IRQ_EXT7
#endif /* __MACH_MPC83XX_SYS_H__ */
#ifndef __MPC83XX_H__
#define __MPC83XX_H__
#include <linux/init.h>
#include <linux/device.h>
/*
* Declaration for the various functions exported by the
* mpc83xx_* files. Mostly for use by mpc83xx_setup
*/
extern int add_bridge(struct device_node *dev);
#endif /* __MPC83XX_H__ */
/*
* FSL SoC setup code
*
* Maintained by Kumar Gala (see MAINTAINERS for contact information)
*
* 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.
*/
#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <asm/system.h>
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/pci-bridge.h>
#include <asm/prom.h>
#include <sysdev/fsl_soc.h>
#undef DEBUG
#ifdef DEBUG
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
int mpc83xx_pci2_busno;
#ifdef CONFIG_PCI
int __init add_bridge(struct device_node *dev)
{
int len;
struct pci_controller *hose;
struct resource rsrc;
int *bus_range;
int primary = 1, has_address = 0;
phys_addr_t immr = get_immrbase();
DBG("Adding PCI host bridge %s\n", dev->full_name);
/* Fetch host bridge registers address */
has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
/* Get bus range if any */
bus_range = (int *) get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
printk(KERN_WARNING "Can't get bus-range for %s, assume"
" bus 0\n", dev->full_name);
}
hose = pcibios_alloc_controller();
if (!hose)
return -ENOMEM;
hose->arch_data = dev;
hose->set_cfg_type = 1;
hose->first_busno = bus_range ? bus_range[0] : 0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;
/* MPC83xx supports up to two host controllers one at 0x8500 from immrbar
* the other at 0x8600, we consider the 0x8500 the primary controller
*/
/* PCI 1 */
if ((rsrc.start & 0xfffff) == 0x8500) {
setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304);
}
/* PCI 2*/
if ((rsrc.start & 0xfffff) == 0x8600) {
setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384);
primary = 0;
hose->bus_offset = hose->first_busno;
mpc83xx_pci2_busno = hose->first_busno;
}
printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%08lx. "
"Firmware bus number: %d->%d\n",
rsrc.start, hose->first_busno, hose->last_busno);
DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
hose, hose->cfg_addr, hose->cfg_data);
/* Interpret the "ranges" property */
/* This also maps the I/O region and sets isa_io/mem_base */
pci_process_bridge_OF_ranges(hose, dev, primary);
return 0;
}
#endif
......@@ -135,12 +135,13 @@ int __init
hydra_init(void)
{
struct device_node *np;
struct resource r;
np = find_devices("mac-io");
if (np == NULL || np->n_addrs == 0)
if (np == NULL || of_address_to_resource(np, 0, &r))
return 0;
Hydra = ioremap(np->addrs[0].address, np->addrs[0].size);
printk("Hydra Mac I/O at %lx\n", np->addrs[0].address);
Hydra = ioremap(r.start, r.end-r.start);
printk("Hydra Mac I/O at %lx\n", r.start);
printk("Hydra Feature_Control was %x",
in_le32(&Hydra->Feature_Control));
out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN |
......@@ -177,18 +178,24 @@ setup_python(struct pci_controller *hose, struct device_node *dev)
{
u32 __iomem *reg;
u32 val;
unsigned long addr = dev->addrs[0].address;
struct resource r;
setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010);
if (of_address_to_resource(dev, 0, &r)) {
printk(KERN_ERR "No address for Python PCI controller\n");
return;
}
/* Clear the magic go-slow bit */
reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40);
reg = ioremap(r.start + 0xf6000, 0x40);
BUG_ON(!reg);
val = in_be32(&reg[12]);
if (val & PRG_CL_RESET_VALID) {
out_be32(&reg[12], val & ~PRG_CL_RESET_VALID);
in_be32(&reg[12]);
}
iounmap(reg);
setup_indirect_pci(hose, r.start + 0xf8000, r.start + 0xf8010);
}
/* Marvell Discovery II based Pegasos 2 */
......@@ -218,7 +225,7 @@ chrp_find_bridges(void)
char *model, *machine;
int is_longtrail = 0, is_mot = 0, is_pegasos = 0;
struct device_node *root = find_path_device("/");
struct resource r;
/*
* The PCI host bridge nodes on some machines don't have
* properties to adequately identify them, so we have to
......@@ -238,7 +245,7 @@ chrp_find_bridges(void)
continue;
++index;
/* The GG2 bridge on the LongTrail doesn't have an address */
if (dev->n_addrs < 1 && !is_longtrail) {
if (of_address_to_resource(dev, 0, &r) && !is_longtrail) {
printk(KERN_WARNING "Can't use %s: no address\n",
dev->full_name);
continue;
......@@ -255,8 +262,8 @@ chrp_find_bridges(void)
printk(KERN_INFO "PCI buses %d..%d",
bus_range[0], bus_range[1]);
printk(" controlled by %s", dev->type);
if (dev->n_addrs > 0)
printk(" at %lx", dev->addrs[0].address);
if (!is_longtrail)
printk(" at %lx", r.start);
printk("\n");
hose = pcibios_alloc_controller();
......
......@@ -352,9 +352,10 @@ static void __init chrp_find_openpic(void)
opaddr = opprop[na-1]; /* assume 32-bit */
oplen /= na * sizeof(unsigned int);
} else {
if (np->n_addrs == 0)
struct resource r;
if (of_address_to_resource(np, 0, &r))
return;
opaddr = np->addrs[0].address;
opaddr = r.start;
oplen = 0;
}
......@@ -377,7 +378,7 @@ static void __init chrp_find_openpic(void)
*/
if (oplen < len) {
printk(KERN_ERR "Insufficient addresses for distributed"
" OpenPIC (%d < %d)\n", np->n_addrs, len);
" OpenPIC (%d < %d)\n", oplen, len);
len = oplen;
}
......
......@@ -21,6 +21,7 @@
#include <linux/mc146818rtc.h>
#include <linux/init.h>
#include <linux/bcd.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/nvram.h>
......@@ -37,14 +38,16 @@ static int nvram_data = NVRAM_DATA;
long __init chrp_time_init(void)
{
struct device_node *rtcs;
struct resource r;
int base;
rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
if (rtcs == NULL)
rtcs = find_compatible_devices("rtc", "ds1385-rtc");
if (rtcs == NULL || rtcs->addrs == NULL)
if (rtcs == NULL || of_address_to_resource(rtcs, 0, &r))
return 0;
base = rtcs->addrs[0].address;
base = r.start;
nvram_as1 = 0;
nvram_as0 = base;
nvram_data = base + 1;
......
......@@ -334,14 +334,12 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus,
*/
int iSeries_get_irq(struct pt_regs *regs)
{
struct paca_struct *lpaca;
/* -2 means ignore this interrupt */
int irq = -2;
lpaca = get_paca();
#ifdef CONFIG_SMP
if (lpaca->lppaca.int_dword.fields.ipi_cnt) {
lpaca->lppaca.int_dword.fields.ipi_cnt = 0;
if (get_lppaca()->int_dword.fields.ipi_cnt) {
get_lppaca()->int_dword.fields.ipi_cnt = 0;
iSeries_smp_message_recv(regs);
}
#endif /* CONFIG_SMP */
......
......@@ -44,7 +44,8 @@ _GLOBAL(local_irq_restore)
/* Check pending interrupts */
/* A decrementer, IPI or PMC interrupt may have occurred
* while we were in the hypervisor (which enables) */
ld r4,PACALPPACA+LPPACAANYINT(r13)
ld r4,PACALPPACAPTR(r13)
ld r4,LPPACAANYINT(r4)
cmpdi r4,0
beqlr
......
......@@ -538,7 +538,7 @@ static unsigned long __init build_iSeries_Memory_Map(void)
*/
static void __init iSeries_setup_arch(void)
{
if (get_paca()->lppaca.shared_proc) {
if (get_lppaca()->shared_proc) {
ppc_md.idle_loop = iseries_shared_idle;
printk(KERN_INFO "Using shared processor idle loop\n");
} else {
......@@ -647,7 +647,7 @@ static void yield_shared_processor(void)
* The decrementer stops during the yield. Force a fake decrementer
* here and let the timer_interrupt code sort out the actual time.
*/
get_paca()->lppaca.int_dword.fields.decr_int = 1;
get_lppaca()->int_dword.fields.decr_int = 1;
process_iSeries_events();
}
......@@ -883,7 +883,7 @@ void dt_cpus(struct iseries_flat_dt *dt)
pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
for (i = 0; i < NR_CPUS; i++) {
if (paca[i].lppaca.dyn_proc_status >= 2)
if (lppaca[i].dyn_proc_status >= 2)
continue;
snprintf(p, 32 - (p - buf), "@%d", i);
......@@ -891,7 +891,7 @@ void dt_cpus(struct iseries_flat_dt *dt)
dt_prop_str(dt, "device_type", "cpu");
index = paca[i].lppaca.dyn_hv_phys_proc_index;
index = lppaca[i].dyn_hv_phys_proc_index;
d = &xIoHriProcessorVpd[index];
dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
......
......@@ -91,7 +91,7 @@ static void smp_iSeries_kick_cpu(int nr)
BUG_ON((nr < 0) || (nr >= NR_CPUS));
/* Verify that our partition has a processor nr */
if (paca[nr].lppaca.dyn_proc_status >= 2)
if (lppaca[nr].dyn_proc_status >= 2)
return;
/* The processor is currently spinning, waiting
......
......@@ -254,11 +254,11 @@ out:
void vpa_init(int cpu)
{
int hwcpu = get_hard_smp_processor_id(cpu);
unsigned long vpa = __pa(&paca[cpu].lppaca);
unsigned long vpa = __pa(&lppaca[cpu]);
long ret;
if (cpu_has_feature(CPU_FTR_ALTIVEC))
paca[cpu].lppaca.vmxregs_in_use = 1;
lppaca[cpu].vmxregs_in_use = 1;
ret = register_vpa(hwcpu, vpa);
......
......@@ -350,6 +350,100 @@ static int do_remove_node(char *buf)
return rv;
}
static char *parse_node(char *buf, size_t bufsize, struct device_node **npp)
{
char *handle_str;
phandle handle;
*npp = NULL;
handle_str = buf;
buf = strchr(buf, ' ');
if (!buf)
return NULL;
*buf = '\0';
buf++;
handle = simple_strtoul(handle_str, NULL, 10);
*npp = of_find_node_by_phandle(handle);
return buf;
}
static int do_add_property(char *buf, size_t bufsize)
{
struct property *prop = NULL;
struct device_node *np;
unsigned char *value;
char *name, *end;
int length;
end = buf + bufsize;
buf = parse_node(buf, bufsize, &np);
if (!np)
return -ENODEV;
if (parse_next_property(buf, end, &name, &length, &value) == NULL)
return -EINVAL;
prop = new_property(name, length, value, NULL);
if (!prop)
return -ENOMEM;
prom_add_property(np, prop);
return 0;
}
static int do_remove_property(char *buf, size_t bufsize)
{
struct device_node *np;
char *tmp;
struct property *prop;
buf = parse_node(buf, bufsize, &np);
if (!np)
return -ENODEV;
tmp = strchr(buf,' ');
if (tmp)
*tmp = '\0';
if (strlen(buf) == 0)
return -EINVAL;
prop = of_find_property(np, buf, NULL);
return prom_remove_property(np, prop);
}
static int do_update_property(char *buf, size_t bufsize)
{
struct device_node *np;
unsigned char *value;
char *name, *end;
int length;
struct property *newprop, *oldprop;
buf = parse_node(buf, bufsize, &np);
end = buf + bufsize;
if (!np)
return -ENODEV;
if (parse_next_property(buf, end, &name, &length, &value) == NULL)
return -EINVAL;
newprop = new_property(name, length, value, NULL);
if (!newprop)
return -ENOMEM;
oldprop = of_find_property(np, name,NULL);
if (!oldprop)
return -ENODEV;
return prom_update_property(np, newprop, oldprop);
}
/**
* ofdt_write - perform operations on the Open Firmware device tree
*
......@@ -392,6 +486,12 @@ static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t coun
rv = do_add_node(tmp, count - (tmp - kbuf));
else if (!strcmp(kbuf, "remove_node"))
rv = do_remove_node(tmp);
else if (!strcmp(kbuf, "add_property"))
rv = do_add_property(tmp, count - (tmp - kbuf));
else if (!strcmp(kbuf, "remove_property"))
rv = do_remove_property(tmp, count - (tmp - kbuf));
else if (!strcmp(kbuf, "update_property"))
rv = do_update_property(tmp, count - (tmp - kbuf));
else
rv = -EINVAL;
out:
......
This diff is collapsed.
......@@ -7,3 +7,4 @@ obj-$(CONFIG_40x) += dcr.o
obj-$(CONFIG_U3_DART) += dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
obj-$(CONFIG_PPC_83xx) += ipic.o
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
This diff is collapsed.
#ifndef __PPC_FSL_SOC_H
#define __PPC_FSL_SOC_H
#ifdef __KERNEL__
extern phys_addr_t get_immrbase(void);
#endif
#endif
This diff is collapsed.
......@@ -270,7 +270,6 @@ EXPORT_SYMBOL(__delay);
EXPORT_SYMBOL(timer_interrupt);
EXPORT_SYMBOL(irq_desc);
EXPORT_SYMBOL(tb_ticks_per_jiffy);
EXPORT_SYMBOL(get_wchan);
EXPORT_SYMBOL(console_drivers);
#ifdef CONFIG_XMON
EXPORT_SYMBOL(xmon);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment