Commit f81f88f4 authored by Tom Rini's avatar Tom Rini

PPC32: Add and make use of ppc_md.rtc_{read,write}_val.

We can then fix IBM PReP machines and their RTCs.
parent 2130835d
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/mc146818rtc.h>
#include <asm/mk48t59.h> #include <asm/mk48t59.h>
#include <asm/prep_nvram.h> #include <asm/prep_nvram.h>
#include <asm/raven.h> #include <asm/raven.h>
...@@ -1023,8 +1024,10 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -1023,8 +1024,10 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.time_init = todc_time_init; ppc_md.time_init = todc_time_init;
if (_prep_type == _PREP_IBM) { if (_prep_type == _PREP_IBM) {
TODC_INIT(TODC_TYPE_MC146818, PREP_NVRAM_AS0, PREP_NVRAM_AS1, ppc_md.rtc_read_val = todc_mc146818_read_val;
PREP_NVRAM_DATA, 8); ppc_md.rtc_write_val = todc_mc146818_write_val;
TODC_INIT(TODC_TYPE_MC146818, RTC_PORT(0), NULL, RTC_PORT(1),
8);
} else { } else {
TODC_INIT(TODC_TYPE_MK48T59, PREP_NVRAM_AS0, PREP_NVRAM_AS1, TODC_INIT(TODC_TYPE_MK48T59, PREP_NVRAM_AS0, PREP_NVRAM_AS1,
PREP_NVRAM_DATA, 8); PREP_NVRAM_DATA, 8);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Author: Mark A. Greer * Author: Mark A. Greer
* mgreer@mvista.com * mgreer@mvista.com
* *
* 2001 (c) MontaVista, Software, Inc. This file is licensed under * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program * the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express * is licensed "as is" without any warranty of any kind, whether express
* or implied. * or implied.
...@@ -31,15 +31,13 @@ ...@@ -31,15 +31,13 @@
* 'nvram_data' to the base address of your nvram and leave 'nvram_as0' and * 'nvram_data' to the base address of your nvram and leave 'nvram_as0' and
* 'nvram_as1' NULL. If your board uses address/data regs to access nvram, * 'nvram_as1' NULL. If your board uses address/data regs to access nvram,
* set 'nvram_as0' to the address of the lower byte, set 'nvram_as1' to the * set 'nvram_as0' to the address of the lower byte, set 'nvram_as1' to the
* address of the upper byte (leave NULL if using mv146818), and set * address of the upper byte (leave NULL if using mc146818), and set
* 'nvram_data' to the address of the 8-bit data register. * 'nvram_data' to the address of the 8-bit data register.
* *
* You also need to set 'ppc_md.nvram_read_val' and 'ppc_md.nvram_write_val' to * In order to break the assumption that the RTC and NVRAM are accessed by
* the proper routines. There are standard ones defined further down in * the same mechanism, you need to explicitly set 'ppc_md.rtc_read_val' and
* this file that you can use. * 'ppc_md.rtc_write_val', otherwise the values of 'ppc_md.rtc_read_val'
* * and 'ppc_md.rtc_write_val' will be used.
* There is a built in assumption that the RTC and NVRAM are accessed by the
* same mechanism (i.e., ppc_md.nvram_read_val, etc works for both).
* *
* Note: Even though the documentation for the various RTC chips say that it * Note: Even though the documentation for the various RTC chips say that it
* take up to a second before it starts updating once the 'R' bit is * take up to a second before it starts updating once the 'R' bit is
...@@ -116,16 +114,15 @@ todc_m48txx_write_val(int addr, unsigned char val) ...@@ -116,16 +114,15 @@ todc_m48txx_write_val(int addr, unsigned char val)
u_char u_char
todc_mc146818_read_val(int addr) todc_mc146818_read_val(int addr)
{ {
outb(addr, todc_info->nvram_as0); outb_p(addr, todc_info->nvram_as0);
return inb(todc_info->nvram_data); return inb_p(todc_info->nvram_data);
} }
void void
todc_mc146818_write_val(int addr, unsigned char val) todc_mc146818_write_val(int addr, unsigned char val)
{ {
outb(addr, todc_info->nvram_as0); outb_p(addr, todc_info->nvram_as0);
outb(val, todc_info->nvram_data); outb_p(val, todc_info->nvram_data);
return;
} }
...@@ -143,16 +140,16 @@ todc_read_val(int addr) ...@@ -143,16 +140,16 @@ todc_read_val(int addr)
if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) { if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
if (addr < todc_info->nvram_size) { /* NVRAM */ if (addr < todc_info->nvram_size) { /* NVRAM */
ppc_md.nvram_write_val(todc_info->nvram_addr_reg, addr); ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
val = ppc_md.nvram_read_val(todc_info->nvram_data_reg); val = ppc_md.rtc_read_val(todc_info->nvram_data_reg);
} }
else { /* Clock Reg */ else { /* Clock Reg */
addr -= todc_info->nvram_size; addr -= todc_info->nvram_size;
val = ppc_md.nvram_read_val(addr); val = ppc_md.rtc_read_val(addr);
} }
} }
else { else {
val = ppc_md.nvram_read_val(addr); val = ppc_md.rtc_read_val(addr);
} }
return val; return val;
...@@ -163,16 +160,16 @@ todc_write_val(int addr, u_char val) ...@@ -163,16 +160,16 @@ todc_write_val(int addr, u_char val)
{ {
if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) { if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) {
if (addr < todc_info->nvram_size) { /* NVRAM */ if (addr < todc_info->nvram_size) { /* NVRAM */
ppc_md.nvram_write_val(todc_info->nvram_addr_reg, addr); ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr);
ppc_md.nvram_write_val(todc_info->nvram_data_reg, val); ppc_md.rtc_write_val(todc_info->nvram_data_reg, val);
} }
else { /* Clock Reg */ else { /* Clock Reg */
addr -= todc_info->nvram_size; addr -= todc_info->nvram_size;
ppc_md.nvram_write_val(addr, val); ppc_md.rtc_write_val(addr, val);
} }
} }
else { else {
ppc_md.nvram_write_val(addr, val); ppc_md.rtc_write_val(addr, val);
} }
} }
...@@ -192,86 +189,80 @@ todc_write_val(int addr, u_char val) ...@@ -192,86 +189,80 @@ todc_write_val(int addr, u_char val)
long __init long __init
todc_time_init(void) todc_time_init(void)
{ {
static u_char not_initialized = 1; u_char cntl_b;
/* Make sure clocks are running */ if (!ppc_md.rtc_read_val)
if (not_initialized) { ppc_md.rtc_read_val = ppc_md.nvram_read_val;
u_char cntl_b; if (!ppc_md.rtc_write_val)
ppc_md.rtc_write_val = ppc_md.nvram_write_val;
cntl_b = todc_read_val(todc_info->control_b);
cntl_b = todc_read_val(todc_info->control_b); if (todc_info->rtc_type == TODC_TYPE_MC146818) {
if ((cntl_b & 0x70) != 0x20) {
if (todc_info->rtc_type == TODC_TYPE_MC146818) { printk(KERN_INFO "TODC %s %s\n",
if ((cntl_b & 0x70) != 0x20) { "real-time-clock was stopped.",
printk(KERN_INFO "TODC %s %s\n", "Now starting...");
"real-time-clock was stopped.", cntl_b &= ~0x70;
"Now starting..."); cntl_b |= 0x20;
cntl_b &= ~0x70;
cntl_b |= 0x20;
}
todc_write_val(todc_info->control_b, cntl_b);
} }
else if (todc_info->rtc_type == TODC_TYPE_DS17285) {
u_char mode;
mode = todc_read_val(TODC_TYPE_DS17285_CNTL_A); todc_write_val(todc_info->control_b, cntl_b);
/* Make sure countdown clear is not set */ } else if (todc_info->rtc_type == TODC_TYPE_DS17285) {
mode &= ~0x40; u_char mode;
/* Enable oscillator, extended register set */
mode |= 0x30;
todc_write_val(TODC_TYPE_DS17285_CNTL_A, mode);
} mode = todc_read_val(TODC_TYPE_DS17285_CNTL_A);
else if (todc_info->rtc_type == TODC_TYPE_DS1501) { /* Make sure countdown clear is not set */
u_char month; mode &= ~0x40;
/* Enable oscillator, extended register set */
mode |= 0x30;
todc_write_val(TODC_TYPE_DS17285_CNTL_A, mode);
todc_info->enable_read = TODC_DS1501_CNTL_B_TE; } else if (todc_info->rtc_type == TODC_TYPE_DS1501) {
todc_info->enable_write = TODC_DS1501_CNTL_B_TE; u_char month;
month = todc_read_val(todc_info->month); todc_info->enable_read = TODC_DS1501_CNTL_B_TE;
todc_info->enable_write = TODC_DS1501_CNTL_B_TE;
if ((month & 0x80) == 0x80) { month = todc_read_val(todc_info->month);
printk(KERN_INFO "TODC %s %s\n",
"real-time-clock was stopped.",
"Now starting...");
month &= ~0x80;
todc_write_val(todc_info->month, month);
}
cntl_b &= ~TODC_DS1501_CNTL_B_TE; if ((month & 0x80) == 0x80) {
todc_write_val(todc_info->control_b, cntl_b); printk(KERN_INFO "TODC %s %s\n",
"real-time-clock was stopped.",
"Now starting...");
month &= ~0x80;
todc_write_val(todc_info->month, month);
} }
else { /* must be a m48txx type */
u_char cntl_a;
todc_info->enable_read = TODC_MK48TXX_CNTL_A_R; cntl_b &= ~TODC_DS1501_CNTL_B_TE;
todc_info->enable_write = TODC_MK48TXX_CNTL_A_W; todc_write_val(todc_info->control_b, cntl_b);
} else { /* must be a m48txx type */
u_char cntl_a;
cntl_a = todc_read_val(todc_info->control_a); todc_info->enable_read = TODC_MK48TXX_CNTL_A_R;
todc_info->enable_write = TODC_MK48TXX_CNTL_A_W;
/* Check & clear STOP bit in control B register */ cntl_a = todc_read_val(todc_info->control_a);
if (cntl_b & TODC_MK48TXX_DAY_CB) {
printk(KERN_INFO "TODC %s %s\n",
"real-time-clock was stopped.",
"Now starting...");
cntl_a |= todc_info->enable_write; /* Check & clear STOP bit in control B register */
cntl_b &= ~TODC_MK48TXX_DAY_CB;/* Start Oscil */ if (cntl_b & TODC_MK48TXX_DAY_CB) {
printk(KERN_INFO "TODC %s %s\n",
"real-time-clock was stopped.",
"Now starting...");
todc_write_val(todc_info->control_a, cntl_a); cntl_a |= todc_info->enable_write;
todc_write_val(todc_info->control_b, cntl_b); cntl_b &= ~TODC_MK48TXX_DAY_CB;/* Start Oscil */
}
/* Make sure READ & WRITE bits are cleared. */
cntl_a &= ~(todc_info->enable_write |
todc_info->enable_read);
todc_write_val(todc_info->control_a, cntl_a); todc_write_val(todc_info->control_a, cntl_a);
todc_write_val(todc_info->control_b, cntl_b);
} }
not_initialized = 0; /* Make sure READ & WRITE bits are cleared. */
cntl_a &= ~(todc_info->enable_write |
todc_info->enable_read);
todc_write_val(todc_info->control_a, cntl_a);
} }
return 0; return 0;
} }
......
...@@ -43,6 +43,8 @@ struct machdep_calls { ...@@ -43,6 +43,8 @@ struct machdep_calls {
long (*time_init)(void); /* Optional, may be NULL */ long (*time_init)(void); /* Optional, may be NULL */
int (*set_rtc_time)(unsigned long nowtime); int (*set_rtc_time)(unsigned long nowtime);
unsigned long (*get_rtc_time)(void); unsigned long (*get_rtc_time)(void);
unsigned char (*rtc_read_val)(int addr);
void (*rtc_write_val)(int addr, unsigned char val);
void (*calibrate_decr)(void); void (*calibrate_decr)(void);
void (*heartbeat)(void); void (*heartbeat)(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment