提交 1df49e27 编写于 作者: W wdenk

Initial revision

上级 e69b4b8f
/*
* (C) Copyright 2001
* Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
*
* 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
*/
/*
* cpu.c
*
* CPU specific code
*
* written or collected and sometimes rewritten by
* Magnus Damm <damm@bitsmart.com>
*
* minor modifications by
* Wolfgang Denk <wd@denx.de>
*
* more modifications by
* Josh Huber <huber@mclx.com>
* added support for the 74xx series of cpus
* added support for the 7xx series of cpus
* made the code a little less hard-coded, and more auto-detectish
*/
#include <common.h>
#include <command.h>
#include <74xx_7xx.h>
#include <asm/cache.h>
cpu_t
get_cpu_type(void)
{
uint pvr = get_pvr();
cpu_t type;
type = CPU_UNKNOWN;
switch (PVR_VER(pvr)) {
case 0x000c:
type = CPU_7400;
break;
case 0x0008:
type = CPU_750;
if (((pvr >> 8) & 0xff) == 0x01) {
type = CPU_750CX; /* old CX (80100 and 8010x?)*/
} else if (((pvr >> 8) & 0xff) == 0x22) {
type = CPU_750CX; /* CX (82201,82202) and CXe (82214) */
} else if (((pvr >> 8) & 0xff) == 0x33) {
type = CPU_750CX; /* CXe (83311) */
} else if (((pvr >> 12) & 0xF) == 0x3) {
type = CPU_755;
}
break;
case 0x800C:
type = CPU_7410;
break;
case 0x8000:
type = CPU_7450;
break;
default:
break;
}
return type;
}
/* ------------------------------------------------------------------------- */
#if !defined(CONFIG_BAB7xx)
int checkcpu (void)
{
DECLARE_GLOBAL_DATA_PTR;
uint type = get_cpu_type();
uint pvr = get_pvr();
ulong clock = gd->cpu_clk;
char buf[32];
char *str;
puts ("CPU: ");
switch (type) {
case CPU_750CX:
printf ("750CX%s v%d.%d", (pvr&0xf0)?"e":"",
(pvr>>8) & 0xf,
pvr & 0xf);
goto PR_CLK;
case CPU_750:
str = "750";
break;
case CPU_755:
str = "755";
break;
case CPU_7400:
str = "MPC7400";
break;
case CPU_7410:
str = "MPC7410";
break;
case CPU_7450:
str = "MPC7450";
break;
default:
printf("Unknown CPU -- PVR: 0x%08x\n", pvr);
return -1;
}
printf ("%s v%d.%d", str, (pvr >> 8) & 0xFF, pvr & 0xFF);
PR_CLK:
printf (" @ %s MHz\n", strmhz(buf, clock));
return (0);
}
#endif
/* these two functions are unimplemented currently [josh] */
/* ------------------------------------------------------------------------- */
/* L1 i-cache */
int
checkicache(void)
{
return 0; /* XXX */
}
/* ------------------------------------------------------------------------- */
/* L1 d-cache */
int
checkdcache(void)
{
return 0; /* XXX */
}
/* ------------------------------------------------------------------------- */
static inline void
soft_restart(unsigned long addr)
{
/* SRR0 has system reset vector, SRR1 has default MSR value */
/* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
__asm__ __volatile__ ("mtspr 26, %0" :: "r" (addr));
__asm__ __volatile__ ("li 4, (1 << 6)" ::: "r4");
__asm__ __volatile__ ("mtspr 27, 4");
__asm__ __volatile__ ("rfi");
while(1); /* not reached */
}
#if !defined(CONFIG_PCIPPC2) && \
!defined(CONFIG_BAB7xx) && \
!defined(CONFIG_ELPPC)
/* no generic way to do board reset. simply call soft_reset. */
void
do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong addr;
/* flush and disable I/D cache */
__asm__ __volatile__ ("mfspr 3, 1008" ::: "r3");
__asm__ __volatile__ ("ori 5, 5, 0xcc00" ::: "r5");
__asm__ __volatile__ ("ori 4, 3, 0xc00" ::: "r4");
__asm__ __volatile__ ("andc 5, 3, 5" ::: "r5");
__asm__ __volatile__ ("sync");
__asm__ __volatile__ ("mtspr 1008, 4");
__asm__ __volatile__ ("isync");
__asm__ __volatile__ ("sync");
__asm__ __volatile__ ("mtspr 1008, 5");
__asm__ __volatile__ ("isync");
__asm__ __volatile__ ("sync");
#ifdef CFG_RESET_ADDRESS
addr = CFG_RESET_ADDRESS;
#else
/*
* note: when CFG_MONITOR_BASE points to a RAM address,
* CFG_MONITOR_BASE - sizeof (ulong) is usually a valid
* address. Better pick an address known to be invalid on your
* system and assign it to CFG_RESET_ADDRESS.
*/
addr = CFG_MONITOR_BASE - sizeof (ulong);
#endif
soft_restart(addr);
while(1); /* not reached */
}
#endif
/* ------------------------------------------------------------------------- */
/*
* For the 7400 the TB clock runs at 1/4 the cpu bus speed.
*/
unsigned long
get_tbclk (void)
{
return CFG_BUS_HZ / 4;
}
/* ------------------------------------------------------------------------- */
#if defined(CONFIG_WATCHDOG)
#if !defined(CONFIG_PCIPPC2) && !defined(CONFIG_BAB7xx)
void
watchdog_reset(void)
{
}
#endif /* !CONFIG_PCIPPC2 && !CONFIG_BAB7xx */
#endif /* CONFIG_WATCHDOG */
/* ------------------------------------------------------------------------- */
此差异已折叠。
此差异已折叠。
/*
* (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Andreas Heppel <aheppel@sysgo.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
*/
/*
* Initialisation of the PCI-to-ISA bridge and disabling the BIOS
* write protection (for flash) in function 0 of the chip.
* Enabling function 1 (IDE controller of the chip.
*/
#include <common.h>
#include <config.h>
#ifdef CFG_WINBOND_83C553
#include <asm/io.h>
#include <pci.h>
#include <w83c553f.h>
#define out8(addr,val) do { \
out_8((u8*) (addr),(val)); udelay(1); \
} while (0)
#define out16(addr,val) do { \
out_be16((u16*) (addr),(val)); udelay(1); \
} while (0)
extern uint ide_bus_offset[CFG_IDE_MAXBUS];
void initialise_pic(void);
void initialise_dma(void);
void initialise_w83c553f(void)
{
pci_dev_t devbusfn;
unsigned char reg8;
unsigned short reg16;
unsigned int reg32;
devbusfn = pci_find_device(W83C553F_VID, W83C553F_DID, 0);
if (devbusfn == -1)
{
printf("Error: Cannot find W83C553F controller on any PCI bus.");
return;
}
pci_read_config_word(devbusfn, PCI_COMMAND, &reg16);
reg16 |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
pci_write_config_word(devbusfn, PCI_COMMAND, reg16);
pci_read_config_byte(devbusfn, WINBOND_IPADCR, &reg8);
/* 16 MB ISA memory space */
reg8 |= (IPADCR_IPATOM4 | IPADCR_IPATOM5 | IPADCR_IPATOM6 | IPADCR_IPATOM7);
reg8 &= ~IPADCR_MBE512;
pci_write_config_byte(devbusfn, WINBOND_IPADCR, reg8);
pci_read_config_byte(devbusfn, WINBOND_CSCR, &reg8);
/* switch off BIOS write protection */
reg8 |= CSCR_UBIOSCSE;
reg8 &= ~CSCR_BIOSWP;
pci_write_config_byte(devbusfn, WINBOND_CSCR, reg8);
/*
* Interrupt routing:
* - IDE -> IRQ 9/0
* - INTA -> IRQ 10
* - INTB -> IRQ 11
* - INTC -> IRQ 14
* - INTD -> IRQ 15
*/
pci_write_config_byte(devbusfn, WINBOND_IDEIRCR, 0x90);
pci_write_config_word(devbusfn, WINBOND_PCIIRCR, 0xABEF);
/*
* Read IDE bus offsets from function 1 device.
* We must unmask the LSB indicating that ist is an IO address.
*/
devbusfn |= PCI_BDF(0,0,1);
/*
* Switch off legacy IRQ for IDE and IDE port 1.
*/
pci_write_config_byte(devbusfn, 0x09, 0x8F);
pci_read_config_dword(devbusfn, WINDOND_IDECSR, &reg32);
reg32 &= ~(IDECSR_LEGIRQ | IDECSR_P1EN | IDECSR_P1F16);
pci_write_config_dword(devbusfn, WINDOND_IDECSR, reg32);
pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &ide_bus_offset[0]);
ide_bus_offset[0] &= ~1;
#if CFG_IDE_MAXBUS > 1
pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_2, &ide_bus_offset[1]);
ide_bus_offset[1] &= ~1;
#endif
/*
* Enable function 1, IDE -> busmastering and IO space access
*/
pci_read_config_word(devbusfn, PCI_COMMAND, &reg16);
reg16 |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
pci_write_config_word(devbusfn, PCI_COMMAND, reg16);
/*
* Initialise ISA interrupt controller
*/
initialise_pic();
/*
* Initialise DMA controller
*/
initialise_dma();
}
void initialise_pic(void)
{
out8(W83C553F_PIC1_ICW1, 0x11);
out8(W83C553F_PIC1_ICW2, 0x08);
out8(W83C553F_PIC1_ICW3, 0x04);
out8(W83C553F_PIC1_ICW4, 0x01);
out8(W83C553F_PIC1_OCW1, 0xfb);
out8(W83C553F_PIC1_ELC, 0x20);
out8(W83C553F_PIC2_ICW1, 0x11);
out8(W83C553F_PIC2_ICW2, 0x08);
out8(W83C553F_PIC2_ICW3, 0x02);
out8(W83C553F_PIC2_ICW4, 0x01);
out8(W83C553F_PIC2_OCW1, 0xff);
out8(W83C553F_PIC2_ELC, 0xce);
out8(W83C553F_TMR1_CMOD, 0x74);
out8(W83C553F_PIC2_OCW1, 0x20);
out8(W83C553F_PIC1_OCW1, 0x20);
out8(W83C553F_PIC2_OCW1, 0x2b);
out8(W83C553F_PIC1_OCW1, 0x2b);
}
void initialise_dma(void)
{
unsigned int channel;
unsigned int rvalue1, rvalue2;
/* perform a H/W reset of the devices */
out8(W83C553F_DMA1 + W83C553F_DMA1_MC, 0x00);
out16(W83C553F_DMA2 + W83C553F_DMA2_MC, 0x0000);
/* initialise all channels to a sane state */
for (channel = 0; channel < 4; channel++) {
/*
* dependent upon the channel, setup the specifics:
*
* demand
* address-increment
* autoinitialize-disable
* verify-transfer
*/
switch (channel) {
case 0:
rvalue1 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH0SEL|W83C553F_MODE_TT_VERIFY);
rvalue2 = (W83C553F_MODE_TM_CASCADE|W83C553F_MODE_CH0SEL);
break;
case 1:
rvalue1 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH1SEL|W83C553F_MODE_TT_VERIFY);
rvalue2 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH1SEL|W83C553F_MODE_TT_VERIFY);
break;
case 2:
rvalue1 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH2SEL|W83C553F_MODE_TT_VERIFY);
rvalue2 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH2SEL|W83C553F_MODE_TT_VERIFY);
break;
case 3:
rvalue1 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH3SEL|W83C553F_MODE_TT_VERIFY);
rvalue2 = (W83C553F_MODE_TM_DEMAND|W83C553F_MODE_CH3SEL|W83C553F_MODE_TT_VERIFY);
break;
default:
rvalue1 = 0x00;
rvalue2 = 0x00;
break;
}
/* write to write mode registers */
out8(W83C553F_DMA1 + W83C553F_DMA1_WM, rvalue1 & 0xFF);
out16(W83C553F_DMA2 + W83C553F_DMA2_WM, rvalue2 & 0x00FF);
}
/* enable all channels */
out8(W83C553F_DMA1 + W83C553F_DMA1_CM, 0x00);
out16(W83C553F_DMA2 + W83C553F_DMA2_CM, 0x0000);
/*
* initialize the global DMA configuration
*
* DACK# active low
* DREQ active high
* fixed priority
* channel group enable
*/
out8(W83C553F_DMA1 + W83C553F_DMA1_CS, 0x00);
out16(W83C553F_DMA2 + W83C553F_DMA2_CS, 0x0000);
}
#endif /* CFG_WINBOND_83C553 */
/*
* (C) Copyright 2002 ELTEC Elektronik AG
* Frank Gottschling <fgottschling@eltec.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
*/
/* i8042.h - Intel 8042 keyboard driver header */
#ifndef _I8042_H_
#define _I8042_H_
/* defines */
#define I8042_DATA_REG (CFG_ISA_IO + 0x0060) /* keyboard i/o buffer */
#define I8042_STATUS_REG (CFG_ISA_IO + 0x0064) /* keyboard status read */
#define I8042_COMMAND_REG (CFG_ISA_IO + 0x0064) /* keyboard ctrl write */
#define KBD_US 0 /* default US layout */
#define KBD_GER 1 /* german layout */
#define KBD_TIMEOUT 1000 /* 1 sec */
#define KBD_RESET_TRIES 3
#define AS 0 /* normal character index */
#define SH 1 /* shift index */
#define CN 2 /* control index */
#define NM 3 /* numeric lock index */
#define AK 4 /* right alt key */
#define CP 5 /* capslock index */
#define ST 6 /* stop output index */
#define EX 7 /* extended code index */
#define ES 8 /* escape and extended code index */
#define NORMAL 0x0000 /* normal key */
#define STP 0x0001 /* scroll lock stop output*/
#define NUM 0x0002 /* numeric lock */
#define CAPS 0x0004 /* capslock */
#define SHIFT 0x0008 /* shift */
#define CTRL 0x0010 /* control*/
#define EXT 0x0020 /* extended scan code 0xe0 */
#define ESC 0x0040 /* escape key press */
#define E1 0x0080 /* extended scan code 0xe1 */
#define BRK 0x0100 /* make break flag for keyboard */
#define ALT 0x0200 /* right alt */
/* exports */
int i8042_kbd_init(void);
int i8042_tstc(void);
int i8042_getc(void);
#endif /* _I8042_H_ */
此差异已折叠。
/*
* (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Andreas Heppel <aheppel@sysgo.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
*/
#ifndef _MPC106_PCI_H
#define _MPC106_PCI_H
/*
* Defines for the MPC106 PCI Config address and data registers followed by
* defines for the standard PCI device configuration header.
*/
#define PCIDEVID_MPC106 0x0
/*
* MPC106 Registers
*/
#define MPC106_REG 0x80000000
#ifdef CFG_ADDRESS_MAP_A
#define MPC106_REG_ADDR 0x80000cf8
#define MPC106_REG_DATA 0x80000cfc
#define MPC106_ISA_IO_PHYS 0x80000000
#define MPC106_ISA_IO_BUS 0x00000000
#define MPC106_ISA_IO_SIZE 0x00800000
#define MPC106_PCI_IO_PHYS 0x81000000
#define MPC106_PCI_IO_BUS 0x01000000
#define MPC106_PCI_IO_SIZE 0x3e800000
#define MPC106_PCI_MEM_PHYS 0xc0000000
#define MPC106_PCI_MEM_BUS 0x00000000
#define MPC106_PCI_MEM_SIZE 0x3f000000
#define MPC106_PCI_MEMORY_PHYS 0x00000000
#define MPC106_PCI_MEMORY_BUS 0x80000000
#define MPC106_PCI_MEMORY_SIZE 0x80000000
#else
#define MPC106_REG_ADDR 0xfec00cf8
#define MPC106_REG_DATA 0xfee00cfc
#define MPC106_ISA_MEM_PHYS 0xfd000000
#define MPC106_ISA_MEM_BUS 0x00000000
#define MPC106_ISA_MEM_SIZE 0x01000000
#define MPC106_ISA_IO_PHYS 0xfe000000
#define MPC106_ISA_IO_BUS 0x00000000
#define MPC106_ISA_IO_SIZE 0x00800000
#define MPC106_PCI_IO_PHYS 0xfe800000
#define MPC106_PCI_IO_BUS 0x00800000
#define MPC106_PCI_IO_SIZE 0x00400000
#define MPC106_PCI_MEM_PHYS 0x80000000
#define MPC106_PCI_MEM_BUS 0x80000000
#define MPC106_PCI_MEM_SIZE 0x7d000000
#define MPC106_PCI_MEMORY_PHYS 0x00000000
#define MPC106_PCI_MEMORY_BUS 0x00000000
#define MPC106_PCI_MEMORY_SIZE 0x40000000
#endif
#define CMD_SERR 0x0100
#define PCI_CMD_MASTER 0x0004
#define PCI_CMD_MEMEN 0x0002
#define PCI_CMD_IOEN 0x0001
#define PCI_STAT_NO_RSV_BITS 0xffff
#define PCI_BUSNUM 0x40
#define PCI_SUBBUSNUM 0x41
#define PCI_DISCOUNT 0x42
#define PCI_PICR1 0xA8
#define PICR1_CF_CBA(value) ((value & 0xff) << 24)
#define PICR1_CF_BREAD_WS(value) ((value & 0x3) << 22)
#define PICR1_PROC_TYPE_603 0x40000
#define PICR1_PROC_TYPE_604 0x60000
#define PICR1_MCP_EN 0x800
#define PICR1_CF_DPARK 0x200
#define PICR1_CF_LOOP_SNOOP 0x10
#define PICR1_CF_L2_COPY_BACK 0x2
#define PICR1_CF_L2_CACHE_MASK 0x3
#define PICR1_CF_APARK 0x8
#define PICR1_ADDRESS_MAP 0x10000
#define PICR1_XIO_MODE 0x80000
#define PICR1_CF_CACHE_1G 0x200000
#define PCI_PICR2 0xAC
#define PICR2_CF_SNOOP_WS(value) ((value & 0x3) << 18)
#define PICR2_CF_FLUSH_L2 0x10000000
#define PICR2_CF_L2_HIT_DELAY(value) ((value & 0x3) << 9)
#define PICR2_CF_APHASE_WS(value) ((value & 0x3) << 2)
#define PICR2_CF_INV_MODE 0x00001000
#define PICR2_CF_MOD_HIGH 0x00020000
#define PICR2_CF_HIT_HIGH 0x00010000
#define PICR2_L2_SIZE_256K 0x00000000
#define PICR2_L2_SIZE_512K 0x00000010
#define PICR2_L2_SIZE_1MB 0x00000020
#define PICR2_L2_EN 0x40000000
#define PICR2_L2_UPDATE_EN 0x80000000
#define PICR2_CF_ADDR_ONLY_DISABLE 0x00004000
#define PICR2_CF_FAST_CASTOUT 0x00000080
#define PICR2_CF_WDATA 0x00000001
#define PICR2_CF_DATA_RAM_PBURST 0x00400000
/*
* Memory controller
*/
#define MPC106_MCCR1 0xF0
#define MCCR1_TYPE_EDO 0x00020000
#define MCCR1_BK0_9BITS 0x0
#define MCCR1_BK0_10BITS 0x1
#define MCCR1_BK0_11BITS 0x2
#define MCCR1_BK0_12BITS 0x3
#define MCCR1_BK1_9BITS 0x0
#define MCCR1_BK1_10BITS 0x4
#define MCCR1_BK1_11BITS 0x8
#define MCCR1_BK1_12BITS 0xC
#define MCCR1_BK2_9BITS 0x00
#define MCCR1_BK2_10BITS 0x10
#define MCCR1_BK2_11BITS 0x20
#define MCCR1_BK2_12BITS 0x30
#define MCCR1_BK3_9BITS 0x00
#define MCCR1_BK3_10BITS 0x40
#define MCCR1_BK3_11BITS 0x80
#define MCCR1_BK3_12BITS 0xC0
#define MCCR1_MEMGO 0x00080000
#define MPC106_MCCR2 0xF4
#define MPC106_MCCR3 0xF8
#define MPC106_MCCR4 0xFC
#define MPC106_MSAR1 0x80
#define MPC106_EMSAR1 0x88
#define MPC106_EMSAR2 0x8C
#define MPC106_MEAR1 0x90
#define MPC106_EMEAR1 0x98
#define MPC106_EMEAR2 0x9C
#define MPC106_MBER 0xA0
#define MBER_BANK0 0x1
#define MBER_BANK1 0x2
#define MBER_BANK2 0x4
#define MBER_BANK3 0x8
#endif
/*
* (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Andreas Heppel <aheppel@sysgo.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
*/
/*
* Date & Time support for the MK48T59 RTC
*/
#undef RTC_DEBUG
#include <common.h>
#include <command.h>
#include <config.h>
#include <rtc.h>
#include <mk48t59.h>
#if defined(CONFIG_RTC_MK48T59)
#if defined(CONFIG_BAB7xx)
static uchar rtc_read (short reg)
{
out8(RTC_PORT_ADDR0, reg & 0xFF);
out8(RTC_PORT_ADDR1, (reg>>8) & 0xFF);
return in8(RTC_PORT_DATA);
}
static void rtc_write (short reg, uchar val)
{
out8(RTC_PORT_ADDR0, reg & 0xFF);
out8(RTC_PORT_ADDR1, (reg>>8) & 0xFF);
out8(RTC_PORT_DATA, val);
}
#elif defined(CONFIG_PCIPPC2)
#include "../board/pcippc2/pcippc2.h"
static uchar rtc_read (short reg)
{
return in8(RTC(reg));
}
static void rtc_write (short reg, uchar val)
{
out8(RTC(reg),val);
}
#else
# error Board specific rtc access functions should be supplied
#endif
static unsigned bcd2bin (uchar n)
{
return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
}
static unsigned char bin2bcd (unsigned int n)
{
return (((n / 10) << 4) | (n % 10));
}
/* ------------------------------------------------------------------------- */
void *nvram_read(void *dest, const short src, size_t count)
{
uchar *d = (uchar *) dest;
short s = src;
while (count--)
*d++ = rtc_read(s++);
return dest;
}
void nvram_write(short dest, const void *src, size_t count)
{
short d = dest;
uchar *s = (uchar *) src;
while (count--)
rtc_write(d++, *s++);
}
#if (CONFIG_COMMANDS & CFG_CMD_DATE)
/* ------------------------------------------------------------------------- */
void rtc_get (struct rtc_time *tmp)
{
uchar save_ctrl_a;
uchar sec, min, hour, mday, wday, mon, year;
/* Simple: freeze the clock, read it and allow updates again */
save_ctrl_a = rtc_read(RTC_CONTROLA);
/* Set the register to read the value. */
save_ctrl_a |= RTC_CA_READ;
rtc_write(RTC_CONTROLA, save_ctrl_a);
sec = rtc_read (RTC_SECONDS);
min = rtc_read (RTC_MINUTES);
hour = rtc_read (RTC_HOURS);
mday = rtc_read (RTC_DAY_OF_MONTH);
wday = rtc_read (RTC_DAY_OF_WEEK);
mon = rtc_read (RTC_MONTH);
year = rtc_read (RTC_YEAR);
/* re-enable update */
save_ctrl_a &= ~RTC_CA_READ;
rtc_write(RTC_CONTROLA, save_ctrl_a);
#ifdef RTC_DEBUG
printf ( "Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
"hr: %02x min: %02x sec: %02x\n",
year, mon, mday, wday,
hour, min, sec );
#endif
tmp->tm_sec = bcd2bin (sec & 0x7F);
tmp->tm_min = bcd2bin (min & 0x7F);
tmp->tm_hour = bcd2bin (hour & 0x3F);
tmp->tm_mday = bcd2bin (mday & 0x3F);
tmp->tm_mon = bcd2bin (mon & 0x1F);
tmp->tm_year = bcd2bin (year);
tmp->tm_wday = bcd2bin (wday & 0x07);
if(tmp->tm_year<70)
tmp->tm_year+=2000;
else
tmp->tm_year+=1900;
tmp->tm_yday = 0;
tmp->tm_isdst= 0;
#ifdef RTC_DEBUG
printf ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
#endif
}
void rtc_set (struct rtc_time *tmp)
{
uchar save_ctrl_a;
#ifdef RTC_DEBUG
printf ( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
#endif
save_ctrl_a = rtc_read(RTC_CONTROLA);
save_ctrl_a |= RTC_CA_WRITE;
rtc_write(RTC_CONTROLA, save_ctrl_a); /* disables the RTC to update the regs */
rtc_write (RTC_YEAR, bin2bcd(tmp->tm_year % 100));
rtc_write (RTC_MONTH, bin2bcd(tmp->tm_mon));
rtc_write (RTC_DAY_OF_WEEK, bin2bcd(tmp->tm_wday));
rtc_write (RTC_DAY_OF_MONTH, bin2bcd(tmp->tm_mday));
rtc_write (RTC_HOURS, bin2bcd(tmp->tm_hour));
rtc_write (RTC_MINUTES, bin2bcd(tmp->tm_min ));
rtc_write (RTC_SECONDS, bin2bcd(tmp->tm_sec ));
save_ctrl_a &= ~RTC_CA_WRITE;
rtc_write(RTC_CONTROLA, save_ctrl_a); /* enables the RTC to update the regs */
}
void rtc_reset (void)
{
uchar control_b;
/*
* Start oscillator here.
*/
control_b = rtc_read(RTC_CONTROLB);
control_b &= ~RTC_CB_STOP;
rtc_write(RTC_CONTROLB, control_b);
}
void rtc_set_watchdog(short multi, short res)
{
uchar wd_value;
wd_value = RTC_WDS | ((multi & 0x1F) << 2) | (res & 0x3);
rtc_write(RTC_WATCHDOG, wd_value);
}
#endif /* (CONFIG_COMMANDS & CFG_CMD_DATE) */
#endif /* CONFIG_RTC_MK48T59 */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册