Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
0004  *
0005  * Adapted for PowerPC (PReP) by Gary Thomas
0006  * Modified by Cort Dougan (cort@cs.nmt.edu).
0007  * Copied and modified from arch/i386/kernel/time.c
0008  *
0009  */
0010 #include <linux/errno.h>
0011 #include <linux/sched.h>
0012 #include <linux/kernel.h>
0013 #include <linux/param.h>
0014 #include <linux/string.h>
0015 #include <linux/mm.h>
0016 #include <linux/interrupt.h>
0017 #include <linux/time.h>
0018 #include <linux/timex.h>
0019 #include <linux/kernel_stat.h>
0020 #include <linux/mc146818rtc.h>
0021 #include <linux/init.h>
0022 #include <linux/bcd.h>
0023 #include <linux/ioport.h>
0024 #include <linux/of_address.h>
0025 
0026 #include <asm/io.h>
0027 #include <asm/nvram.h>
0028 #include <asm/sections.h>
0029 #include <asm/time.h>
0030 
0031 #include <platforms/chrp/chrp.h>
0032 
0033 #define NVRAM_AS0  0x74
0034 #define NVRAM_AS1  0x75
0035 #define NVRAM_DATA 0x77
0036 
0037 static int nvram_as1 = NVRAM_AS1;
0038 static int nvram_as0 = NVRAM_AS0;
0039 static int nvram_data = NVRAM_DATA;
0040 
0041 long __init chrp_time_init(void)
0042 {
0043     struct device_node *rtcs;
0044     struct resource r;
0045     int base;
0046 
0047     rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00");
0048     if (rtcs == NULL)
0049         rtcs = of_find_compatible_node(NULL, "rtc", "ds1385-rtc");
0050     if (rtcs == NULL)
0051         return 0;
0052     if (of_address_to_resource(rtcs, 0, &r)) {
0053         of_node_put(rtcs);
0054         return 0;
0055     }
0056     of_node_put(rtcs);
0057 
0058     base = r.start;
0059     nvram_as1 = 0;
0060     nvram_as0 = base;
0061     nvram_data = base + 1;
0062 
0063     return 0;
0064 }
0065 
0066 static int chrp_cmos_clock_read(int addr)
0067 {
0068     if (nvram_as1 != 0)
0069         outb(addr>>8, nvram_as1);
0070     outb(addr, nvram_as0);
0071     return (inb(nvram_data));
0072 }
0073 
0074 static void chrp_cmos_clock_write(unsigned long val, int addr)
0075 {
0076     if (nvram_as1 != 0)
0077         outb(addr>>8, nvram_as1);
0078     outb(addr, nvram_as0);
0079     outb(val, nvram_data);
0080     return;
0081 }
0082 
0083 /*
0084  * Set the hardware clock. -- Cort
0085  */
0086 int chrp_set_rtc_time(struct rtc_time *tmarg)
0087 {
0088     unsigned char save_control, save_freq_select;
0089     struct rtc_time tm = *tmarg;
0090 
0091     spin_lock(&rtc_lock);
0092 
0093     save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
0094 
0095     chrp_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);
0096 
0097     save_freq_select = chrp_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
0098 
0099     chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
0100 
0101     if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
0102         tm.tm_sec = bin2bcd(tm.tm_sec);
0103         tm.tm_min = bin2bcd(tm.tm_min);
0104         tm.tm_hour = bin2bcd(tm.tm_hour);
0105         tm.tm_mon = bin2bcd(tm.tm_mon);
0106         tm.tm_mday = bin2bcd(tm.tm_mday);
0107         tm.tm_year = bin2bcd(tm.tm_year);
0108     }
0109     chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
0110     chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES);
0111     chrp_cmos_clock_write(tm.tm_hour,RTC_HOURS);
0112     chrp_cmos_clock_write(tm.tm_mon,RTC_MONTH);
0113     chrp_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);
0114     chrp_cmos_clock_write(tm.tm_year,RTC_YEAR);
0115 
0116     /* The following flags have to be released exactly in this order,
0117      * otherwise the DS12887 (popular MC146818A clone with integrated
0118      * battery and quartz) will not reset the oscillator and will not
0119      * update precisely 500 ms later. You won't find this mentioned in
0120      * the Dallas Semiconductor data sheets, but who believes data
0121      * sheets anyway ...                           -- Markus Kuhn
0122      */
0123     chrp_cmos_clock_write(save_control, RTC_CONTROL);
0124     chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
0125 
0126     spin_unlock(&rtc_lock);
0127     return 0;
0128 }
0129 
0130 void chrp_get_rtc_time(struct rtc_time *tm)
0131 {
0132     unsigned int year, mon, day, hour, min, sec;
0133 
0134     do {
0135         sec = chrp_cmos_clock_read(RTC_SECONDS);
0136         min = chrp_cmos_clock_read(RTC_MINUTES);
0137         hour = chrp_cmos_clock_read(RTC_HOURS);
0138         day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
0139         mon = chrp_cmos_clock_read(RTC_MONTH);
0140         year = chrp_cmos_clock_read(RTC_YEAR);
0141     } while (sec != chrp_cmos_clock_read(RTC_SECONDS));
0142 
0143     if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
0144         sec = bcd2bin(sec);
0145         min = bcd2bin(min);
0146         hour = bcd2bin(hour);
0147         day = bcd2bin(day);
0148         mon = bcd2bin(mon);
0149         year = bcd2bin(year);
0150     }
0151     if (year < 70)
0152         year += 100;
0153     tm->tm_sec = sec;
0154     tm->tm_min = min;
0155     tm->tm_hour = hour;
0156     tm->tm_mday = day;
0157     tm->tm_mon = mon;
0158     tm->tm_year = year;
0159 }