From 9dc67828a9906498a16fd4ad55ae5319cc934dd1 Mon Sep 17 00:00:00 2001 From: Robert Kukla Date: Sun, 3 Feb 2008 18:15:39 +0000 Subject: mrobe 100: real time clock (if anybody recognises the RTC chip let me know) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16208 a1c6a512-1295-4272-9138-f99709370657 --- firmware/SOURCES | 5 +- firmware/drivers/rtc/rtc_mr100.c | 114 ++++++++ firmware/drivers/sw_i2c.c | 301 +++++++++++++++++++++ firmware/export/config-mrobe100.h | 2 +- firmware/export/config.h | 1 + firmware/export/sw_i2c.h | 4 +- firmware/target/coldfire/iriver/h100/sw_i2c-h100.c | 269 ------------------ 7 files changed, 423 insertions(+), 273 deletions(-) create mode 100644 firmware/drivers/rtc/rtc_mr100.c create mode 100644 firmware/drivers/sw_i2c.c delete mode 100644 firmware/target/coldfire/iriver/h100/sw_i2c-h100.c diff --git a/firmware/SOURCES b/firmware/SOURCES index eaa4cb32cb..9330576145 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -148,6 +148,8 @@ drivers/rtc/rtc_s3c2440.c drivers/rtc/rtc_as3514.c #elif (CONFIG_RTC == RTC_RX5X348AB) drivers/rtc/rtc_rx5x348ab.c +#elif (CONFIG_RTC == RTC_MR100) +drivers/rtc/rtc_mr100.c #endif /* (CONFIG_RTC == RTC_) */ #endif /* SIMULATOR */ @@ -523,12 +525,12 @@ target/coldfire/iriver/audio-iriver.c #ifdef IRIVER_H100_SERIES #ifndef SIMULATOR +drivers/sw_i2c.c target/coldfire/ata-as-coldfire.S target/coldfire/iriver/ata-iriver.c target/coldfire/iriver/lcd-remote-iriver.c target/coldfire/iriver/system-iriver.c target/coldfire/iriver/fmradio_i2c-iriver.c -target/coldfire/iriver/h100/sw_i2c-h100.c target/coldfire/iriver/h100/adc-h100.c target/coldfire/iriver/h100/backlight-h100.c target/coldfire/iriver/h100/button-h100.c @@ -661,6 +663,7 @@ target/arm/tms320dm320/dsp-dm320.c #ifdef MROBE_100 #ifndef SIMULATOR +drivers/sw_i2c.c target/arm/ata-as-arm.S target/arm/ata-pp5020.c target/arm/wmcodec-pp.c diff --git a/firmware/drivers/rtc/rtc_mr100.c b/firmware/drivers/rtc/rtc_mr100.c new file mode 100644 index 0000000000..96d84156a7 --- /dev/null +++ b/firmware/drivers/rtc/rtc_mr100.c @@ -0,0 +1,114 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 by Robert Kukla + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "rtc.h" +#include "logf.h" +#include "sw_i2c.h" +#include "i2c-pp.h" + +/* The RTC chip is unknown, the information about it was gathered by + * reverse engineering the bootloader. + */ + +#define RTC_ADDR 0x60 + +#define RTC_CMD_CTRL 0 /* OF uses it with single byte 1 or 2 */ +#define RTC_CMD_UNKN 1 /* OF uses it with single byte 8 */ +#define RTC_CMD_DATA 2 +#define RTC_CMD_TEST 7 /* OF uses it with single byte 0xAA */ + +/* private */ + +static void reverse_bits(unsigned char* v, int size) { + + int i,j,in,out=0; + + for(j=0; j>1; + out = out<<1; + } + v[j] = out>>1; + } +} + +static int sw_i2c(int access, unsigned char chip, unsigned char cmd, + unsigned char* buf, int count) { + int i; + + i2c_lock(); + GPIOC_ENABLE |= 0x00000030; + + chip|=cmd<<1; + + if(access == SW_I2C_READ) { + i = sw_i2c_read(chip, 0, buf, count); + reverse_bits(buf, count); + } else { + reverse_bits(buf, count); + i = sw_i2c_write(chip, 0, buf, count); + } + + GPIOC_ENABLE &= ~0x00000030; + i2c_unlock(); + + return i; +} + +/* public */ + +void rtc_init(void) +{ + sw_i2c_init(); + + /* to set a time while buttons are stil not working + unsigned char v[7] = {0x00,0x47,0x17,0x06,0x03,0x02,0x08}; + rtc_write_datetime(v); + */ +} + +int rtc_read_datetime(unsigned char* buf) +{ + int i; + unsigned char v[7]; + + i = sw_i2c(SW_I2C_READ, RTC_ADDR, RTC_CMD_DATA, v, 7); + + v[4] &= 0x3f; /* mask out p.m. flag */ + + for(i=0; i<7; i++) + buf[i] = v[6-i]; + + return i; +} + +int rtc_write_datetime(unsigned char* buf) +{ + int i; + unsigned char v[7]; + + for(i=0; i<7; i++) + v[i]=buf[6-i]; + + i = sw_i2c(SW_I2C_WRITE, RTC_ADDR, RTC_CMD_DATA, v, 7); + + return i; +} + diff --git a/firmware/drivers/sw_i2c.c b/firmware/drivers/sw_i2c.c new file mode 100644 index 0000000000..c1f6868226 --- /dev/null +++ b/firmware/drivers/sw_i2c.c @@ -0,0 +1,301 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 by Miika Pekkarinen + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "system.h" +#include "logf.h" +#include "inttypes.h" + +#include "sw_i2c.h" + +/** + * I2C-functions are copied and ported from fmradio.c. + * later fixed, adapted and moved to a seperate file so they can be re-used + * by the rtc-ds1339c and later by the m:robe-100 code by Robert Kukla + */ + +/* cute little functions, atomic read-modify-write */ + +#ifdef MROBE_100 + +/* SCL is GPIOC, 4 */ +#define SCL (GPIOC_INPUT_VAL & 0x00000010) +#define SCL_OUT_LO GPIOC_OUTPUT_VAL&=~0x00000010 +#define SCL_LO GPIOC_OUTPUT_EN |= 0x00000010 +#define SCL_HI GPIOC_OUTPUT_EN &=~0x00000010 + +/* SDA is GPIOC, 5 */ +#define SDA (GPIOC_INPUT_VAL & 0x00000020) +#define SDA_OUT_LO GPIOC_OUTPUT_VAL&=~0x00000020 +#define SDA_LO GPIOC_OUTPUT_EN |= 0x00000020 +#define SDA_HI GPIOC_OUTPUT_EN &=~0x00000020 + +#define DELAY do { volatile int _x; for(_x=0;_x<22;_x++);} while(0) + +#else + +/* SCL is GPIO, 12 */ +#define SCL ( 0x00001000 & GPIO_READ) +#define SCL_OUT_LO and_l(~0x00001000, &GPIO_OUT) +#define SCL_LO or_l( 0x00001000, &GPIO_ENABLE) +#define SCL_HI and_l(~0x00001000, &GPIO_ENABLE) + +/* SDA is GPIO1, 13 */ +#define SDA ( 0x00002000 & GPIO1_READ) +#define SDA_OUT_LO and_l(~0x00002000, &GPIO1_OUT) +#define SDA_LO or_l( 0x00002000, &GPIO1_ENABLE) +#define SDA_HI and_l(~0x00002000, &GPIO1_ENABLE) + +/* delay loop to achieve 400kHz at 120MHz CPU frequency */ +#define DELAY \ + ({ \ + int _x_; \ + asm volatile ( \ + "move.l #21, %[_x_] \r\n" \ + "1: \r\n" \ + "subq.l #1, %[_x_] \r\n" \ + "bhi.b 1b \r\n" \ + : [_x_]"=&d"(_x_) \ + ); \ + }) + +#endif + +void sw_i2c_init(void) +{ +#ifndef MROBE_100 + or_l(0x00001000, &GPIO_FUNCTION); + or_l(0x00002000, &GPIO1_FUNCTION); +#endif + + SDA_HI; + SCL_HI; + SDA_OUT_LO; + SCL_OUT_LO; +} + +/* in: C=? D=? + * out: C=L D=L + */ +static void sw_i2c_start(void) +{ + SCL_LO; + DELAY; + SDA_HI; + DELAY; + SCL_HI; + DELAY; + SDA_LO; + DELAY; + SCL_LO; +} + +/* in: C=L D=? + * out: C=H D=H + */ +static void sw_i2c_stop(void) +{ + SDA_LO; + DELAY; + SCL_HI; + DELAY; + SDA_HI; +} + +/* in: C=L D=H + * out: C=L D=L + */ +static void sw_i2c_ack(void) +{ + SDA_LO; + DELAY; + + SCL_HI; + DELAY; + SCL_LO; +} + +/* in: C=L D=H + * out: C=L D=H + */ +static void sw_i2c_nack(void) +{ + SDA_HI; /* redundant */ + DELAY; + + SCL_HI; + DELAY; + SCL_LO; +} + +/* in: C=L D=? + * out: C=L D=H + */ +static bool sw_i2c_getack(void) +{ + bool ret = true; +/* int count = 10; */ + + SDA_HI; /* sets to input */ + DELAY; + SCL_HI; + DELAY; + +/* while (SDA && count--) */ +/* DELAY; */ + + if (SDA) + /* ack failed */ + ret = false; + + SCL_LO; + + return ret; +} + +/* in: C=L D=? + * out: C=L D=? + */ +static void sw_i2c_outb(unsigned char byte) +{ + int i; + + /* clock out each bit, MSB first */ + for ( i=0x80; i; i>>=1 ) + { + if ( i & byte ) + SDA_HI; + else + SDA_LO; + DELAY; + + SCL_HI; + DELAY; + SCL_LO; + } +} + +/* in: C=L D=? + * out: C=L D=H + */ +static unsigned char sw_i2c_inb(void) +{ + int i; + unsigned char byte = 0; + + SDA_HI; /* sets to input */ + + /* clock in each bit, MSB first */ + for ( i=0x80; i; i>>=1 ) + { + DELAY; + do { + SCL_HI; + DELAY; + } + while(SCL==0); /* wait for any SCL clock stretching */ + if ( SDA ) + byte |= i; + SCL_LO; + } + + return byte; +} + +int sw_i2c_write(unsigned char chip, unsigned char location, unsigned char* buf, int count) +{ + int i; + + sw_i2c_start(); + sw_i2c_outb((chip & 0xfe) | SW_I2C_WRITE); + if (!sw_i2c_getack()) + { + sw_i2c_stop(); + return -1; + } + +#ifdef MROBE_100 /* does not use register addressing */ + (void) location; +#else + sw_i2c_outb(location); + if (!sw_i2c_getack()) + { + sw_i2c_stop(); + return -2; + } +#endif + + for (i=0; i ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 by Miika Pekkarinen - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "system.h" -#include "logf.h" -#include "inttypes.h" - -#include "sw_i2c.h" - -/** - * I2C-functions are copied and ported from fmradio.c. - * later fixed, adapted and moved to a seperate file so they can be re-used by the rtc-ds1339c code by Robert Kukla - */ - -/* cute little functions, atomic read-modify-write */ - -/* SCL is GPIO, 12 */ -#define SCL ( 0x00001000 & GPIO_READ) -#define SCL_OUT_LO and_l(~0x00001000, &GPIO_OUT) -#define SCL_LO or_l( 0x00001000, &GPIO_ENABLE) -#define SCL_HI and_l(~0x00001000, &GPIO_ENABLE) - -/* SDA is GPIO1, 13 */ -#define SDA ( 0x00002000 & GPIO1_READ) -#define SDA_OUT_LO and_l(~0x00002000, &GPIO1_OUT) -#define SDA_LO or_l( 0x00002000, &GPIO1_ENABLE) -#define SDA_HI and_l(~0x00002000, &GPIO1_ENABLE) - -/* delay loop to achieve 400kHz at 120MHz CPU frequency */ -#define DELAY \ - ({ \ - int _x_; \ - asm volatile ( \ - "move.l #21, %[_x_] \r\n" \ - "1: \r\n" \ - "subq.l #1, %[_x_] \r\n" \ - "bhi.b 1b \r\n" \ - : [_x_]"=&d"(_x_) \ - ); \ - }) - -void sw_i2c_init(void) -{ - or_l(0x00001000, &GPIO_FUNCTION); - or_l(0x00002000, &GPIO1_FUNCTION); - SDA_HI; - SCL_HI; - SDA_OUT_LO; - SCL_OUT_LO; -} - -/* in: C=? D=? - * out: C=L D=L - */ -static void sw_i2c_start(void) -{ - SCL_LO; - DELAY; - SDA_HI; - DELAY; - SCL_HI; - DELAY; - SDA_LO; - DELAY; - SCL_LO; -} - -/* in: C=L D=? - * out: C=H D=H - */ -static void sw_i2c_stop(void) -{ - SDA_LO; - DELAY; - SCL_HI; - DELAY; - SDA_HI; -} - -/* in: C=L D=H - * out: C=L D=L - */ -static void sw_i2c_ack(void) -{ - SDA_LO; - DELAY; - - SCL_HI; - DELAY; - SCL_LO; -} - -/* in: C=L D=H - * out: C=L D=H - */ -static void sw_i2c_nack(void) -{ - SDA_HI; /* redundant */ - DELAY; - - SCL_HI; - DELAY; - SCL_LO; -} - -/* in: C=L D=? - * out: C=L D=H - */ -static bool sw_i2c_getack(void) -{ - bool ret = true; -/* int count = 10; */ - - SDA_HI; /* sets to input */ - DELAY; - SCL_HI; - DELAY; - -/* while (SDA && count--) */ -/* DELAY; */ - - if (SDA) - /* ack failed */ - ret = false; - - SCL_LO; - - return ret; -} - -/* in: C=L D=? - * out: C=L D=? - */ -static void sw_i2c_outb(unsigned char byte) -{ - int i; - - /* clock out each bit, MSB first */ - for ( i=0x80; i; i>>=1 ) - { - if ( i & byte ) - SDA_HI; - else - SDA_LO; - DELAY; - - SCL_HI; - DELAY; - SCL_LO; - } -} - -/* in: C=L D=? - * out: C=L D=H - */ -static unsigned char sw_i2c_inb(void) -{ - int i; - unsigned char byte = 0; - - SDA_HI; /* sets to input */ - - /* clock in each bit, MSB first */ - for ( i=0x80; i; i>>=1 ) - { - DELAY; - do { - SCL_HI; - DELAY; - } - while(SCL==0); /* wait for any SCL clock stretching */ - if ( SDA ) - byte |= i; - SCL_LO; - } - - return byte; -} - -int sw_i2c_write(unsigned char chip, unsigned char location, const unsigned char* buf, int count) -{ - int i; - - sw_i2c_start(); - sw_i2c_outb((chip & 0xfe) | SW_I2C_WRITE); - if (!sw_i2c_getack()) - { - sw_i2c_stop(); - return -1; - } - - sw_i2c_outb(location); - if (!sw_i2c_getack()) - { - sw_i2c_stop(); - return -2; - } - - for (i=0; i