/****************************************/ /* MES/Copyleft Yukio Mituiwa,2007 */ /* */ /* 2007/6/1 first release */ /* */ /****************************************/ #include #ifdef _KERNEL_ #include "mes.h" #include "conf.h" #define device_main(arg1,arg2) init_rtc(void) extern PIOConf rtc_config[]; #endif typedef struct { IOREG *regptr; int port, offset; unsigned char bits[2]; } RTCConf; #define RTCNUM 1 static RTCConf rtc[RTCNUM]; #define SCL (rtc[minor].bits[0]) #define SDA (rtc[minor].bits[1]) #define DATAREG *(rtc[minor].regptr) #define RTC_WRITE 0xa2 #define RTC_READ 0xa3 #define NAK SDA static void _wait() { volatile int w; #if defined(__H8300H__) w = 0; #endif #if defined(__sh__) for(w = 0;w < 2;w++); #endif } static void rtc_start(int minor) { ddr_set(rtc[minor].port, SDA); DATAREG &= ~SCL; DATAREG |= SDA; _wait(); DATAREG |= SCL; DATAREG &= ~SDA; _wait(); DATAREG &= ~SCL; ddr_reset(rtc[minor].port, SDA); } static void rtc_stop(int minor) { ddr_set(rtc[minor].port, SDA); DATAREG &= ~SCL; DATAREG &= ~SDA; _wait(); DATAREG |= SCL; DATAREG |= SDA; _wait(); DATAREG &= ~SCL; ddr_reset(rtc[minor].port, SDA); } static int rtc_write(int minor, int data) { int i, mask; ddr_set(rtc[minor].port, SDA); mask = 0x80; for(i = 0;i < 8;i++) { if(data & mask) DATAREG |= SDA; else DATAREG &= ~SDA; DATAREG |= SCL; _wait(); DATAREG &= ~SCL; mask >>= 1; _wait(); } ddr_reset(rtc[minor].port, SDA); DATAREG |= SCL; _wait(); i = DATAREG & SDA; DATAREG &= ~SCL; return i; } static int rtc_read(int minor) { int i, data; data = 0; for(i = 0;i < 8;i++) { data <<= 1; DATAREG |= SCL; if(DATAREG & SDA) data++; _wait(); DATAREG &= ~SCL; _wait(); } return data; } static void rtc_ack(int minor) { ddr_set(rtc[minor].port, SDA); DATAREG &= ~SDA; DATAREG |= SCL; _wait(); DATAREG &= ~SCL; ddr_reset(rtc[minor].port, SDA); } static void rtc_nak(int minor) { ddr_set(rtc[minor].port, SDA); DATAREG |= SDA; DATAREG |= SCL; _wait(); DATAREG &= ~SCL; DATAREG &= ~SDA; ddr_reset(rtc[minor].port, SDA); } static int send_ctrl(int minor, int ctrl) { int ret, count = 0; do { rtc_start(minor); ret = rtc_write(minor, ctrl); if(count++ > 1000) return -1; } while(ret == NAK); return 0; } static int write_rtc(int minor, char *src, int size) { int ret; if(minor >= RTCNUM) return -1; ret = send_ctrl(minor, RTC_WRITE); if(ret == -1) return -1; ret = rtc_write(minor, rtc[minor].offset); if(ret == -1) return -1; ret = rtc_write(minor, *src); if(ret == -1) return -1; rtc_stop(minor); if(++rtc[minor].offset > 8) rtc[minor].offset = 0; return 1; } static int read_rtc(int minor, char *dest, int size) { int data, ret; if(minor >= RTCNUM) return -1; ret = send_ctrl(minor, RTC_WRITE); if(ret == -1) return -1; ret = rtc_write(minor, rtc[minor].offset); if(ret == -1) return -1; ret = send_ctrl(minor, RTC_READ); if(ret == -1) return -1; data = rtc_read(minor); *dest = data; rtc_nak(minor); rtc_stop(minor); if(++rtc[minor].offset > 8) rtc[minor].offset = 0; return 1; } static int open_rtc(int minor, int option) { int port; if(minor >= RTCNUM) return -1; ddr_reset(rtc[minor].port, SDA); ddr_set(rtc[minor].port, SCL); // DATAREG &= ~SCL; return 0; } static int close_rtc(int minor) { if(minor >= RTCNUM) return -1; return 0; } static int seek_rtc(int minor, int pos) { if(minor >= RTCNUM) return -1; if(pos > 8) return -1; rtc[minor].offset = pos; return 0; } static int ioctl_rtc(int minor, int data, int op) { int ret; if(minor >= RTCNUM) return -1; ret = 0; switch(op) { case DEV_INFO: break; default: ret = -1; } return ret; } static Functions func; int device_main(int argc, char **argv) { unsigned int minor, n; #ifndef _KERNEL_ minor = 0; for(n = 1;n < argc;n++) { if(memcmp(argv[n], "rtc", 3) == 0) { minor = stoi(&argv[n][3]); if(minor >= RTCNUM) minor = 0; } else if(memcmp(argv[n], "p=", 2) == 0) { rtc[minor].port = stoi(&argv[n][2]); } else if(memcmp(argv[n], "clk=", 4) == 0) { rtc[minor].bits[0] = 1 << stoi(&argv[n][4]); } else if(memcmp(argv[n], "dat=", 4) == 0) { rtc[minor].bits[1] = 1 << stoi(&argv[n][4]); } } #endif for(minor = 0;minor < RTCNUM;minor++) { #ifdef _KERNEL_ rtc[minor].port = rtc_config[minor].port; rtc[minor].bits[0] = 1 << rtc_config[minor].bits[1]; rtc[minor].bits[1] = 1 << rtc_config[minor].bits[3]; #endif rtc[minor].regptr = get_dr(rtc[minor].port); rtc[minor].offset = 0; } func.open_dev = open_rtc; func.close_dev = close_rtc; func.write_dev = write_rtc; func.read_dev = read_rtc; func.seek_dev = seek_rtc; func.ioctl_dev = ioctl_rtc; func.poll_dev = 0; strcpy(&(func.name[0]), "rtc"); device_return(&func); }