📄 rtc_rx5c348.c
字号:
/* * RTC routines for RICOH Rx5C348 SPI chip. * Copyright (C) 2000-2001 Toshiba Corporation * * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the * terms of the GNU General Public License version 2. This program is * licensed "as is" without any warranty of any kind, whether express * or implied. * * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) */#include <linux/init.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/rtc.h>#include <linux/time.h>#include <asm/time.h>#include <asm/tx4938/spi.h>#define EPOCH 2000/* registers */#define Rx5C348_REG_SECOND 0#define Rx5C348_REG_MINUTE 1#define Rx5C348_REG_HOUR 2#define Rx5C348_REG_WEEK 3#define Rx5C348_REG_DAY 4#define Rx5C348_REG_MONTH 5#define Rx5C348_REG_YEAR 6#define Rx5C348_REG_ADJUST 7#define Rx5C348_REG_ALARM_W_MIN 8#define Rx5C348_REG_ALARM_W_HOUR 9#define Rx5C348_REG_ALARM_W_WEEK 10#define Rx5C348_REG_ALARM_D_MIN 11#define Rx5C348_REG_ALARM_D_HOUR 12#define Rx5C348_REG_CTL1 14#define Rx5C348_REG_CTL2 15/* register bits */#define Rx5C348_BIT_PM 0x20 /* REG_HOUR */#define Rx5C348_BIT_Y2K 0x80 /* REG_MONTH */#define Rx5C348_BIT_24H 0x20 /* REG_CTL1 */#define Rx5C348_BIT_XSTP 0x10 /* REG_CTL2 *//* commands */#define Rx5C348_CMD_W(addr) (((addr) << 4) | 0x08) /* single write */#define Rx5C348_CMD_R(addr) (((addr) << 4) | 0x0c) /* single read */#define Rx5C348_CMD_MW(addr) (((addr) << 4) | 0x00) /* burst write */#define Rx5C348_CMD_MR(addr) (((addr) << 4) | 0x04) /* burst read */static struct spi_dev_desc srtc_dev_desc = { .baud = 1000000, /* 1.0Mbps @ Vdd 2.0V */ .tcss = 31, .tcsh = 1, .tcsr = 62, /* 31us for Tcss (62us for Tcsr) is required for carry operation) */ .byteorder = 1, /* MSB-First */ .polarity = 0, /* High-Active */ .phase = 1, /* Shift-Then-Sample */};static int srtc_chipid;static int srtc_24h;static inline intspi_rtc_io(unsigned char *inbuf, unsigned char *outbuf, unsigned int count){ unsigned char *inbufs[1], *outbufs[1]; unsigned int incounts[2], outcounts[2]; inbufs[0] = inbuf; incounts[0] = count; incounts[1] = 0; outbufs[0] = outbuf; outcounts[0] = count; outcounts[1] = 0; return txx9_spi_io(srtc_chipid, &srtc_dev_desc, inbufs, incounts, outbufs, outcounts, 0);}/* * Conversion between binary and BCD. */#ifndef BCD_TO_BIN#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)#endif#ifndef BIN_TO_BCD#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)#endif/* RTC-dependent code for time.c */static intrtc_rx5c348_set_time(unsigned long t){ unsigned char inbuf[8]; struct rtc_time tm; u8 year, month, day, hour, minute, second, century; /* convert */ to_tm(t, &tm); year = tm.tm_year % 100; month = tm.tm_mon+1; /* tm_mon starts from 0 to 11 */ day = tm.tm_mday; hour = tm.tm_hour; minute = tm.tm_min; second = tm.tm_sec; century = tm.tm_year / 100; inbuf[0] = Rx5C348_CMD_MW(Rx5C348_REG_SECOND); BIN_TO_BCD(second); inbuf[1] = second; BIN_TO_BCD(minute); inbuf[2] = minute; if (srtc_24h) { BIN_TO_BCD(hour); inbuf[3] = hour; } else { /* hour 0 is AM12, noon is PM12 */ inbuf[3] = 0; if (hour >= 12) inbuf[3] = Rx5C348_BIT_PM; hour = (hour + 11) % 12 + 1; BIN_TO_BCD(hour); inbuf[3] |= hour; } inbuf[4] = 0; /* ignore week */ BIN_TO_BCD(day); inbuf[5] = day; BIN_TO_BCD(month); inbuf[6] = month; if (century >= 20) inbuf[6] |= Rx5C348_BIT_Y2K; BIN_TO_BCD(year); inbuf[7] = year; /* write in one transfer to avoid data inconsistency */ return spi_rtc_io(inbuf, NULL, 8);}static unsigned longrtc_rx5c348_get_time(void){ unsigned char inbuf[8], outbuf[8]; unsigned int year, month, day, hour, minute, second; inbuf[0] = Rx5C348_CMD_MR(Rx5C348_REG_SECOND); memset(inbuf + 1, 0, 7); /* read in one transfer to avoid data inconsistency */ if (spi_rtc_io(inbuf, outbuf, 8)) return 0; second = outbuf[1]; BCD_TO_BIN(second); minute = outbuf[2]; BCD_TO_BIN(minute); if (srtc_24h) { hour = outbuf[3]; BCD_TO_BIN(hour); } else { hour = outbuf[3] & ~Rx5C348_BIT_PM; BCD_TO_BIN(hour); hour %= 12; if (outbuf[3] & Rx5C348_BIT_PM) hour += 12; } day = outbuf[5]; BCD_TO_BIN(day); month = outbuf[6] & ~Rx5C348_BIT_Y2K; BCD_TO_BIN(month); year = outbuf[7]; BCD_TO_BIN(year); year += EPOCH; return mktime(year, month, day, hour, minute, second);}void __initrtc_rx5c348_init(int chipid){ unsigned char inbuf[2], outbuf[2]; srtc_chipid = chipid; /* turn on RTC if it is not on */ inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL2); inbuf[1] = 0; spi_rtc_io(inbuf, outbuf, 2); if (outbuf[1] & Rx5C348_BIT_XSTP) { inbuf[0] = Rx5C348_CMD_W(Rx5C348_REG_CTL2); inbuf[1] = 0; spi_rtc_io(inbuf, NULL, 2); } inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL1); inbuf[1] = 0; spi_rtc_io(inbuf, outbuf, 2); if (outbuf[1] & Rx5C348_BIT_24H) srtc_24h = 1; /* set the function pointers */ rtc_get_time = rtc_rx5c348_get_time; rtc_set_time = rtc_rx5c348_set_time;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -