Path: blob/master/arch/powerpc/platforms/chrp/time.c
10820 views
/*1* Copyright (C) 1991, 1992, 1995 Linus Torvalds2*3* Adapted for PowerPC (PReP) by Gary Thomas4* Modified by Cort Dougan ([email protected]).5* Copied and modified from arch/i386/kernel/time.c6*7*/8#include <linux/errno.h>9#include <linux/sched.h>10#include <linux/kernel.h>11#include <linux/param.h>12#include <linux/string.h>13#include <linux/mm.h>14#include <linux/interrupt.h>15#include <linux/time.h>16#include <linux/timex.h>17#include <linux/kernel_stat.h>18#include <linux/mc146818rtc.h>19#include <linux/init.h>20#include <linux/bcd.h>21#include <linux/ioport.h>2223#include <asm/io.h>24#include <asm/nvram.h>25#include <asm/prom.h>26#include <asm/sections.h>27#include <asm/time.h>2829extern spinlock_t rtc_lock;3031#define NVRAM_AS0 0x7432#define NVRAM_AS1 0x7533#define NVRAM_DATA 0x773435static int nvram_as1 = NVRAM_AS1;36static int nvram_as0 = NVRAM_AS0;37static int nvram_data = NVRAM_DATA;3839long __init chrp_time_init(void)40{41struct device_node *rtcs;42struct resource r;43int base;4445rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00");46if (rtcs == NULL)47rtcs = of_find_compatible_node(NULL, "rtc", "ds1385-rtc");48if (rtcs == NULL)49return 0;50if (of_address_to_resource(rtcs, 0, &r)) {51of_node_put(rtcs);52return 0;53}54of_node_put(rtcs);5556base = r.start;57nvram_as1 = 0;58nvram_as0 = base;59nvram_data = base + 1;6061return 0;62}6364int chrp_cmos_clock_read(int addr)65{66if (nvram_as1 != 0)67outb(addr>>8, nvram_as1);68outb(addr, nvram_as0);69return (inb(nvram_data));70}7172void chrp_cmos_clock_write(unsigned long val, int addr)73{74if (nvram_as1 != 0)75outb(addr>>8, nvram_as1);76outb(addr, nvram_as0);77outb(val, nvram_data);78return;79}8081/*82* Set the hardware clock. -- Cort83*/84int chrp_set_rtc_time(struct rtc_time *tmarg)85{86unsigned char save_control, save_freq_select;87struct rtc_time tm = *tmarg;8889spin_lock(&rtc_lock);9091save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */9293chrp_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);9495save_freq_select = chrp_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */9697chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);9899if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {100tm.tm_sec = bin2bcd(tm.tm_sec);101tm.tm_min = bin2bcd(tm.tm_min);102tm.tm_hour = bin2bcd(tm.tm_hour);103tm.tm_mon = bin2bcd(tm.tm_mon);104tm.tm_mday = bin2bcd(tm.tm_mday);105tm.tm_year = bin2bcd(tm.tm_year);106}107chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS);108chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES);109chrp_cmos_clock_write(tm.tm_hour,RTC_HOURS);110chrp_cmos_clock_write(tm.tm_mon,RTC_MONTH);111chrp_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);112chrp_cmos_clock_write(tm.tm_year,RTC_YEAR);113114/* The following flags have to be released exactly in this order,115* otherwise the DS12887 (popular MC146818A clone with integrated116* battery and quartz) will not reset the oscillator and will not117* update precisely 500 ms later. You won't find this mentioned in118* the Dallas Semiconductor data sheets, but who believes data119* sheets anyway ... -- Markus Kuhn120*/121chrp_cmos_clock_write(save_control, RTC_CONTROL);122chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);123124spin_unlock(&rtc_lock);125return 0;126}127128void chrp_get_rtc_time(struct rtc_time *tm)129{130unsigned int year, mon, day, hour, min, sec;131132do {133sec = chrp_cmos_clock_read(RTC_SECONDS);134min = chrp_cmos_clock_read(RTC_MINUTES);135hour = chrp_cmos_clock_read(RTC_HOURS);136day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);137mon = chrp_cmos_clock_read(RTC_MONTH);138year = chrp_cmos_clock_read(RTC_YEAR);139} while (sec != chrp_cmos_clock_read(RTC_SECONDS));140141if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {142sec = bcd2bin(sec);143min = bcd2bin(min);144hour = bcd2bin(hour);145day = bcd2bin(day);146mon = bcd2bin(mon);147year = bcd2bin(year);148}149if (year < 70)150year += 100;151tm->tm_sec = sec;152tm->tm_min = min;153tm->tm_hour = hour;154tm->tm_mday = day;155tm->tm_mon = mon;156tm->tm_year = year;157}158159160