more ppc
This commit is contained in:
parent
ebf98ebdc0
commit
2041c328cd
23 changed files with 2666 additions and 0 deletions
43
src/arch/ppc/include/bsp.h
Normal file
43
src/arch/ppc/include/bsp.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#ifndef _BSP_H
|
||||
#define _BSP_H
|
||||
|
||||
/* This function is called very early on, and may not have a functioning
|
||||
stack. It should be careful not to touch memory until it has enabled
|
||||
memory accesses. */
|
||||
void bsp_init_mp107(void);
|
||||
|
||||
/* Called early to initialize i/o for logging */
|
||||
void bsp_init_io(void);
|
||||
|
||||
/* Called to relocate data */
|
||||
void bsp_relocate(void);
|
||||
|
||||
/* Called before the relocation jump - data has been relocated. */
|
||||
unsigned bsp_init_memory(unsigned offset);
|
||||
|
||||
/* This function is called immediately after relocation. Do whatever
|
||||
is necessary to perform printf. */
|
||||
void bsp_init_post_reloc(unsigned memory);
|
||||
|
||||
/* Called after the first print to the outside world */
|
||||
void bsp_init_post_hello(void);
|
||||
|
||||
/* Called if things have failed very, very badly. */
|
||||
void bsp_indicate_dead(void);
|
||||
|
||||
/* Prints out a BSP description */
|
||||
void bsp_identify(void);
|
||||
|
||||
/* BSP primary clock */
|
||||
unsigned bsp_clock_speed(void);
|
||||
|
||||
/* Memory regions - all of memory runs from memory_base to top. */
|
||||
extern unsigned long memory_base;
|
||||
extern unsigned long memory_top;
|
||||
extern unsigned long physical_memory_size;
|
||||
|
||||
#endif
|
||||
21
src/arch/ppc/include/ppc.h
Normal file
21
src/arch/ppc/include/ppc.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#ifndef _PPC_H
|
||||
#define _PPC_H
|
||||
|
||||
#define BIG_ENDIAN
|
||||
#define RODATA __attribute__ ((__section__ (".rodata")))
|
||||
|
||||
/* Do CPU specific setup, with optional icache */
|
||||
void ppc_setup_cpu(int icache);
|
||||
|
||||
void ppc_enable_dcache(void);
|
||||
void ppc_disable_dcache(void);
|
||||
void ppc_enable_mmu(void);
|
||||
|
||||
/* Describe which sort of ppc CPU I am */
|
||||
void ppc_identify(void);
|
||||
|
||||
#endif
|
||||
293
src/arch/ppc/include/ppc_asm.tmpl
Normal file
293
src/arch/ppc/include/ppc_asm.tmpl
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
* (C) Copyright 2000
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains all the macros and symbols which define
|
||||
* a PowerPC assembly language environment.
|
||||
*/
|
||||
#ifndef __PPC_ASM_TMPL__
|
||||
#define __PPC_ASM_TMPL__
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* These definitions simplify the ugly declarations necessary for GOT
|
||||
* definitions.
|
||||
*
|
||||
* Stolen from prepboot/bootldr.h, (C) 1998 Gabriel Paubert, paubert@iram.es
|
||||
*
|
||||
* Uses r14 to access the GOT
|
||||
*/
|
||||
|
||||
#define START_GOT \
|
||||
.section ".got2","aw"; \
|
||||
.LCTOC1 = .+32768
|
||||
|
||||
#define END_GOT \
|
||||
.text
|
||||
|
||||
#define GET_GOT \
|
||||
bl 1f ; \
|
||||
.text 2 ; \
|
||||
0: .long .LCTOC1-1f ; \
|
||||
.text ; \
|
||||
1: mflr r14 ; \
|
||||
lwz r0,0b-1b(r14) ; \
|
||||
add r14,r0,r14 ;
|
||||
|
||||
#define GOT_ENTRY(NAME) .L_ ## NAME = . - .LCTOC1 ; .long NAME
|
||||
|
||||
#define GOT(NAME) .L_ ## NAME (r14)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Register names
|
||||
*/
|
||||
#define r0 0
|
||||
#define r1 1
|
||||
#define r2 2
|
||||
#define r3 3
|
||||
#define r4 4
|
||||
#define r5 5
|
||||
#define r6 6
|
||||
#define r7 7
|
||||
#define r8 8
|
||||
#define r9 9
|
||||
#define r10 10
|
||||
#define r11 11
|
||||
#define r12 12
|
||||
#define r13 13
|
||||
#define r14 14
|
||||
#define r15 15
|
||||
#define r16 16
|
||||
#define r17 17
|
||||
#define r18 18
|
||||
#define r19 19
|
||||
#define r20 20
|
||||
#define r21 21
|
||||
#define r22 22
|
||||
#define r23 23
|
||||
#define r24 24
|
||||
#define r25 25
|
||||
#define r26 26
|
||||
#define r27 27
|
||||
#define r28 28
|
||||
#define r29 29
|
||||
#define r30 30
|
||||
#define r31 31
|
||||
|
||||
/*
|
||||
* FP register names
|
||||
*/
|
||||
#define fr0 0
|
||||
#define fr1 1
|
||||
#define fr2 2
|
||||
#define fr3 3
|
||||
#define fr4 4
|
||||
#define fr5 5
|
||||
#define fr6 6
|
||||
#define fr7 7
|
||||
#define fr8 8
|
||||
#define fr9 9
|
||||
#define fr10 10
|
||||
#define fr11 11
|
||||
#define fr12 12
|
||||
#define fr13 13
|
||||
#define fr14 14
|
||||
#define fr15 15
|
||||
#define fr16 16
|
||||
#define fr17 17
|
||||
#define fr18 18
|
||||
#define fr19 19
|
||||
#define fr20 20
|
||||
#define fr21 21
|
||||
#define fr22 22
|
||||
#define fr23 23
|
||||
#define fr24 24
|
||||
#define fr25 25
|
||||
#define fr26 26
|
||||
#define fr27 27
|
||||
#define fr28 28
|
||||
#define fr29 29
|
||||
#define fr30 30
|
||||
#define fr31 31
|
||||
|
||||
/* Some special registers */
|
||||
|
||||
#define TBRU 269 /* Time base Upper/Lower (Reading) */
|
||||
#define TBRL 268
|
||||
#define TBWU 284 /* Time base Upper/Lower (Writing) */
|
||||
#define TBWL 285
|
||||
#define XER 1
|
||||
#define LR 8
|
||||
#define CTR 9
|
||||
#define HID0 1008 /* Hardware Implementation */
|
||||
#define PVR 287 /* Processor Version */
|
||||
#define SDR1 25 /* MMU hash base register */
|
||||
#define DAR 19 /* Data Address Register */
|
||||
#define SPR0 272 /* Supervisor Private Registers */
|
||||
#define SPRG0 272
|
||||
#define SPR1 273
|
||||
#define SPRG1 273
|
||||
#define SPR2 274
|
||||
#define SPRG2 274
|
||||
#define SPR3 275
|
||||
#define SPRG3 275
|
||||
#define DSISR 18
|
||||
#define SRR0 26 /* Saved Registers (exception) */
|
||||
#define SRR1 27
|
||||
#define DEC 22 /* Decrementer */
|
||||
#define EAR 282 /* External Address Register */
|
||||
#define ICR 148 /* Interrupt Cause Register (37-44) */
|
||||
#define DER 149
|
||||
#define COUNTA 150 /* Breakpoint Counter (37-44) */
|
||||
#define COUNTB 151 /* Breakpoint Counter (37-44) */
|
||||
#define LCTRL1 156 /* Load/Store Support (37-40) */
|
||||
#define LCTRL2 157 /* Load/Store Support (37-41) */
|
||||
#define ICTRL 158
|
||||
|
||||
/* Registers in the processor's internal memory map that we use.
|
||||
*/
|
||||
#define IMMR 0xff000000
|
||||
|
||||
#define SYPCR 0x00000004
|
||||
#define BR0 0x00000100
|
||||
#define OR0 0x00000104
|
||||
#define BR1 0x00000108
|
||||
#define OR1 0x0000010c
|
||||
#define BR2 0x00000110
|
||||
#define OR2 0x00000114
|
||||
#define BR3 0x00000118
|
||||
#define OR3 0x0000011c
|
||||
#define BR4 0x00000120
|
||||
#define OR4 0x00000124
|
||||
|
||||
#define MAR 0x00000164
|
||||
#define MCR 0x00000168
|
||||
#define MAMR 0x00000170
|
||||
#define MBMR 0x00000174
|
||||
#define MSTAT 0x00000178
|
||||
#define MPTPR 0x0000017a
|
||||
#define MDR 0x0000017c
|
||||
|
||||
#define TBSCR 0x00000200
|
||||
#define TBREFF0 0x00000204
|
||||
|
||||
#define PLPRCR 0x00000284
|
||||
|
||||
#define curptr r2
|
||||
|
||||
#define SYNC \
|
||||
sync; \
|
||||
isync
|
||||
|
||||
/*
|
||||
* Macros for storing registers into and loading registers from
|
||||
* exception frames.
|
||||
*/
|
||||
#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base)
|
||||
#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
|
||||
#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
|
||||
#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
|
||||
#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
|
||||
#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base)
|
||||
#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
|
||||
#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
|
||||
#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
|
||||
#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
|
||||
|
||||
/*
|
||||
* GCC sometimes accesses words at negative offsets from the stack
|
||||
* pointer, although the SysV ABI says it shouldn't. To cope with
|
||||
* this, we leave this much untouched space on the stack on exception
|
||||
* entry.
|
||||
*/
|
||||
#define STACK_UNDERHEAD 64
|
||||
|
||||
#if 0 /* we don't use virtual addresses in PPCBOOT */
|
||||
#define tophys(rd,rs,rt) addis rd,rs,-KERNELBASE@h
|
||||
#define tovirt(rd,rs,rt) addis rd,rs,KERNELBASE@h
|
||||
#else
|
||||
#define tophys(rd,rs,rt) mr rd,rs
|
||||
#define tovirt(rd,rs,rt) mr rd,rs
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exception entry code. This code runs with address translation
|
||||
* turned off, i.e. using physical addresses.
|
||||
* We assume sprg3 has the physical address of the current
|
||||
* task's thread_struct.
|
||||
*/
|
||||
#define EXCEPTION_PROLOG \
|
||||
mtspr SPRG0,r20; \
|
||||
mtspr SPRG1,r21; \
|
||||
mfcr r20; \
|
||||
tophys(r21,r1,r21); /* use tophys(kernel sp) otherwise */ \
|
||||
subi r21,r21,INT_FRAME_SIZE+STACK_UNDERHEAD; /* alloc exc. frame */\
|
||||
1: stw r20,_CCR(r21); /* save registers */ \
|
||||
stw r22,GPR22(r21); \
|
||||
stw r23,GPR23(r21); \
|
||||
mfspr r20,SPRG0; \
|
||||
stw r20,GPR20(r21); \
|
||||
mfspr r22,SPRG1; \
|
||||
stw r22,GPR21(r21); \
|
||||
mflr r20; \
|
||||
stw r20,_LINK(r21); \
|
||||
mfctr r22; \
|
||||
stw r22,_CTR(r21); \
|
||||
mfspr r20,XER; \
|
||||
stw r20,_XER(r21); \
|
||||
mfspr r22,SRR0; \
|
||||
mfspr r23,SRR1; \
|
||||
stw r0,GPR0(r21); \
|
||||
stw r1,GPR1(r21); \
|
||||
stw r2,GPR2(r21); \
|
||||
stw r1,0(r21); \
|
||||
tovirt(r1,r21,r1); /* set new kernel sp */ \
|
||||
SAVE_4GPRS(3, r21);
|
||||
/*
|
||||
* Note: code which follows this uses cr0.eq (set if from kernel),
|
||||
* r21, r22 (SRR0), and r23 (SRR1).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Exception vectors.
|
||||
*
|
||||
* The data words for `hdlr' and `int_return' are initialized with
|
||||
* OFFSET values only; they must be relocated first before they can
|
||||
* be used!
|
||||
*/
|
||||
#define STD_EXCEPTION(n, label, hdlr) \
|
||||
. = n; \
|
||||
label: \
|
||||
EXCEPTION_PROLOG; \
|
||||
lwz r3,GOT(transfer_to_handler); \
|
||||
mtlr r3; \
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD; \
|
||||
li r20,MSR_KERNEL; \
|
||||
blrl ; \
|
||||
.L_ ## label : \
|
||||
.long hdlr - _start + EXC_OFF_SYS_RESET; \
|
||||
.long int_return - _start + EXC_OFF_SYS_RESET
|
||||
|
||||
|
||||
#endif /* __PPC_ASM_TMPL__ */
|
||||
128
src/arch/ppc/include/ppcreg.h
Normal file
128
src/arch/ppc/include/ppcreg.h
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
/* In the MSR, not all bits are interesting to us
|
||||
13 - POW - Power management
|
||||
14 - TGPR - temporary registers for page table routines
|
||||
15 - ILE - Exception little endian
|
||||
16 - EE - External interrupts
|
||||
17 - PR - Privilege level
|
||||
18 - FP - Floating Point available
|
||||
19 - ME - Machine check exception enable
|
||||
20 - FE0 - Floating exception mode 0
|
||||
21 - SE - Single step trace mode
|
||||
22 - BE - Branch trace enable
|
||||
23 - FE1 - Floating exception mode 1
|
||||
25 - IP - Exception prefix
|
||||
26 - IR - Instruction address translation
|
||||
27 - DR - Data address translation
|
||||
30 - RI - Recoverable exception
|
||||
31 - LE - Little endian mode
|
||||
MSR_MASK is the bits we do not change.
|
||||
*/
|
||||
|
||||
#define MSR_MASK 0xfff8008c
|
||||
#define MSR_POW 0x00040000
|
||||
#define MSR_TGPR 0x00020000
|
||||
#define MSR_ILE 0x00010000
|
||||
#define MSR_EE 0x00008000
|
||||
#define MSR_PR 0x00004000
|
||||
#define MSR_FP 0x00002000
|
||||
#define MSR_ME 0x00001000
|
||||
#define MSR_FE0 0x00000800
|
||||
#define MSR_SE 0x00000400
|
||||
#define MSR_BE 0x00000200
|
||||
#define MSR_FE1 0x00000100
|
||||
#define MSR_IP 0x00000040
|
||||
#define MSR_IR 0x00000020
|
||||
#define MSR_DR 0x00000010
|
||||
#define MSR_RI 0x00000002
|
||||
#define MSR_LE 0x00000001
|
||||
|
||||
#define MSR_DEFAULT (MSR_FP | MSR_IR | MSR_DR)
|
||||
|
||||
/* We are interested in the following hid0 bits:
|
||||
6 - ECLK - Enable external test clock (603 only)
|
||||
11 - DPM - Turn on dynamic power management (603 only)
|
||||
15 - NHR - Not hard reset
|
||||
16 - ICE - Instruction cache enable
|
||||
17 - DCE - Data cache enable
|
||||
18 - ILOCK - Instruction cache lock
|
||||
19 - DLOCK - Data cache lock
|
||||
20 - ICFI - Instruction cache invalidate
|
||||
21 - DCFI - Data cache invalidate
|
||||
24 - NOSER - Serial execution disable (604 only - turbo mode)
|
||||
24 - SGE - Store gathering enable (7410 only)
|
||||
29 - BHT - Branch history table (604 only)
|
||||
|
||||
I made up the tags for the 604 specific bits, as they aren't
|
||||
named in the 604 book. The 603 book calls the invalidate bits
|
||||
ICFI and DCI, and I have no idea why it isn't DCFI. Maybe IBM named
|
||||
one, and Motorola named the other. */
|
||||
|
||||
#define HID0_ECLK 0x02000000
|
||||
#define HID0_DPM 0x00100000
|
||||
#define HID0_NHR 0x00010000
|
||||
#define HID0_ICE 0x00008000
|
||||
#define HID0_DCE 0x00004000
|
||||
#define HID0_ILOCK 0x00002000
|
||||
#define HID0_DLOCK 0x00001000
|
||||
#define HID0_ICFI 0x00000800
|
||||
#define HID0_DCFI 0x00000400
|
||||
#define HID0_NOSER 0x00000080
|
||||
#define HID0_SGE 0x00000080
|
||||
#define HID0_BTIC 0x00000020
|
||||
#define HID0_BHT 0x00000004
|
||||
|
||||
/*
|
||||
* BAT defines
|
||||
*/
|
||||
|
||||
/*
|
||||
* BL field in upper BAT register
|
||||
*/
|
||||
#define BAT_BL_128K 0x00000000
|
||||
#define BAT_BL_256K 0x00000004
|
||||
#define BAT_BL_512K 0x0000000C
|
||||
#define BAT_BL_1M 0x0000001C
|
||||
#define BAT_BL_2M 0x0000003C
|
||||
#define BAT_BL_4M 0x0000007C
|
||||
#define BAT_BL_8M 0x000000FC
|
||||
#define BAT_BL_16M 0x000001FC
|
||||
#define BAT_BL_32M 0x000003FC
|
||||
#define BAT_BL_64M 0x000007FC
|
||||
#define BAT_BL_128M 0x00000FFC
|
||||
#define BAT_BL_256M 0x00001FFC
|
||||
|
||||
/*
|
||||
* Supervisor/user valid mode in upper BAT register
|
||||
*/
|
||||
#define BAT_VALID_SUPERVISOR 0x00000002
|
||||
#define BAT_VALID_USER 0x00000001
|
||||
#define BAT_INVALID 0x00000000
|
||||
|
||||
/*
|
||||
* WIMG bit setting in lower BAT register
|
||||
*/
|
||||
#define BAT_WRITE_THROUGH 0x00000040
|
||||
#define BAT_CACHE_INHIBITED 0x00000020
|
||||
#define BAT_COHERENT 0x00000010
|
||||
#define BAT_GUARDED 0x00000008
|
||||
|
||||
/*
|
||||
* Protection bits in lower BAT register
|
||||
*/
|
||||
#define BAT_NO_ACCESS 0x00000000
|
||||
#define BAT_READ_ONLY 0x00000001
|
||||
#define BAT_READ_WRITE 0x00000002
|
||||
|
||||
#ifndef ASM
|
||||
unsigned __getmsr(void);
|
||||
void __setmsr(unsigned value);
|
||||
unsigned __gethid0(void);
|
||||
unsigned __gethid1(void);
|
||||
void __sethid0(unsigned value);
|
||||
unsigned __getpvr(void);
|
||||
#endif
|
||||
|
||||
12
src/arch/ppc/include/timer.h
Normal file
12
src/arch/ppc/include/timer.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#ifndef _TIMER_H
|
||||
#define __TIMER_H
|
||||
|
||||
unsigned get_hz(void);
|
||||
unsigned ticks_since_boot(void);
|
||||
void sleep_ticks(unsigned);
|
||||
|
||||
#endif
|
||||
109
src/arch/ppc/lib/c_start.S
Normal file
109
src/arch/ppc/lib/c_start.S
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
/*
|
||||
* The assumption is that we're located in ROM and we have a fake stack
|
||||
* located in cache. Our task is to turn on memory proper, the finish
|
||||
* configuring the machine.
|
||||
*/
|
||||
|
||||
#define ASM
|
||||
#include "ppcreg.h"
|
||||
#include <ppc_asm.tmpl>
|
||||
|
||||
.section ".text"
|
||||
.globl _start
|
||||
|
||||
_start:
|
||||
/*
|
||||
* init stack pointer to real ram now that memory is on
|
||||
*/
|
||||
lis r1, _estack@ha
|
||||
addi r1, r1, _estack@l
|
||||
stwu r0,-64(r1)
|
||||
stwu r1,-24(r1)
|
||||
|
||||
/*
|
||||
* Clear stack
|
||||
*/
|
||||
lis r4, _stack@ha
|
||||
addi r4, r4, _stack@l
|
||||
lis r7, _estack@ha
|
||||
addi r7, r7, _estack@l
|
||||
lis r5, 0
|
||||
1: stwx r5, 0, r4
|
||||
addi r4, r4, 4
|
||||
cmp 0, 0, r4, r7
|
||||
ble 1b
|
||||
sync
|
||||
|
||||
/*
|
||||
* Clear bss
|
||||
*/
|
||||
lis r4, _bss@ha
|
||||
addi r4, r4, _bss@l
|
||||
lis r7, _ebss@ha
|
||||
addi r7, r7, _ebss@l
|
||||
lis r5, 0
|
||||
1: stwx r5, 0, r4
|
||||
addi r4, r4, 4
|
||||
cmp 0, 0, r4, r7
|
||||
ble 1b
|
||||
sync
|
||||
|
||||
/*
|
||||
* Set up the EABI pointers, before we enter any C code
|
||||
*/
|
||||
lis r13, _SDA_BASE_@ha
|
||||
addi r13, r13, _SDA_BASE_@l
|
||||
lis r2, _SDA2_BASE_@ha
|
||||
addi r2, r2, _SDA2_BASE_@l
|
||||
|
||||
/*
|
||||
* load start address into SRR0 for rfi
|
||||
*/
|
||||
lis r3, hardwaremain@ha
|
||||
addi r3, r3, hardwaremain@l
|
||||
mtspr SRR0, r3
|
||||
|
||||
/*
|
||||
* load the current MSR into SRR1 so that it will be copied
|
||||
* back into MSR on rfi
|
||||
*/
|
||||
mfmsr r4
|
||||
mtspr SRR1, r4 // load SRR1 with r4
|
||||
|
||||
/*
|
||||
* If something returns after rfi then die
|
||||
*/
|
||||
lis r3, dead@ha
|
||||
addi r3, r3, dead@l
|
||||
mtlr r3
|
||||
|
||||
/*
|
||||
* Complete rest of initialization in C (hardwaremain)
|
||||
*/
|
||||
rfi
|
||||
|
||||
/*
|
||||
* Stop here if something goes wrong
|
||||
*/
|
||||
dead:
|
||||
b dead
|
||||
/*NOTREACHED*/
|
||||
|
||||
/* Remove need for ecrti.o and ectrn.o */
|
||||
.globl __init
|
||||
__init:
|
||||
.globl __fini
|
||||
__fini:
|
||||
.globl __CTOR_LIST__
|
||||
__CTOR_LIST__:
|
||||
.globl __CTOR_END__
|
||||
__CTOR_END__:
|
||||
.globl __DTOR_LIST__
|
||||
__DTOR_LIST__:
|
||||
.globl __DTOR_END__
|
||||
__DTOR_END__:
|
||||
blr
|
||||
45
src/arch/ppc/lib/floats.S
Normal file
45
src/arch/ppc/lib/floats.S
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 1999-2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
|
||||
.globl _init_float_registers
|
||||
|
||||
_init_float_registers:
|
||||
lfd fr0, 0(r3)
|
||||
lfd fr1, 0(r3)
|
||||
lfd fr2, 0(r3)
|
||||
lfd fr3, 0(r3)
|
||||
lfd fr4, 0(r3)
|
||||
lfd fr5, 0(r3)
|
||||
lfd fr6, 0(r3)
|
||||
lfd fr7, 0(r3)
|
||||
lfd fr8, 0(r3)
|
||||
lfd fr9, 0(r3)
|
||||
lfd fr10, 0(r3)
|
||||
lfd fr11, 0(r3)
|
||||
lfd fr12, 0(r3)
|
||||
lfd fr13, 0(r3)
|
||||
lfd fr14, 0(r3)
|
||||
lfd fr15, 0(r3)
|
||||
lfd fr16, 0(r3)
|
||||
lfd fr17, 0(r3)
|
||||
lfd fr18, 0(r3)
|
||||
lfd fr19, 0(r3)
|
||||
lfd fr20, 0(r3)
|
||||
lfd fr21, 0(r3)
|
||||
lfd fr22, 0(r3)
|
||||
lfd fr23, 0(r3)
|
||||
lfd fr24, 0(r3)
|
||||
lfd fr25, 0(r3)
|
||||
lfd fr26, 0(r3)
|
||||
lfd fr27, 0(r3)
|
||||
lfd fr28, 0(r3)
|
||||
lfd fr29, 0(r3)
|
||||
lfd fr30, 0(r3)
|
||||
lfd fr31, 0(r3)
|
||||
blr
|
||||
|
||||
.end
|
||||
|
||||
43
src/arch/ppc/lib/floats.inc
Normal file
43
src/arch/ppc/lib/floats.inc
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 1999-2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
/* .text*/
|
||||
.globl _init_float_registers
|
||||
|
||||
_init_float_registers:
|
||||
lfd 0, 0(3)
|
||||
lfd 1, 0(3)
|
||||
lfd 2, 0(3)
|
||||
lfd 3, 0(3)
|
||||
lfd 4, 0(3)
|
||||
lfd 5, 0(3)
|
||||
lfd 6, 0(3)
|
||||
lfd 7, 0(3)
|
||||
lfd 8, 0(3)
|
||||
lfd 9, 0(3)
|
||||
lfd 10, 0(3)
|
||||
lfd 11, 0(3)
|
||||
lfd 12, 0(3)
|
||||
lfd 13, 0(3)
|
||||
lfd 14, 0(3)
|
||||
lfd 15, 0(3)
|
||||
lfd 16, 0(3)
|
||||
lfd 17, 0(3)
|
||||
lfd 18, 0(3)
|
||||
lfd 19, 0(3)
|
||||
lfd 20, 0(3)
|
||||
lfd 21, 0(3)
|
||||
lfd 22, 0(3)
|
||||
lfd 23, 0(3)
|
||||
lfd 24, 0(3)
|
||||
lfd 25, 0(3)
|
||||
lfd 26, 0(3)
|
||||
lfd 27, 0(3)
|
||||
lfd 28, 0(3)
|
||||
lfd 29, 0(3)
|
||||
lfd 30, 0(3)
|
||||
lfd 31, 0(3)
|
||||
blr
|
||||
.end
|
||||
|
||||
58
src/arch/ppc/lib/id.c
Normal file
58
src/arch/ppc/lib/id.c
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#include "ppc.h"
|
||||
#include "ppcreg.h"
|
||||
#include <printk.h>
|
||||
|
||||
void ppc_identify(void)
|
||||
{
|
||||
unsigned type = __getpvr() >> 16;
|
||||
unsigned version = __getpvr() & 0xffff;
|
||||
const char *cpu_string = 0;
|
||||
switch(type) {
|
||||
case 1:
|
||||
cpu_string = "601";
|
||||
break;
|
||||
case 3:
|
||||
cpu_string = "603";
|
||||
break;
|
||||
case 4:
|
||||
cpu_string = "604";
|
||||
break;
|
||||
case 6:
|
||||
cpu_string = "603e";
|
||||
break;
|
||||
case 7:
|
||||
cpu_string = "603ev";
|
||||
break;
|
||||
case 8:
|
||||
cpu_string = "750";
|
||||
break;
|
||||
case 9:
|
||||
cpu_string = "604e";
|
||||
break;
|
||||
case 10:
|
||||
cpu_string = "604ev5 (MachV)";
|
||||
break;
|
||||
case 12:
|
||||
cpu_string = "7400";
|
||||
break;
|
||||
case 50:
|
||||
cpu_string = "821";
|
||||
break;
|
||||
case 80:
|
||||
cpu_string = "860";
|
||||
break;
|
||||
case 0x800c:
|
||||
cpu_string = "7410";
|
||||
break;
|
||||
}
|
||||
if (cpu_string)
|
||||
printk_info("PowerPC %s", cpu_string);
|
||||
else
|
||||
printk_info("PowerPC unknown (0x%x)", type);
|
||||
printk_info(" CPU, version %d.%d\n", version >> 8, version & 0xff);
|
||||
}
|
||||
|
||||
130
src/arch/ppc/lib/setup.c
Normal file
130
src/arch/ppc/lib/setup.c
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#include "ppc.h"
|
||||
#include "ppcreg.h"
|
||||
|
||||
unsigned __getmsr(void)
|
||||
{
|
||||
unsigned result;
|
||||
__asm__ volatile ("mfmsr %0" : "=r" (result));
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned __gethid0(void)
|
||||
{
|
||||
unsigned result;
|
||||
__asm__ volatile ("mfspr %0,1008" : "=r" (result));
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned __gethid1(void)
|
||||
{
|
||||
unsigned result;
|
||||
__asm__ volatile ("mfspr %0,1009" : "=r" (result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void __sethid0(unsigned value)
|
||||
{
|
||||
__asm__ volatile ("mtspr 1008,%0" : : "r" (value));
|
||||
}
|
||||
|
||||
unsigned __getpvr(void)
|
||||
{
|
||||
int result;
|
||||
__asm__("mfspr %0, 287" : "=r" (result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void __setmsr(unsigned value)
|
||||
{
|
||||
__asm__ volatile ("mtmsr %0; sync" :: "r" (value));
|
||||
}
|
||||
|
||||
void __set1015(unsigned value)
|
||||
{
|
||||
__asm__ volatile ("mtspr 1015,%0" : : "r" (value));
|
||||
}
|
||||
|
||||
extern void _init_float_registers(const double *);
|
||||
/*RODATA static const double dummy_float = 1.0;*/
|
||||
static const double dummy_float = 1.0;
|
||||
|
||||
#define HID0_DCACHE HID0_DCE
|
||||
#define MSR_DATA MSR_DR
|
||||
|
||||
void ppc_setup_cpu(int icache)
|
||||
{
|
||||
int type = __getpvr() >> 16;
|
||||
int version = __getpvr() & 0xffff;
|
||||
|
||||
if (type == 0xc)
|
||||
{
|
||||
if (version == 0x0200)
|
||||
__set1015(0x19000004);
|
||||
else if (((version & 0xff00) == 0x0200) &&
|
||||
(version != 0x0209))
|
||||
__set1015(0x01000000);
|
||||
}
|
||||
if (icache)
|
||||
{
|
||||
__sethid0(HID0_NHR | HID0_BHT | HID0_ICE | HID0_ICFI | HID0_BTIC
|
||||
| HID0_DCACHE);
|
||||
__sethid0(HID0_DPM | HID0_NHR | HID0_BHT | HID0_ICE | HID0_BTIC
|
||||
| HID0_DCACHE);
|
||||
}
|
||||
else
|
||||
{
|
||||
__sethid0(HID0_DPM | HID0_NHR | HID0_BHT | HID0_BTIC | HID0_DCACHE);
|
||||
}
|
||||
#if 1
|
||||
/* if (type == 8 || type == 12) */
|
||||
{
|
||||
__setmsr(MSR_FP | MSR_DATA);
|
||||
_init_float_registers(&dummy_float);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ppc_enable_dcache(void)
|
||||
{
|
||||
/*
|
||||
* Already enabled in crt0.S
|
||||
*/
|
||||
#if 0
|
||||
unsigned hid0 = __gethid0();
|
||||
__sethid0(hid0 | HID0_DCFI | HID0_DCE);
|
||||
__sethid0(hid0 | HID0_DCE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ppc_disable_dcache(void)
|
||||
{
|
||||
unsigned hid0 = __gethid0();
|
||||
__sethid0(hid0 & ~HID0_DCE);
|
||||
}
|
||||
|
||||
void ppc_enable_mmu(void)
|
||||
{
|
||||
unsigned msr = __getmsr();
|
||||
__setmsr(msr | MSR_DR | MSR_IR);
|
||||
}
|
||||
|
||||
void make_coherent(void *base, unsigned length)
|
||||
{
|
||||
unsigned hid0 = __gethid0();
|
||||
|
||||
if (hid0 & HID0_DCE)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned offset = 0x1f & (unsigned) base;
|
||||
unsigned adjusted_base = (unsigned) base & ~0x1f;
|
||||
for(i = 0; i < length + offset; i+= 32)
|
||||
__asm__ volatile ("dcbf %1,%0" : : "r" (adjusted_base), "r" (i));
|
||||
if (hid0 & HID0_ICE)
|
||||
for(i = 0; i < length + offset; i+= 32)
|
||||
__asm__ volatile ("icbi %1,%0" : : "r" (adjusted_base), "r" (i));
|
||||
}
|
||||
}
|
||||
13
src/arch/ppc/lib/timebase.S
Normal file
13
src/arch/ppc/lib/timebase.S
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 1999-2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
.text
|
||||
.globl _timebase
|
||||
_timebase:
|
||||
mftbu 3
|
||||
mftb 4
|
||||
mftbu 5
|
||||
cmpw 3, 5
|
||||
bne _timebase
|
||||
blr
|
||||
31
src/arch/ppc/lib/timer.c
Normal file
31
src/arch/ppc/lib/timer.c
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#include <timer.h>
|
||||
#include <bsp.h>
|
||||
|
||||
unsigned get_hz(void)
|
||||
{
|
||||
return bsp_clock_speed() >> 16;
|
||||
}
|
||||
|
||||
unsigned ticks_since_boot(void)
|
||||
{
|
||||
extern unsigned long long _timebase(void);
|
||||
return (unsigned) (_timebase() >> 16);
|
||||
}
|
||||
|
||||
void sleep_ticks(unsigned ticks)
|
||||
{
|
||||
unsigned then = ticks + ticks_since_boot();
|
||||
while(ticks_since_boot() < then)
|
||||
;
|
||||
}
|
||||
|
||||
void udelay(int usecs)
|
||||
{
|
||||
unsigned ticksperusec = get_hz() / 1000000;
|
||||
|
||||
sleep_ticks(ticksperusec * usecs);
|
||||
}
|
||||
14
src/northbridge/motorola/mpc107/Config
Normal file
14
src/northbridge/motorola/mpc107/Config
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# Objects linked with linuxbios
|
||||
#
|
||||
object i2c.o
|
||||
object mpc107_pci.o
|
||||
object meminfo.o
|
||||
object mpc107.o
|
||||
object mpc107_utils.S
|
||||
|
||||
#
|
||||
# Included in crt0.S
|
||||
#
|
||||
mainboardinit northbridge/motorola/mpc107/mpc107_init.inc
|
||||
mainboardinit northbridge/motorola/mpc107/mpc107_utils.inc
|
||||
99
src/northbridge/motorola/mpc107/i2c.c
Normal file
99
src/northbridge/motorola/mpc107/i2c.c
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/* $Id$
|
||||
* (C) Copyright 2002
|
||||
* Humboldt Solutions Ltd, <adrian@humboldt.co.uk>
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "i2c.h"
|
||||
|
||||
static i2c_bus *first_i2c = NULL;
|
||||
|
||||
#if 0
|
||||
int register_i2c_bus(const i2c_fn *fn, char *tag, void *data)
|
||||
{
|
||||
i2c_bus *bus = malloc (sizeof (i2c_bus));
|
||||
|
||||
if (bus)
|
||||
{
|
||||
bus->fn = fn;
|
||||
bus->tag = tag;
|
||||
bus->data = data;
|
||||
bus->next = first_i2c;
|
||||
first_i2c = bus;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
i2c_bus *find_i2c_bus(const char *name)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (! name)
|
||||
return first_i2c;
|
||||
|
||||
if (first_i2c)
|
||||
{
|
||||
i2c_bus *i2c;
|
||||
|
||||
len = strlen(name);
|
||||
|
||||
for (i2c = first_i2c; i2c; i2c = i2c->next)
|
||||
if (strlen(i2c->tag) == len && memcmp (name, i2c->tag, len) == 0)
|
||||
return i2c;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void i2c_start(struct i2c_bus *bus)
|
||||
{
|
||||
if (! bus)
|
||||
bus = first_i2c;
|
||||
|
||||
bus->fn->start(bus);
|
||||
}
|
||||
|
||||
void i2c_stop(struct i2c_bus *bus)
|
||||
{
|
||||
if (! bus)
|
||||
bus = first_i2c;
|
||||
|
||||
bus->fn->stop(bus);
|
||||
}
|
||||
|
||||
int i2c_master_write(struct i2c_bus *bus, int target, int address,
|
||||
const u8 *data, int length)
|
||||
{
|
||||
if (! bus)
|
||||
bus = first_i2c;
|
||||
|
||||
return bus->fn->master_write(bus, target, address, data, length);
|
||||
}
|
||||
|
||||
int i2c_master_read(struct i2c_bus *bus, int target, int address,
|
||||
u8 *data, int length)
|
||||
{
|
||||
if (! bus)
|
||||
bus = first_i2c;
|
||||
|
||||
return bus->fn->master_read(bus, target, address, data, length);
|
||||
}
|
||||
|
||||
57
src/northbridge/motorola/mpc107/i2c.h
Normal file
57
src/northbridge/motorola/mpc107/i2c.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/* $Id$
|
||||
* (C) Copyright 2002
|
||||
* Humboldt Solutions Ltd, <adrian@humboldt.co.uk>
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _I2C_H
|
||||
#define _I2C_H
|
||||
|
||||
struct i2c_bus;
|
||||
|
||||
typedef struct i2c_fn
|
||||
{
|
||||
void (* start)(struct i2c_bus *bus);
|
||||
void (* stop)(struct i2c_bus *bus);
|
||||
int (* master_write)(struct i2c_bus *bus, int target, int address,
|
||||
const u8 *data, int length);
|
||||
int (* master_read)(struct i2c_bus *bus, int target, int address,
|
||||
u8 *data, int length);
|
||||
} i2c_fn;
|
||||
|
||||
typedef struct i2c_bus
|
||||
{
|
||||
const i2c_fn *fn;
|
||||
char *tag;
|
||||
void *data;
|
||||
struct i2c_bus *next;
|
||||
} i2c_bus;
|
||||
|
||||
i2c_bus *find_i2c_bus(const char *name);
|
||||
int register_i2c_bus(const i2c_fn *fn, char *tag, void *data);
|
||||
|
||||
void i2c_start(struct i2c_bus *bus);
|
||||
void i2c_stop(struct i2c_bus *bus);
|
||||
int i2c_master_write(struct i2c_bus *bus, int target, int address,
|
||||
const u8 *data, int length);
|
||||
int i2c_master_read(struct i2c_bus *bus, int target, int address,
|
||||
u8 *data, int length);
|
||||
void init_i2c_nvram(const char *i2c_tag);
|
||||
|
||||
extern i2c_fn mpc107_i2c_fn;
|
||||
|
||||
#endif
|
||||
202
src/northbridge/motorola/mpc107/meminfo.c
Normal file
202
src/northbridge/motorola/mpc107/meminfo.c
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* Humboldt Solutions Ltd, adrian@humboldt.co.uk.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <printk.h>
|
||||
#include "mpc107.h"
|
||||
|
||||
void
|
||||
sdram_dimm_to_bank_info(const char *data, sdram_dimm_info *dimm, int verbose)
|
||||
{
|
||||
sdram_bank_info *bank1 = dimm->bank1;
|
||||
sdram_bank_info *bank2 = dimm->bank2;
|
||||
unsigned char csum = 0;
|
||||
unsigned char x;
|
||||
int i;
|
||||
int no_cas_latencies = 0;
|
||||
char latency[3];
|
||||
|
||||
/* Mark banks initially broken */
|
||||
bank1->size = 0;
|
||||
bank2->size = 0;
|
||||
|
||||
if (data[0] < 64)
|
||||
{
|
||||
if (verbose)
|
||||
printk_info("SPD data too short\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0; i < 63; i++)
|
||||
csum += data[i];
|
||||
|
||||
if (csum != data[63])
|
||||
{
|
||||
if (verbose)
|
||||
printk_info("Broken checksum\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (data[2] != 0x04)
|
||||
{
|
||||
if (verbose)
|
||||
printk_info("SDRAM Only\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bank1->row_bits = data[3] & 0x0f;
|
||||
if (data[3] >> 4)
|
||||
bank2->row_bits = data[3] >> 4;
|
||||
else
|
||||
bank2->row_bits = bank1->row_bits;
|
||||
|
||||
bank1->internal_banks = bank2->internal_banks = data[17];
|
||||
|
||||
bank1->col_bits = data[4] & 0x0f;
|
||||
if (data[4] >> 4)
|
||||
bank2->col_bits = data[4] >> 4;
|
||||
else
|
||||
bank2->col_bits = bank1->col_bits;
|
||||
|
||||
if (data[7] || (data[6] != 80 && data[6] != 72 && data[6] != 64))
|
||||
{
|
||||
if (verbose)
|
||||
printk_info("Data width incorrect\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (data[8] != 0x01)
|
||||
{
|
||||
if (verbose)
|
||||
printk_info("3.3V TTL DIMMS only\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Extract CAS latencies in reverse order, as we only get info on
|
||||
the highest ones. */
|
||||
x = data[18];
|
||||
for(i = 7; i > 0; i--)
|
||||
{
|
||||
if (x & 0x40)
|
||||
{
|
||||
if (no_cas_latencies < 3)
|
||||
latency[no_cas_latencies] = i;
|
||||
no_cas_latencies++;
|
||||
}
|
||||
x <<= 1;
|
||||
}
|
||||
|
||||
/* Now fill in other timings - we're most interested in the lowest
|
||||
CAS latency, so we shuffle data to put that first. */
|
||||
for(i = no_cas_latencies; i >= 0; i--)
|
||||
bank1->cas_latency[no_cas_latencies - i - 1] =
|
||||
bank2->cas_latency[no_cas_latencies - i - 1] =
|
||||
latency[i];
|
||||
for(i = no_cas_latencies; i < 3; i++)
|
||||
bank1->cas_latency[i] = bank2->cas_latency[i] = 0;
|
||||
|
||||
/* Store values for the highest cas latency */
|
||||
bank1->cycle_time[no_cas_latencies - 1] =
|
||||
bank2->cycle_time[no_cas_latencies- 1] =
|
||||
100 * (data[9] >> 4) + 10 * (data[9] & 0xf);
|
||||
bank1->access_time[no_cas_latencies - 1] =
|
||||
bank2->access_time[no_cas_latencies - 1] =
|
||||
100 * (data[10] >> 4) + 10 * (data[10] & 0xf);
|
||||
/* Then the second highest */
|
||||
if (no_cas_latencies > 1)
|
||||
{
|
||||
bank1->cycle_time[no_cas_latencies - 2] =
|
||||
bank2->cycle_time[no_cas_latencies- 2] =
|
||||
100 * (data[23] >> 4) + 10 * (data[23] & 0xf);
|
||||
bank1->access_time[no_cas_latencies - 2] =
|
||||
bank2->access_time[no_cas_latencies - 2] =
|
||||
100 * (data[24] >> 4) + 10 * (data[24] & 0xf);
|
||||
}
|
||||
/* Then the third highest */
|
||||
if (no_cas_latencies > 2)
|
||||
{
|
||||
bank1->cycle_time[no_cas_latencies - 3] =
|
||||
bank2->cycle_time[no_cas_latencies- 3] =
|
||||
100 * (data[25] >> 2) + 25 * (data[25] & 0x3);
|
||||
bank1->access_time[no_cas_latencies - 3] =
|
||||
bank2->access_time[no_cas_latencies - 3] =
|
||||
100 * (data[26] >> 2) + 25 * (data[26] & 0x3);
|
||||
}
|
||||
if (verbose)
|
||||
for(i = 0; i < no_cas_latencies; i++)
|
||||
printk_info("CL %d: cycle %dns access %dns\n",
|
||||
bank1->cas_latency[i], bank1->cycle_time[i] / 100,
|
||||
bank1->access_time[i] / 100);
|
||||
|
||||
/* Other timings */
|
||||
bank1->min_back_to_back = bank2->min_back_to_back = data[15];
|
||||
bank1->min_row_precharge = bank2->min_row_precharge = data[27];
|
||||
bank1->min_active_to_active = bank2->min_active_to_active = data[28];
|
||||
bank1->min_ras_to_cas = bank2->min_ras_to_cas = data[29];
|
||||
bank1->min_ras = bank2->min_ras = data[30];
|
||||
|
||||
/* Error detection type */
|
||||
bank1->error_detect = bank2->error_detect = data[11];
|
||||
|
||||
/* Crucial row sizes - these mark the data as valid */
|
||||
for(i = 7; i >= 0; i--)
|
||||
{
|
||||
if (data[31] & (1 << i))
|
||||
{
|
||||
bank1->size = (4*1024*1024) << i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (data[5] > 1)
|
||||
{
|
||||
for(i-- ; i >= 0; i--)
|
||||
{
|
||||
if (data[31] & (1 << i))
|
||||
{
|
||||
bank2->size = (4*1024*1024) << i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! bank2->size)
|
||||
bank2->size = bank1->size;
|
||||
}
|
||||
dimm->size = bank1->size + bank2->size;
|
||||
}
|
||||
|
||||
void
|
||||
print_sdram_bank_info(const sdram_bank_info *bank)
|
||||
{
|
||||
printk_info("Bank %d: %dMB\n", bank->number, bank->size / (1024*1024));
|
||||
}
|
||||
|
||||
static const char *error_types[] = {"", "Parity ", "ECC "};
|
||||
|
||||
void
|
||||
print_sdram_dimm_info(const sdram_dimm_info *dimm)
|
||||
{
|
||||
printk_info("Dimm %d: ", dimm->number);
|
||||
if (dimm->size)
|
||||
printk_info("%dMB CL%d (%s): Running at CL%d %s\n",
|
||||
dimm->size / (1024*1024), dimm->bank1->cas_latency[0],
|
||||
dimm->part_number,
|
||||
dimm->bank1->actual_cas,
|
||||
error_types[dimm->bank1->actual_detect]);
|
||||
else
|
||||
printk_info("(none)\n");
|
||||
}
|
||||
509
src/northbridge/motorola/mpc107/mpc107.c
Normal file
509
src/northbridge/motorola/mpc107/mpc107.c
Normal file
|
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* Humboldt Solutions Ltd, adrian@humboldt.co.uk.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
#include <bsp.h>
|
||||
#include <ppc.h>
|
||||
#include <pci.h>
|
||||
#include <mem.h>
|
||||
#include <types.h>
|
||||
#include <string.h>
|
||||
#include <printk.h>
|
||||
#include <arch/io.h>
|
||||
#include "i2c.h"
|
||||
#include "mpc107.h"
|
||||
#include <timer.h>
|
||||
|
||||
#define NUM_DIMMS 1
|
||||
#define NUM_BANKS 2
|
||||
|
||||
extern struct pci_ops pci_direct_ppc;
|
||||
|
||||
struct mem_range *
|
||||
getmeminfo(void)
|
||||
{
|
||||
int i;
|
||||
sdram_dimm_info dimm[NUM_DIMMS];
|
||||
sdram_bank_info bank[NUM_BANKS];
|
||||
static struct mem_range meminfo;
|
||||
|
||||
hostbridge_probe_dimms(NUM_DIMMS, dimm, bank);
|
||||
|
||||
meminfo.basek = 0;
|
||||
meminfo.sizek = 0;
|
||||
|
||||
for (i = 0; i < NUM_BANKS; i++) {
|
||||
meminfo.sizek += bank[i].size;
|
||||
}
|
||||
|
||||
meminfo.sizek >>= 10;
|
||||
|
||||
return &meminfo;
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory is already turned on, but with pessimistic settings. Now
|
||||
* we optimize settings to the actual memory configuration.
|
||||
*/
|
||||
unsigned
|
||||
mpc107_config_memory(void)
|
||||
{
|
||||
sdram_dimm_info sdram_dimms[NUM_DIMMS];
|
||||
sdram_bank_info sdram_banks[NUM_BANKS];
|
||||
|
||||
hostbridge_probe_dimms(NUM_DIMMS, sdram_dimms, sdram_banks);
|
||||
return hostbridge_config_memory(NUM_BANKS, sdram_banks, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure memory settings.
|
||||
*/
|
||||
unsigned long
|
||||
hostbridge_config_memory(int no_banks, sdram_bank_info * bank, int for_real)
|
||||
{
|
||||
int i, j;
|
||||
char ignore[8];
|
||||
/* Convert bus clock to cycle time in 100ns units */
|
||||
unsigned cycle_time = 10 * (2500000000U / bsp_clock_speed());
|
||||
/* Approximate */
|
||||
unsigned access_time = cycle_time - 300;
|
||||
unsigned cas_latency = 0;
|
||||
unsigned rdlat;
|
||||
unsigned refint;
|
||||
unsigned refrec;
|
||||
unsigned acttorw, acttopre;
|
||||
unsigned pretoact, bstopre;
|
||||
enum sdram_error_detect error_detect;
|
||||
u32 mccr1;
|
||||
u32 mccr2;
|
||||
u32 mccr3;
|
||||
u32 mccr4;
|
||||
u8 bank_enable;
|
||||
u32 memstart1, memstart2;
|
||||
u32 extmemstart1, extmemstart2;
|
||||
u32 memend1, memend2;
|
||||
u32 extmemend1, extmemend2;
|
||||
u32 address;
|
||||
|
||||
/* Set up the ignore mask */
|
||||
for(i = 0; i < no_banks; i++)
|
||||
ignore[i] = (bank[i].size == 0);
|
||||
|
||||
/* Pick best CAS latency possible */
|
||||
for (i = 0; i < no_banks; i++)
|
||||
{
|
||||
if (! ignore[i])
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
if (cycle_time >= bank[i].cycle_time[j] &&
|
||||
access_time >= bank[i].access_time[j])
|
||||
{
|
||||
cas_latency = bank[i].cas_latency[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!cas_latency)
|
||||
return 0;
|
||||
|
||||
/* For various parameters there is a risk of clashing between banks */
|
||||
error_detect = (for_real > 1) ? ERRORS_ECC : ERRORS_NONE;
|
||||
for (i = 0; i < no_banks; i++)
|
||||
{
|
||||
if (! ignore[i])
|
||||
{
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
if (bank[i].cas_latency[j] == cas_latency)
|
||||
break;
|
||||
if (j == 3)
|
||||
{
|
||||
ignore[i] = 1;
|
||||
if (! for_real)
|
||||
printk_info("Disabling memory bank %d (cas latency)\n", i);
|
||||
}
|
||||
if (bank[i].error_detect < error_detect)
|
||||
error_detect = bank[i].error_detect;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Read in configuration of port X */
|
||||
pci_direct_ppc.read_dword(0, 0, 0xf0, &mccr1);
|
||||
pci_direct_ppc.read_dword(0, 0, 0xf4, &mccr2);
|
||||
pci_direct_ppc.read_dword(0, 0, 0xfc, &mccr4);
|
||||
mccr1 &= 0xfff00000;
|
||||
mccr2 &= 0xffe00000;
|
||||
mccr3 = 0;
|
||||
mccr4 &= 0x00230000;
|
||||
|
||||
pretoact = 0;
|
||||
acttorw = 0;
|
||||
acttopre = 0;
|
||||
for (i = 0; i < no_banks; i++)
|
||||
if (! ignore[i])
|
||||
{
|
||||
int rowcode = -1;
|
||||
if (for_real)
|
||||
{
|
||||
bank[i].actual_detect = error_detect;
|
||||
bank[i].actual_cas = cas_latency;
|
||||
}
|
||||
|
||||
switch (bank[i].row_bits) {
|
||||
case 13:
|
||||
if (bank[i].internal_banks == 4)
|
||||
rowcode = 2;
|
||||
else if (bank[i].internal_banks == 2)
|
||||
rowcode = 1;
|
||||
break;
|
||||
case 12:
|
||||
if (bank[i].internal_banks == 4)
|
||||
rowcode = 0;
|
||||
else if (bank[i].internal_banks == 2)
|
||||
rowcode = 1;
|
||||
break;
|
||||
case 11:
|
||||
if (bank[i].internal_banks == 4)
|
||||
rowcode = 0;
|
||||
else if (bank[i].internal_banks == 2)
|
||||
rowcode = 3;
|
||||
break;
|
||||
}
|
||||
if (rowcode == -1) {
|
||||
ignore[i] = 1;
|
||||
if (! for_real)
|
||||
printk_info("Memory bank %d disabled: row bits %d and banks %d not supported\n", i, bank[i].row_bits, bank[i].internal_banks);
|
||||
} else
|
||||
mccr1 |= rowcode << (2 * i);
|
||||
|
||||
/* Update worst case settings */
|
||||
if (! ignore[i]) {
|
||||
if (bank[i].min_row_precharge > pretoact)
|
||||
pretoact = bank[i].min_row_precharge;
|
||||
if (bank[i].min_ras_to_cas > acttorw)
|
||||
acttorw = bank[i].min_ras_to_cas;
|
||||
if (bank[i].min_ras > acttopre)
|
||||
acttopre = bank[i].min_ras;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now convert to clock cycles, rounding up */
|
||||
pretoact = (100 * pretoact + cycle_time - 1) / cycle_time;
|
||||
acttopre = (100 * acttopre + cycle_time - 1) / cycle_time;
|
||||
acttorw = (100 * acttorw + cycle_time - 1) / cycle_time;
|
||||
refrec = acttopre;
|
||||
bstopre = 0x240; /* Set conservative values, because we can't derive */
|
||||
refint = 1000;
|
||||
|
||||
if (error_detect == ERRORS_ECC)
|
||||
{
|
||||
rdlat = cas_latency + 2;
|
||||
mccr4 |= 0x00400000;
|
||||
mccr2 |= 0x000c0001;
|
||||
}
|
||||
else
|
||||
{
|
||||
rdlat = cas_latency + 1;
|
||||
mccr4 |= 0x00100000;
|
||||
}
|
||||
|
||||
if (pretoact > 16 || acttopre > 16 || acttorw > 16)
|
||||
if (! for_real)
|
||||
printk_info("Timings out of range\n");
|
||||
mccr4 |= ((pretoact & 0x0f) << 28) | ((acttopre & 0xf) << 24) |
|
||||
((acttorw & 0x0f) << 4) |
|
||||
((bstopre & 0x003) << 18) | ((bstopre & 0x3c0) >> 6) |
|
||||
(cas_latency << 12) | 0x00000200 /* burst length */ ;
|
||||
mccr3 |= ((bstopre & 0x03c) << 26) |
|
||||
((refrec & 0x0f) << 24) | (rdlat << 20);
|
||||
mccr2 |= refint << 2;
|
||||
mccr1 |= 0x00080000; /* memgo */
|
||||
|
||||
address = 0;
|
||||
memstart1 = memstart2 = 0;
|
||||
extmemstart1 = extmemstart2 = 0;
|
||||
memend1 = memend2 = 0;
|
||||
extmemend1 = extmemend2 = 0;
|
||||
bank_enable = 0;
|
||||
for (i = 0; i < no_banks; i++) {
|
||||
if (! ignore[i]) {
|
||||
u32 end = address + bank[i].size - 1;
|
||||
bank_enable |= 1 << i;
|
||||
if (i < 4) {
|
||||
memstart1 |= ((address >> 20) & 0xff) << (8 * i);
|
||||
extmemstart1 |= ((address >> 28) & 0x03) << (8 * i);
|
||||
memend1 |= ((end >> 20) & 0xff) << (8 * i);
|
||||
extmemend1 |= ((end >> 28) & 0x03) << (8 * i);
|
||||
} else {
|
||||
int k = i - 4;
|
||||
memstart2 |= ((address >> 20) & 0xff) << (8 * k);
|
||||
extmemstart2 |= ((address >> 28) & 0x03) << (8 * k);
|
||||
memend2 |= ((end >> 20) & 0xff) << (8 * k);
|
||||
extmemend2 |= ((end >> 28) & 0x03) << (8 * k);
|
||||
}
|
||||
address += bank[i].size;
|
||||
}
|
||||
}
|
||||
|
||||
if (for_real)
|
||||
{
|
||||
pci_direct_ppc.write_byte(0, 0, 0xa0, bank_enable);
|
||||
pci_direct_ppc.write_dword(0, 0, 0x80, memstart1);
|
||||
pci_direct_ppc.write_dword(0, 0, 0x84, memstart2);
|
||||
pci_direct_ppc.write_dword(0, 0, 0x88, extmemstart1);
|
||||
pci_direct_ppc.write_dword(0, 0, 0x8c, extmemstart2);
|
||||
pci_direct_ppc.write_dword(0, 0, 0x90, memend1);
|
||||
pci_direct_ppc.write_dword(0, 0, 0x94, memend2);
|
||||
pci_direct_ppc.write_dword(0, 0, 0x98, extmemend1);
|
||||
pci_direct_ppc.write_dword(0, 0, 0x9c, extmemend2);
|
||||
|
||||
pci_direct_ppc.write_dword(0, 0, 0xfc, mccr4);
|
||||
pci_direct_ppc.write_dword(0, 0, 0xf8, mccr3);
|
||||
pci_direct_ppc.write_dword(0, 0, 0xf4, mccr2);
|
||||
pci_direct_ppc.write_dword(0, 0, 0xf0, mccr1);
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
#define MPC107_I2CADDR 0x00
|
||||
#define MPC107_I2CFDR 0x04
|
||||
#define MPC107_I2CCR 0x08
|
||||
#define MPC107_I2CSR 0x0c
|
||||
#define MPC107_I2CDR 0x10
|
||||
|
||||
#define MPC107_CCR_MEN 0x80
|
||||
#define MPC107_CCR_MSTA 0x20
|
||||
#define MPC107_CCR_MTX 0x10
|
||||
#define MPC107_CCR_TXAK 0x08
|
||||
#define MPC107_CCR_RSTA 0x04
|
||||
|
||||
#define MPC107_CSR_MCF 0x80
|
||||
#define MPC107_CSR_MAAS 0x40
|
||||
#define MPC107_CSR_MBB 0x20
|
||||
#define MPC107_CSR_MAL 0x10
|
||||
#define MPC107_CSR_SRW 0x04
|
||||
#define MPC107_CSR_MIF 0x02
|
||||
#define MPC107_CSR_RXAK 0x01
|
||||
|
||||
#define i2c_base 0xfc003000
|
||||
|
||||
static int
|
||||
i2c_wait(unsigned timeout, int writing)
|
||||
{
|
||||
u32 x;
|
||||
while (((x = readl(i2c_base + MPC107_I2CSR)) & (MPC107_CSR_MCF | MPC107_CSR_MIF))
|
||||
!= (MPC107_CSR_MCF | MPC107_CSR_MIF)) {
|
||||
if (ticks_since_boot() > timeout)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (x & MPC107_CSR_MAL) {
|
||||
return -1;
|
||||
}
|
||||
if (writing && (x & MPC107_CSR_RXAK)) {
|
||||
printk_info("No RXAK\n");
|
||||
/* generate stop */
|
||||
writel(MPC107_CCR_MEN, i2c_base + MPC107_I2CCR);
|
||||
return -1;
|
||||
}
|
||||
writel(0, i2c_base + MPC107_I2CSR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mpc107_i2c_start(struct i2c_bus *bus)
|
||||
{
|
||||
/* Set clock */
|
||||
writel(0x1031, i2c_base + MPC107_I2CFDR);
|
||||
/* Clear arbitration */
|
||||
writel(0, i2c_base + MPC107_I2CSR);
|
||||
}
|
||||
|
||||
static void
|
||||
mpc107_i2c_stop(struct i2c_bus *bus)
|
||||
{
|
||||
/* After last DIMM shut down I2C */
|
||||
writel(0x0, i2c_base + MPC107_I2CCR);
|
||||
}
|
||||
|
||||
static int
|
||||
mpc107_i2c_byte_write(struct i2c_bus *bus, int target, int address, u8 data)
|
||||
{
|
||||
unsigned timeout = ticks_since_boot() + 3 * get_hz();
|
||||
|
||||
/* Must wait here for clocks to start */
|
||||
sleep_ticks(get_hz() / 40);
|
||||
/* Start with MEN */
|
||||
writel(MPC107_CCR_MEN, i2c_base + MPC107_I2CCR);
|
||||
/* Start as master */
|
||||
writel(MPC107_CCR_MEN | MPC107_CCR_MSTA | MPC107_CCR_MTX, i2c_base + MPC107_I2CCR);
|
||||
/* Write target byte */
|
||||
writel(target, i2c_base + MPC107_I2CDR);
|
||||
|
||||
if (i2c_wait(timeout, 1) < 0)
|
||||
return -1;
|
||||
|
||||
/* Write data address byte */
|
||||
writel(address, i2c_base + MPC107_I2CDR);
|
||||
|
||||
if (i2c_wait(timeout, 1) < 0)
|
||||
return -1;
|
||||
|
||||
/* Write data byte */
|
||||
writel(data, i2c_base + MPC107_I2CDR);
|
||||
|
||||
if (i2c_wait(timeout, 1) < 0)
|
||||
return -1;
|
||||
|
||||
/* generate stop */
|
||||
writel(MPC107_CCR_MEN, i2c_base + MPC107_I2CCR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mpc107_i2c_master_write(struct i2c_bus *bus, int target, int address, const u8 *data, int length)
|
||||
{
|
||||
unsigned count;
|
||||
for(count = 0; count < length; count++)
|
||||
{
|
||||
if (mpc107_i2c_byte_write(bus, target, address, data[count]) < 0)
|
||||
return -1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
#define DIMM_LENGTH 0xfff
|
||||
|
||||
static int
|
||||
mpc107_i2c_master_read(struct i2c_bus *bus, int target, int address,
|
||||
u8 *data, int length)
|
||||
{
|
||||
unsigned timeout = ticks_since_boot() + 3 * get_hz();
|
||||
unsigned count;
|
||||
|
||||
/* Must wait here for clocks to start */
|
||||
sleep_ticks(get_hz() / 40);
|
||||
/* Start with MEN */
|
||||
writel(MPC107_CCR_MEN, i2c_base + MPC107_I2CCR);
|
||||
/* Start as master */
|
||||
writel(MPC107_CCR_MEN | MPC107_CCR_MSTA | MPC107_CCR_MTX, i2c_base + MPC107_I2CCR);
|
||||
/* Write target byte */
|
||||
writel(target, i2c_base + MPC107_I2CDR);
|
||||
|
||||
if (i2c_wait(timeout, 1) < 0)
|
||||
return -1;
|
||||
|
||||
/* Write data address byte */
|
||||
writel(address, i2c_base + MPC107_I2CDR);
|
||||
|
||||
if (i2c_wait(timeout, 1) < 0)
|
||||
return -1;
|
||||
|
||||
/* Switch to read - restart */
|
||||
writel(MPC107_CCR_MEN | MPC107_CCR_MSTA | MPC107_CCR_MTX | MPC107_CCR_RSTA, i2c_base + MPC107_I2CCR);
|
||||
/* Write target address byte - this time with the read flag set */
|
||||
writel(target | 1, i2c_base + MPC107_I2CDR);
|
||||
|
||||
if (i2c_wait(timeout, 0) < 0)
|
||||
return -1;
|
||||
|
||||
if (length == 1)
|
||||
writel(MPC107_CCR_MEN | MPC107_CCR_MSTA | MPC107_CCR_TXAK, i2c_base + MPC107_I2CCR);
|
||||
else
|
||||
writel(MPC107_CCR_MEN | MPC107_CCR_MSTA, i2c_base + MPC107_I2CCR);
|
||||
/* Dummy read */
|
||||
readl(i2c_base + MPC107_I2CDR);
|
||||
|
||||
count = 0;
|
||||
while (count < length) {
|
||||
|
||||
if (i2c_wait(timeout, 0) < 0)
|
||||
return -1;
|
||||
|
||||
/* Generate txack on next to last byte */
|
||||
if (count == length - 2)
|
||||
writel(MPC107_CCR_MEN | MPC107_CCR_MSTA | MPC107_CCR_TXAK, i2c_base + MPC107_I2CCR);
|
||||
/* Generate stop on last byte */
|
||||
if (count == length - 1)
|
||||
writel(MPC107_CCR_MEN | MPC107_CCR_TXAK, i2c_base + MPC107_I2CCR);
|
||||
data[count] = readl(i2c_base + MPC107_I2CDR);
|
||||
if (count == 0 && length == DIMM_LENGTH) {
|
||||
if (data[0] == 0xff) {
|
||||
printk_debug("I2C device not present\n");
|
||||
length = 3;
|
||||
} else {
|
||||
length = data[0];
|
||||
if (length < 3)
|
||||
length = 3;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
/* Finish with disable master */
|
||||
writel(MPC107_CCR_MEN, i2c_base + MPC107_I2CCR);
|
||||
return length;
|
||||
}
|
||||
|
||||
i2c_fn mpc107_i2c_fn = {
|
||||
mpc107_i2c_start, mpc107_i2c_stop,
|
||||
mpc107_i2c_master_write, mpc107_i2c_master_read
|
||||
};
|
||||
|
||||
/*
|
||||
* Find dimm information.
|
||||
*/
|
||||
void
|
||||
hostbridge_probe_dimms(int no_dimms, sdram_dimm_info *dimms, sdram_bank_info * bank)
|
||||
{
|
||||
unsigned char data[256];
|
||||
unsigned dimm;
|
||||
|
||||
printk_debug("i2c testing\n");
|
||||
mpc107_i2c_start(NULL);
|
||||
|
||||
for(dimm = 0; dimm < no_dimms; dimm++)
|
||||
{
|
||||
dimms[dimm].number = dimm;
|
||||
dimms[dimm].bank1 = bank + dimm*2;
|
||||
dimms[dimm].bank2 = bank + dimm*2 + 1;
|
||||
bank[dimm*2].size = 0;
|
||||
bank[dimm*2+1].size = 0;
|
||||
bank[dimm*2].number = 0;
|
||||
bank[dimm*2+1].number = 1;
|
||||
}
|
||||
|
||||
|
||||
for (dimm = 0; dimm < no_dimms; dimm ++) {
|
||||
unsigned limit = mpc107_i2c_master_read(NULL, 0xa0 + 2*dimm, 0,
|
||||
data, DIMM_LENGTH);
|
||||
|
||||
if (limit > 3) {
|
||||
sdram_dimm_to_bank_info(data, dimms + dimm, 0);
|
||||
memcpy(dimms[dimm].part_number, data + 73, 18);
|
||||
dimms[dimm].part_number[18] = 0;
|
||||
printk_debug("Part Number: %s\n", dimms[dimm].part_number);
|
||||
}
|
||||
}
|
||||
|
||||
mpc107_i2c_stop(NULL);
|
||||
}
|
||||
79
src/northbridge/motorola/mpc107/mpc107.h
Normal file
79
src/northbridge/motorola/mpc107/mpc107.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* (C) Copyright 2001
|
||||
* Humboldt Solutions Ltd, adrian@humboldt.co.uk.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _MPC107_H
|
||||
#define _MPC107_H
|
||||
|
||||
#ifdef ASM
|
||||
#define BMC_BASE 0x8000 /* Bridge memory controller base address */
|
||||
#else
|
||||
|
||||
enum sdram_error_detect {
|
||||
ERRORS_NONE, ERRORS_PARITY, ERRORS_ECC
|
||||
};
|
||||
|
||||
typedef struct sdram_dimm_info
|
||||
{
|
||||
unsigned size;
|
||||
unsigned number;
|
||||
char part_number[20];
|
||||
struct sdram_bank_info *bank1;
|
||||
struct sdram_bank_info *bank2;
|
||||
} sdram_dimm_info;
|
||||
|
||||
typedef struct sdram_bank_info
|
||||
{
|
||||
unsigned number;
|
||||
unsigned char row_bits;
|
||||
unsigned char internal_banks;
|
||||
unsigned char col_bits;
|
||||
unsigned char data_width;
|
||||
/* Cycle and access times are stored with lowest CAS latency first. Units
|
||||
are 0.01ns */
|
||||
unsigned short cycle_time[3];
|
||||
unsigned short access_time[3];
|
||||
/* Best CAS latencies */
|
||||
unsigned char cas_latency[3];
|
||||
unsigned char cs_latency;
|
||||
unsigned char we_latency;
|
||||
unsigned char min_back_to_back;
|
||||
unsigned char min_row_precharge;
|
||||
unsigned char min_active_to_active;
|
||||
unsigned char min_ras_to_cas;
|
||||
unsigned char min_ras;
|
||||
unsigned char burst_mask;
|
||||
enum sdram_error_detect error_detect;
|
||||
/* Bank size */
|
||||
unsigned size;
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
enum sdram_error_detect actual_detect;
|
||||
unsigned char actual_cas;
|
||||
} sdram_bank_info;
|
||||
|
||||
void sdram_dimm_to_bank_info(const char *dimm_data, sdram_dimm_info *dimm, int verbose);
|
||||
void print_sdram_dimm_info(const sdram_dimm_info *dimm);
|
||||
void print_sdram_bank_info(const sdram_bank_info *bank);
|
||||
|
||||
unsigned long hostbridge_config_memory(int no_banks, sdram_bank_info *bank, int for_real);
|
||||
void hostbridge_probe_dimms(int no_dimms, sdram_dimm_info *dimm, sdram_bank_info * bank);
|
||||
unsigned mpc107_config_memory(void);
|
||||
#endif
|
||||
#endif
|
||||
85
src/northbridge/motorola/mpc107/mpc107_init.S
Normal file
85
src/northbridge/motorola/mpc107/mpc107_init.S
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
|
||||
|
||||
.globl bsp_init_northbridge
|
||||
|
||||
bsp_init_northbridge:
|
||||
mflr r11
|
||||
lis r10, 0x8000
|
||||
|
||||
/* PCI Cmd */
|
||||
li r4, 6
|
||||
ori r3, r10, 4
|
||||
bl __pci_config_write_16
|
||||
|
||||
/* PCI Stat */
|
||||
ori r3, r10, 6
|
||||
bl __pci_config_read_16
|
||||
ori r4, r4, 0xffff
|
||||
ori r3, r10, 6
|
||||
bl __pci_config_write_16
|
||||
|
||||
/* CLK Drive */
|
||||
ori r4, r10, 0xfc01 /* Top bit will be ignored */
|
||||
ori r3, r10, 0x74
|
||||
bl __pci_config_write_16
|
||||
|
||||
/* EUMBBAR */
|
||||
lis r4, 0xfc00
|
||||
ori r3, r10, 0x78
|
||||
bl __pci_config_write_32
|
||||
|
||||
/* Page CTR */
|
||||
li r4, 0x32
|
||||
ori r3, r10, 0xa3
|
||||
lis r7, 1
|
||||
mtctr r7
|
||||
bl __pci_config_write_8
|
||||
|
||||
/* PICR1 */
|
||||
lis r4, 0xff04
|
||||
ori r4, r4, 0x1a18
|
||||
ori r3, r10, 0xa8
|
||||
bl __pci_config_write_32
|
||||
|
||||
/* PICR2 */
|
||||
lis r4, 0x0404
|
||||
ori r4, r4, 0x0004
|
||||
ori r3, r10, 0xac
|
||||
bl __pci_config_write_32
|
||||
|
||||
/* Preserve memgo bit */
|
||||
/* MCCR1 */
|
||||
ori r3, r10, 0xf0
|
||||
bl __pci_config_read_32
|
||||
lis r7, 0x0008
|
||||
and r4, r7, r3
|
||||
oris r4, r4, 0x75e0
|
||||
ori r3, r10, 0xf0
|
||||
bl __pci_config_write_32
|
||||
|
||||
/* MCCR4 */
|
||||
ori r3, r10, 0xfc
|
||||
bl __pci_config_read_32
|
||||
lis r7, 0x0050
|
||||
and r4, r7, r3
|
||||
oris r4, r4, 0x3522
|
||||
ori r3, r10, 0xfc
|
||||
bl __pci_config_write_32
|
||||
|
||||
/* MCCR2 */
|
||||
ori r3, r10, 0xf4
|
||||
bl __pci_config_read_32
|
||||
lis r7, 0x000f
|
||||
ori r7, r7, 0x0001
|
||||
and r4, r3, r7
|
||||
oris r4, r4, 0x0440
|
||||
ori r3, r10, 0xf4
|
||||
bl __pci_config_write_32
|
||||
mtlr r11
|
||||
blr
|
||||
|
||||
311
src/northbridge/motorola/mpc107/mpc107_init.inc
Normal file
311
src/northbridge/motorola/mpc107/mpc107_init.inc
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
.globl bsp_init_northbridge
|
||||
|
||||
#define ASM
|
||||
#include "mpc107.h"
|
||||
|
||||
bsp_init_northbridge:
|
||||
mflr r11
|
||||
lis r10, BMC_BASE
|
||||
|
||||
/*
|
||||
* PCI Cmd
|
||||
*/
|
||||
li r4, 0x0006
|
||||
ori r3, r10, 0x04
|
||||
bl __pci_config_write_16
|
||||
|
||||
/*
|
||||
* PCI Stat
|
||||
*/
|
||||
ori r3, r10, 0x06
|
||||
bl __pci_config_read_16
|
||||
ori r4, r4, 0xffff
|
||||
ori r3, r10, 0x06
|
||||
bl __pci_config_write_16
|
||||
|
||||
/*
|
||||
* PICR1
|
||||
*/
|
||||
ori r3, r10, 0xa8
|
||||
bl __pci_config_read_32
|
||||
|
||||
/*
|
||||
* Preserve RCS0/Addr Map bits
|
||||
*/
|
||||
lis r0, 0x0011
|
||||
and r4, r4, r0
|
||||
|
||||
lis r0, 0xff00
|
||||
// oris r0, r0, 0x0040 /* burst read wait states = 1 */
|
||||
oris r0, r0, 0x0004 /* processor type = 603/750 */
|
||||
|
||||
// ori r0, r0, 0x2000 /* enable LocalBusSlave */
|
||||
ori r0, r0, 0x1000 /* enable Flash write */
|
||||
ori r0, r0, 0x0800 /* enable MCP* assertion */
|
||||
// ori r0, r0, 0x0400 /* enable TEA* assertion */
|
||||
ori r0, r0, 0x0200 /* enable data bus parking */
|
||||
// ori r0, r0, 0x0040 /* enable PCI store gathering */
|
||||
ori r0, r0, 0x0010 /* enable loop-snoop */
|
||||
ori r0, r0, 0x0008 /* enable address bus parking */
|
||||
// ori r0, r0, 0x0004 /* enable speculative PCI reads */
|
||||
|
||||
or r4, r4, r0
|
||||
ori r3, r10, 0xa8
|
||||
bl __pci_config_write_32
|
||||
|
||||
/*
|
||||
* PICR2
|
||||
*/
|
||||
lis r4, 0x0000
|
||||
// oris r4, r4, 0x2000 /* no Serialize Config cycles */
|
||||
// oris r4, r4, 0x0800 /* No PCI Snoop cycles */
|
||||
oris r4, r4, 0x0400 /* FF0 is Local ROM */
|
||||
// oris r4, r4, 0x0200 /* Flash write lockout */
|
||||
|
||||
// oris r4, r4, 0x0000 /* snoop wt states = 0 */
|
||||
oris r4, r4, 0x0004 /* snoop wt states = 1 */
|
||||
// oris r4, r4, 0x0008 /* snoop wt states = 2 */
|
||||
// oris r4, r4, 0x000c /* snoop wt states = 3 */
|
||||
|
||||
// ori r4, r4, 0x0000 /* addr phase wt states = 0 */
|
||||
ori r4, r4, 0x0004 /* addr phase wt states = 1 */
|
||||
// ori r4, r4, 0x0008 /* addr phase wt states = 2 */
|
||||
// ori r4, r4, 0x000c /* addr phase wt states = 3 */
|
||||
|
||||
ori r3, r10, 0xac
|
||||
bl __pci_config_write_32
|
||||
|
||||
/*
|
||||
* EUMBBAR
|
||||
*/
|
||||
lis r4, 0xfc00
|
||||
ori r3, r10, 0x78
|
||||
bl __pci_config_write_32
|
||||
|
||||
/*
|
||||
* MCCR1 - Set MEMGO bit later!
|
||||
*/
|
||||
ori r3, r10, 0xf0
|
||||
bl __pci_config_read_32
|
||||
|
||||
lis r7, 0x0008 /* Preserve MEMGO bit in case we're in RAM */
|
||||
and r4, r7, r3
|
||||
// lis r4, 0x0000 /* Rom speed @100MHz (10ns) */
|
||||
oris r4, r4, 0x7580 /* Safe local ROM = 10+3 clocks */
|
||||
// oris r4, r4, 0x7380 /* Fast local ROM = 7+3 clocks */
|
||||
|
||||
// oris r4, r4, 0x0010 /* Burst ROM/Flash enable */
|
||||
// oris r4, r4, 0x0004 /* Self-refresh enable */
|
||||
// oris r4, r4, 0x0002 /* EDO/FP enable (else SDRAM) */
|
||||
// oris r4, r4, 0x0001 /* Parity check */
|
||||
|
||||
// ori r4, r4, 0xFFFF /* 16Mbit/2 bank SDRAM */
|
||||
// ori r4, r4, 0x5555 /* 64Mbit/2 bank SDRAM */
|
||||
ori r4, r4, 0x0000 /* 64Mbit/4 bank SDRAM */
|
||||
|
||||
ori r3, r10, 0xf0
|
||||
bl __pci_config_write_32
|
||||
|
||||
/*
|
||||
* MCCR2
|
||||
*/
|
||||
lis r4, 0x0000
|
||||
// oris r4, r4, 0x4000 /* TS_WAIT_TIMER = 3 clocks */
|
||||
oris r4, r4, 0x0400 /* ASRISE = 2 clocks */
|
||||
oris r4, r4, 0x0040 /* ASFALL = 2 clocks */
|
||||
// oris r4, r4, 0x0010 /* SDRAM parity (else ECC) */
|
||||
// oris r4, r4, 0x0008 /* SDRAM inline writes */
|
||||
// oris r4, r4, 0x0004 /* SDRAM inline reads */
|
||||
// oris r4, r4, 0x0002 /* ECC enable */
|
||||
// oris r4, r4, 0x0001 /* EDO (else FP) */
|
||||
|
||||
// ori r4, r4, 0x06b8 /* Refresh 33MHz bus */
|
||||
// ori r4, r4, 0x035c /* Refresh 66MHz bus */
|
||||
ori r4, r4, 0x023c /* Refresh 100MHz bus */
|
||||
// ori r4, r4, 0x01ac /* Refresh 133MHz bus */
|
||||
|
||||
// ori r4, r4, 0x0002 /* Reserve a page */
|
||||
// ori r4, r4, 0x0001 /* RWM parity */
|
||||
|
||||
ori r3, r10, 0xf4
|
||||
bl __pci_config_write_32
|
||||
|
||||
/*
|
||||
* MCCR3
|
||||
*/
|
||||
lis r4, 0x7000 /* BSTOPRE_M = 7 */
|
||||
oris r4, r4, 0x0800 /* REFREC = 8 clocks */
|
||||
oris r4, r4, 0x0040 /* RDLAT = 4 clocks */
|
||||
// oris r4, r4, 0x0030 /* RDLAT = 3 clocks */
|
||||
|
||||
ori r3, r10, 0xf8
|
||||
bl __pci_config_write_32
|
||||
|
||||
/*
|
||||
* MCCR4
|
||||
*/
|
||||
lis r4, 0x3000 /* PRETOACT = 3 clocks */
|
||||
oris r4, r4, 0x0500 /* ACTOPRE = 5 clocks */
|
||||
// oris r4, r4, 0x0080 /* Enable 8-beat burst (32-bit bus) */
|
||||
// oris r4, r4, 0x0040 /* Enable Inline ECC/Parity */
|
||||
oris r4, r4, 0x0020 /* Enable Extended ROM (RCS2/RCS3) */
|
||||
oris r4, r4, 0x0010 /* Registered buffers */
|
||||
oris r4, r4, 0x0000 /* BSTOPRE_U = 0 */
|
||||
oris r4, r4, 0x0002 /* Change RCS1 to 8-bit mode */
|
||||
|
||||
// ori r4, r4, 0x8000 /* Registered DIMMs */
|
||||
ori r4, r4, 0x3000 /* CAS Latencey (CL=3) */
|
||||
// ori r4, r4, 0x2000 /* CAS Latencey (CL=2) */
|
||||
ori r4, r4, 0x0200 /* Sequential wrap/4-beat burst */
|
||||
ori r4, r4, 0x0030 /* Reserve a page */
|
||||
ori r4, r4, 0x0009 /* RWM parity */
|
||||
|
||||
ori r3, r10, 0xfc
|
||||
bl __pci_config_write_32
|
||||
|
||||
/*
|
||||
* MSAR1/MSAR2/MESAR1/MESAR2
|
||||
*/
|
||||
lis r4, 0x6040
|
||||
ori r4, r4, 0x2000
|
||||
ori r3, r10, 0x80
|
||||
bl __pci_config_write_32
|
||||
|
||||
lis r4, 0xe0c0
|
||||
ori r4, r4, 0xa080
|
||||
ori r3, r10, 0x84
|
||||
bl __pci_config_write_32
|
||||
|
||||
lis r4, 0x0000
|
||||
ori r4, r4, 0x0000
|
||||
ori r3, r10, 0x88
|
||||
bl __pci_config_write_32
|
||||
|
||||
lis r4, 0x0000
|
||||
ori r4, r4, 0x0000
|
||||
ori r3, r10, 0x8c
|
||||
bl __pci_config_write_32
|
||||
|
||||
/*
|
||||
* MEAR1/MEAR2/MEEAR1/MEEAR2
|
||||
*/
|
||||
lis r4, 0x7f5f
|
||||
ori r4, r4, 0x3f1f
|
||||
ori r3, r10, 0x90
|
||||
bl __pci_config_write_32
|
||||
|
||||
lis r4, 0xffdf
|
||||
ori r4, r4, 0xbf9f
|
||||
ori r3, r10, 0x94
|
||||
bl __pci_config_write_32
|
||||
|
||||
lis r4, 0x0000
|
||||
ori r4, r4, 0x0000
|
||||
ori r3, r10, 0x98
|
||||
bl __pci_config_write_32
|
||||
|
||||
lis r4, 0x0000
|
||||
ori r4, r4, 0x0000
|
||||
ori r3, r10, 0x9c
|
||||
bl __pci_config_write_32
|
||||
|
||||
/*
|
||||
* ODCR
|
||||
*/
|
||||
li r4, 0
|
||||
ori r4, r4, 0x80 /* PCI I/O 50 ohms */
|
||||
ori r4, r4, 0x40 /* CPU I/O 50 ohms */
|
||||
// ori r4, r4, 0x30 /* Mem I/O 8 ohms */
|
||||
// ori r4, r4, 0x20 /* Mem I/O 13 ohms */
|
||||
// ori r4, r4, 0x10 /* Mem I/O 20 ohms */
|
||||
ori r4, r4, 0x00 /* Mem I/O 40 ohms */
|
||||
// ori r4, r4, 0x0c /* PCIClk 8 ohms */
|
||||
// ori r4, r4, 0x08 /* PCIClk 13 ohms */
|
||||
// ori r4, r4, 0x04 /* PCIClk 20 ohms */
|
||||
ori r4, r4, 0x00 /* PCIClk 40 ohms */
|
||||
// ori r4, r4, 0x03 /* MemClk 8 ohms */
|
||||
// ori r4, r4, 0x02 /* MemClk 13.3 ohms */
|
||||
// ori r4, r4, 0x01 /* MemClk 20 ohms */
|
||||
ori r4, r4, 0x00 /* MemClk 40 ohms */
|
||||
ori r3, r10, 0x73
|
||||
bl __pci_config_write_8
|
||||
|
||||
/* CDCR */
|
||||
li r4, 0x7fff
|
||||
addi r4, r4, 1 /* PCI_SYNC_OUT disabled */
|
||||
ori r4, r4, 0x7c00 /* PCI_CLK disabled */
|
||||
// ori r4, r4, 0x0300 /* CPU_CLK 8 ohms */
|
||||
// ori r4, r4, 0x0200 /* CPU_CLK 13 ohms */
|
||||
// ori r4, r4, 0x0100 /* CPU_CLK 20 ohms */
|
||||
// ori r4, r4, 0x0000 /* CPU_CLK 40 ohms */
|
||||
// ori r4, r4, 0x0080 /* SDRAM_SYNC_OUT disabled */
|
||||
// ori r4, r4, 0x0078 /* SDRAM_CLK disabled */
|
||||
// ori r4, r4, 0x0004 /* CPU_CLK0 disabled */
|
||||
// ori r4, r4, 0x0002 /* CPU_CLK1 disabled */
|
||||
ori r4, r4, 0x0001 /* CPU_CLK2 disabled */
|
||||
|
||||
ori r3, r10, 0x74
|
||||
bl __pci_config_write_16
|
||||
|
||||
/*
|
||||
* MDCR
|
||||
*/
|
||||
li r4, 0x00
|
||||
// ori r4, r4, 0x80 /* MCP 1=open-drain, 0=output */
|
||||
ori r4, r4, 0x40 /* SRESET 1=open-drain, 0=output */
|
||||
ori r4, r4, 0x20 /* QACK 1=high-Z, 0=output */
|
||||
|
||||
ori r3, r10, 0x76
|
||||
bl __pci_config_write_8
|
||||
|
||||
/*
|
||||
* MBEN
|
||||
*/
|
||||
li r4, 0x03 /* Enable banks 0 and 1 */
|
||||
ori r3, r10, 0xa0
|
||||
bl __pci_config_write_8
|
||||
|
||||
/*
|
||||
* PGMAX
|
||||
*/
|
||||
li r4, 0x32 /* 33MHz value w/ROMFAL=8 */
|
||||
ori r3, r10, 0xa3
|
||||
bl __pci_config_write_8
|
||||
|
||||
/*
|
||||
* Wait 200us
|
||||
*/
|
||||
lis r7, 0x0001
|
||||
mtctr r7
|
||||
wait1:
|
||||
bdnz wait1
|
||||
|
||||
/*
|
||||
* Now set memgo bit in MCCR1
|
||||
*/
|
||||
ori r3, r10, 0xf0
|
||||
bl __pci_config_read_32
|
||||
|
||||
lis r7, 0x0008 /* MEMGO=1 */
|
||||
or r4, r7, r3
|
||||
|
||||
ori r3, r10, 0xf0
|
||||
bl __pci_config_write_32
|
||||
|
||||
/*
|
||||
* Wait again
|
||||
*/
|
||||
|
||||
lis r7, 0x002
|
||||
ori r7, r7, 0xffff
|
||||
mtctr r7
|
||||
wait2:
|
||||
bdnz wait2
|
||||
|
||||
mtlr r11
|
||||
blr
|
||||
|
||||
62
src/northbridge/motorola/mpc107/mpc107_pci.c
Normal file
62
src/northbridge/motorola/mpc107/mpc107_pci.c
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#include <pci.h>
|
||||
#include <bsp.h>
|
||||
|
||||
unsigned __pci_config_read_32(unsigned address);
|
||||
unsigned __pci_config_read_16(unsigned address);
|
||||
unsigned __pci_config_read_8(unsigned address);
|
||||
void __pci_config_write_32(unsigned address, unsigned data);
|
||||
void __pci_config_write_16(unsigned address, unsigned short data);
|
||||
void __pci_config_write_8(unsigned address, unsigned char data);
|
||||
|
||||
#define CONFIG_CMD(bus,devfn,where) (bus << 16 | devfn << 8 | where | 0x80000000)
|
||||
|
||||
static int pci_ppc_read_config_dword(unsigned char bus, int devfn, int where, u32 *data)
|
||||
{
|
||||
*data = __pci_config_read_32(CONFIG_CMD(bus, devfn, where));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pci_ppc_read_config_word(unsigned char bus, int devfn, int where, u16 *data)
|
||||
{
|
||||
*data = __pci_config_read_16(CONFIG_CMD(bus, devfn, where));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pci_ppc_read_config_byte(unsigned char bus, int devfn, int where, u8 *data)
|
||||
{
|
||||
*data = __pci_config_read_8(CONFIG_CMD(bus, devfn, where));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pci_ppc_write_config_dword(unsigned char bus, int devfn, int where, u32 data)
|
||||
{
|
||||
__pci_config_write_32(CONFIG_CMD(bus, devfn, where), data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pci_ppc_write_config_word(unsigned char bus, int devfn, int where, u16 data)
|
||||
{
|
||||
__pci_config_write_16(CONFIG_CMD(bus, devfn, where), data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pci_ppc_write_config_byte(unsigned char bus, int devfn, int where, u8 data)
|
||||
{
|
||||
__pci_config_write_8(CONFIG_CMD(bus, devfn, where), data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pci_ops pci_direct_ppc =
|
||||
{
|
||||
pci_ppc_read_config_byte,
|
||||
pci_ppc_read_config_word,
|
||||
pci_ppc_read_config_dword,
|
||||
pci_ppc_write_config_byte,
|
||||
pci_ppc_write_config_word,
|
||||
pci_ppc_write_config_dword
|
||||
};
|
||||
|
||||
162
src/northbridge/motorola/mpc107/mpc107_utils.S
Normal file
162
src/northbridge/motorola/mpc107/mpc107_utils.S
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
#include <ppc_asm.tmpl>
|
||||
|
||||
.globl __pci_config_read_32
|
||||
__pci_config_read_32:
|
||||
lis r4, 0xfec0
|
||||
stwbrx r3, 0, r4
|
||||
sync
|
||||
lis r4, 0xfee0
|
||||
lwbrx r3, 0, r4
|
||||
blr
|
||||
|
||||
.globl __pci_config_read_16
|
||||
__pci_config_read_16:
|
||||
lis r4, 0xfec0
|
||||
andi. r5, r3, 2
|
||||
stwbrx r3, 0, r4
|
||||
sync
|
||||
oris r4, r5, 0xfee0
|
||||
lhbrx r3, 0, r4
|
||||
blr
|
||||
|
||||
.globl __pci_config_read_8
|
||||
__pci_config_read_8:
|
||||
lis r4, 0xfec0
|
||||
andi. r5, r3, 3
|
||||
stwbrx r3, 0, r4
|
||||
sync
|
||||
oris r4, r5, 0xfee0
|
||||
lbz r3, 0(r4)
|
||||
blr
|
||||
|
||||
.globl __pci_config_write_32
|
||||
__pci_config_write_32:
|
||||
lis r5, 0xfec0
|
||||
stwbrx r3, r0, r5
|
||||
sync
|
||||
lis r5, 0xfee0
|
||||
stwbrx r4, r0, r5
|
||||
sync
|
||||
blr
|
||||
|
||||
.globl __pci_config_write_16
|
||||
__pci_config_write_16:
|
||||
lis r5, 0xfec0
|
||||
andi. r6, r3, 2
|
||||
stwbrx r3, r0, 5
|
||||
sync
|
||||
oris r5, r6, 0xfee0
|
||||
sthbrx r4, r0, r5
|
||||
sync
|
||||
blr
|
||||
|
||||
.globl __pci_config_write_8
|
||||
__pci_config_write_8:
|
||||
lis r5, 0xfec0
|
||||
andi. r6, r3, 3
|
||||
stwbrx r3, r0, r5
|
||||
sync
|
||||
oris r5, r6, 0xfee0
|
||||
stb r4, 0(r5)
|
||||
sync
|
||||
blr
|
||||
|
||||
.globl in_8
|
||||
in_8:
|
||||
oris r3, r3, 0xfe00
|
||||
lbz r3,0(r3)
|
||||
blr
|
||||
|
||||
.globl in_16
|
||||
in_16:
|
||||
oris r3, r3, 0xfe00
|
||||
lhbrx r3, 0, r3
|
||||
blr
|
||||
|
||||
.globl in_16_ne
|
||||
in_16_ne:
|
||||
oris r3, r3, 0xfe00
|
||||
lhzx r3, 0, r3
|
||||
blr
|
||||
|
||||
.globl in_32
|
||||
in_32:
|
||||
oris r3, r3, 0xfe00
|
||||
lwbrx r3, 0, r3
|
||||
blr
|
||||
|
||||
.globl out_8
|
||||
out_8:
|
||||
oris r3, r3, 0xfe00
|
||||
stb r4, 0(r3)
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl out_16
|
||||
out_16:
|
||||
oris r3, r3, 0xfe00
|
||||
sthbrx r4, 0, r3
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl out_16_ne
|
||||
out_16_ne:
|
||||
oris r3, r3, 0xfe00
|
||||
sth r4, 0(r3)
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl out_32
|
||||
out_32:
|
||||
oris r3, r3, 0xfe00
|
||||
stwbrx r4, 0, r3
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl read_8
|
||||
read_8:
|
||||
lbz r3,0(r3)
|
||||
blr
|
||||
|
||||
.globl read_16
|
||||
read_16:
|
||||
lhbrx r3, 0, r3
|
||||
blr
|
||||
|
||||
.globl read_32
|
||||
read_32:
|
||||
lwbrx r3, 0, r3
|
||||
blr
|
||||
|
||||
.globl read_32_ne
|
||||
read_32_ne:
|
||||
lwz r3, 0(r3)
|
||||
blr
|
||||
|
||||
.globl write_8
|
||||
write_8:
|
||||
stb r4, 0(r3)
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl write_16
|
||||
write_16:
|
||||
sthbrx r4, 0, r3
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl write_32
|
||||
write_32:
|
||||
stwbrx r4, 0, r3
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl write_32_ne
|
||||
write_32_ne:
|
||||
stw r4, 0(r3)
|
||||
eieio
|
||||
blr
|
||||
160
src/northbridge/motorola/mpc107/mpc107_utils.inc
Normal file
160
src/northbridge/motorola/mpc107/mpc107_utils.inc
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/* $Id$ */
|
||||
/* Copyright 2000 AG Electronics Ltd. */
|
||||
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
|
||||
|
||||
.globl __pci_config_read_32
|
||||
__pci_config_read_32:
|
||||
lis r4, 0xfec0
|
||||
stwbrx r3, r0, r4
|
||||
sync
|
||||
lis r4, 0xfee0
|
||||
lwbrx r3, 0, r4
|
||||
blr
|
||||
|
||||
.globl __pci_config_read_16
|
||||
__pci_config_read_16:
|
||||
lis r4, 0xfec0
|
||||
andi. r5, r3, 2
|
||||
stwbrx r3, r0, r4
|
||||
sync
|
||||
oris r4, r5, 0xfee0
|
||||
lhbrx r3, r0, r4
|
||||
blr
|
||||
|
||||
.globl __pci_config_read_8
|
||||
__pci_config_read_8:
|
||||
lis r4, 0xfec0
|
||||
andi. r5, r3, 3
|
||||
stwbrx r3, r0, r4
|
||||
sync
|
||||
oris r4, r5, 0xfee0
|
||||
lbz r3, 0(r4)
|
||||
blr
|
||||
|
||||
.globl __pci_config_write_32
|
||||
__pci_config_write_32:
|
||||
lis r5, 0xfec0
|
||||
stwbrx r3, r0, r5
|
||||
sync
|
||||
lis r5, 0xfee0
|
||||
stwbrx r4, r0, r5
|
||||
sync
|
||||
blr
|
||||
|
||||
.globl __pci_config_write_16
|
||||
__pci_config_write_16:
|
||||
lis r5, 0xfec0
|
||||
andi. r6, r3, 2
|
||||
stwbrx r3, r0, 5
|
||||
sync
|
||||
oris r5, r6, 0xfee0
|
||||
sthbrx r4, r0, r5
|
||||
sync
|
||||
blr
|
||||
|
||||
.globl __pci_config_write_8
|
||||
__pci_config_write_8:
|
||||
lis r5, 0xfec0
|
||||
andi. r6, r3, 3
|
||||
stwbrx r3, r0, r5
|
||||
sync
|
||||
oris r5, r6, 0xfee0
|
||||
stb r4, 0(r5)
|
||||
sync
|
||||
blr
|
||||
|
||||
.globl in_8
|
||||
in_8:
|
||||
oris r3, r3, 0xfe00
|
||||
lbz r3,0(r3)
|
||||
blr
|
||||
|
||||
.globl in_16
|
||||
in_16:
|
||||
oris r3, r3, 0xfe00
|
||||
lhbrx r3, 0, r3
|
||||
blr
|
||||
|
||||
.globl in_16_ne
|
||||
in_16_ne:
|
||||
oris r3, r3, 0xfe00
|
||||
lhzx r3, 0, r3
|
||||
blr
|
||||
|
||||
.globl in_32
|
||||
in_32:
|
||||
oris r3, r3, 0xfe00
|
||||
lwbrx r3, 0, r3
|
||||
blr
|
||||
|
||||
.globl out_8
|
||||
out_8:
|
||||
oris r3, r3, 0xfe00
|
||||
stb r4, 0(r3)
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl out_16
|
||||
out_16:
|
||||
oris r3, r3, 0xfe00
|
||||
sthbrx r4, 0, r3
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl out_16_ne
|
||||
out_16_ne:
|
||||
oris r3, r3, 0xfe00
|
||||
sth r4, 0(r3)
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl out_32
|
||||
out_32:
|
||||
oris r3, r3, 0xfe00
|
||||
stwbrx r4, 0, r3
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl read_8
|
||||
read_8:
|
||||
lbz r3,0(r3)
|
||||
blr
|
||||
|
||||
.globl read_16
|
||||
read_16:
|
||||
lhbrx r3, 0, r3
|
||||
blr
|
||||
|
||||
.globl read_32
|
||||
read_32:
|
||||
lwbrx r3, 0, r3
|
||||
blr
|
||||
|
||||
.globl read_32_ne
|
||||
read_32_ne:
|
||||
lwz r3, 0(r3)
|
||||
blr
|
||||
|
||||
.globl write_8
|
||||
write_8:
|
||||
stb r4, 0(r3)
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl write_16
|
||||
write_16:
|
||||
sthbrx r4, 0, r3
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl write_32
|
||||
write_32:
|
||||
stwbrx r4, 0, r3
|
||||
eieio
|
||||
blr
|
||||
|
||||
.globl write_32_ne
|
||||
write_32_ne:
|
||||
stw r4, 0(r3)
|
||||
eieio
|
||||
blr
|
||||
Loading…
Add table
Add a link
Reference in a new issue