summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Kukla <roolku@rockbox.org>2007-02-28 13:20:36 +0000
committerRobert Kukla <roolku@rockbox.org>2007-02-28 13:20:36 +0000
commit50b5ee4781a44234b4ea5dccf3be6ae5ec9fd324 (patch)
treed5197ea90c5dcfa574b84743ecbbd7fa2a754e55
parent343c428f2cf97c82540aecf07d154e43ff40e79a (diff)
downloadrockbox-50b5ee4781a44234b4ea5dccf3be6ae5ec9fd324.tar.gz
rockbox-50b5ee4781a44234b4ea5dccf3be6ae5ec9fd324.zip
FS#6419 - driver for H1x0 series RTC Mod with runtime detection
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12520 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/gui/gwps-common.c7
-rw-r--r--apps/gui/statusbar.c9
-rw-r--r--apps/menus/settings_menu.c30
-rw-r--r--apps/misc.c7
-rw-r--r--apps/plugins/clock.c2
-rw-r--r--apps/recorder/recording.c9
-rw-r--r--apps/scrobbler.c6
-rw-r--r--firmware/SOURCES4
-rw-r--r--firmware/common/timefuncs.c13
-rw-r--r--firmware/drivers/eeprom_24cxx.c265
-rw-r--r--firmware/drivers/fat.c20
-rw-r--r--firmware/drivers/rtc/rtc_ds1339_ds3231.c144
-rw-r--r--firmware/export/config-h120.h8
-rw-r--r--firmware/export/config.h1
-rw-r--r--firmware/export/rtc.h9
-rw-r--r--firmware/export/sw_i2c.h30
-rw-r--r--firmware/target/coldfire/iriver/h100/sw_i2c-h100.c259
-rw-r--r--firmware/target/coldfire/iriver/h300/sw_i2c-h300.c105
18 files changed, 660 insertions, 268 deletions
diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c
index 70f5565b61..8fa80c725a 100644
--- a/apps/gui/gwps-common.c
+++ b/apps/gui/gwps-common.c
@@ -23,7 +23,9 @@
23#include <stdlib.h> 23#include <stdlib.h>
24#include "system.h" 24#include "system.h"
25#include "settings.h" 25#include "settings.h"
26#ifdef CONFIG_RTC
26#include "rtc.h" 27#include "rtc.h"
28#endif
27#include "audio.h" 29#include "audio.h"
28#include "status.h" 30#include "status.h"
29#include "power.h" 31#include "power.h"
@@ -972,6 +974,11 @@ static char* get_tag(struct wps_data* wps_data,
972#ifdef CONFIG_RTC 974#ifdef CONFIG_RTC
973 case 'c': /* Real Time Clock display */ 975 case 'c': /* Real Time Clock display */
974 *flags |= WPS_REFRESH_DYNAMIC; 976 *flags |= WPS_REFRESH_DYNAMIC;
977#if CONFIG_RTC == RTC_DS1339_DS3231
978 if(!rtc_detected)
979 return NULL;
980 else
981#endif
975 { 982 {
976 int value; 983 int value;
977 char *format = 0; 984 char *format = 0;
diff --git a/apps/gui/statusbar.c b/apps/gui/statusbar.c
index fbd8943315..a36ae15974 100644
--- a/apps/gui/statusbar.c
+++ b/apps/gui/statusbar.c
@@ -28,6 +28,9 @@
28#include "powermgmt.h" 28#include "powermgmt.h"
29#include "usb.h" 29#include "usb.h"
30#include "led.h" 30#include "led.h"
31#ifdef CONFIG_RTC
32#include "rtc.h"
33#endif
31 34
32#include "status.h" /* needed for battery_state global var */ 35#include "status.h" /* needed for battery_state global var */
33#include "action.h" /* for keys_locked */ 36#include "action.h" /* for keys_locked */
@@ -239,6 +242,9 @@ void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw)
239 bar->info.led = led_read(HZ/2); /* delay should match polling interval */ 242 bar->info.led = led_read(HZ/2); /* delay should match polling interval */
240#endif 243#endif
241#ifdef CONFIG_RTC 244#ifdef CONFIG_RTC
245#if CONFIG_RTC == RTC_DS1339_DS3231
246 if(rtc_detected)
247#endif
242 { 248 {
243 struct tm* tm = get_time(); 249 struct tm* tm = get_time();
244 bar->info.hour = tm->tm_hour; 250 bar->info.hour = tm->tm_hour;
@@ -324,6 +330,9 @@ void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw)
324 gui_statusbar_icon_lock_remote(display); 330 gui_statusbar_icon_lock_remote(display);
325#endif 331#endif
326#ifdef CONFIG_RTC 332#ifdef CONFIG_RTC
333#if CONFIG_RTC == RTC_DS1339_DS3231
334 if(rtc_detected)
335#endif
327 gui_statusbar_time(display, bar->info.hour, bar->info.minute); 336 gui_statusbar_time(display, bar->info.hour, bar->info.minute);
328#endif /* CONFIG_RTC */ 337#endif /* CONFIG_RTC */
329#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD) 338#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c
index 508f7214a1..818271b623 100644
--- a/apps/menus/settings_menu.c
+++ b/apps/menus/settings_menu.c
@@ -38,6 +38,12 @@
38#ifdef HAVE_ALARM_MOD 38#ifdef HAVE_ALARM_MOD
39#include "alarm_menu.h" 39#include "alarm_menu.h"
40#endif 40#endif
41#ifdef CONFIG_RTC
42#include "rtc.h"
43#endif
44
45/* callback to display rtc menus dynamically */
46int rtc_detect_callback(int action,const struct menu_item_ex *this_item);
41 47
42/***********************************/ 48/***********************************/
43/* TAGCACHE MENU */ 49/* TAGCACHE MENU */
@@ -206,7 +212,7 @@ static int timedate_set(void)
206 212
207MENUITEM_FUNCTION(time_set, ID2P(LANG_TIME), timedate_set, NULL, NOICON); 213MENUITEM_FUNCTION(time_set, ID2P(LANG_TIME), timedate_set, NULL, NOICON);
208MENUITEM_SETTING(timeformat, &global_settings.timeformat, NULL); 214MENUITEM_SETTING(timeformat, &global_settings.timeformat, NULL);
209MAKE_MENU(time_menu, ID2P(LANG_TIME_MENU), 0, NOICON, &time_set, &timeformat); 215MAKE_MENU(time_menu, ID2P(LANG_TIME_MENU), rtc_detect_callback, NOICON, &time_set, &timeformat);
210#endif 216#endif
211 217
212/* System menu */ 218/* System menu */
@@ -246,7 +252,7 @@ MENUITEM_FUNCTION(sleep_timer_call, ID2P(LANG_SLEEP_TIMER), sleep_timer,
246 setting to the user */ 252 setting to the user */
247#ifdef HAVE_ALARM_MOD 253#ifdef HAVE_ALARM_MOD
248MENUITEM_FUNCTION(alarm_screen_call, ID2P(LANG_ALARM_MOD_ALARM_MENU), 254MENUITEM_FUNCTION(alarm_screen_call, ID2P(LANG_ALARM_MOD_ALARM_MENU),
249 (menu_function)alarm_screen, NULL, NOICON); 255 (menu_function)alarm_screen, rtc_detect_callback, NOICON);
250#endif 256#endif
251 257
252/* Limits menu */ 258/* Limits menu */
@@ -383,3 +389,23 @@ MAKE_MENU(settings_menu_item, ID2P(LANG_GENERAL_SETTINGS), 0,
383 &bookmark_settings_menu, &browse_langs, &voice_settings_menu ); 389 &bookmark_settings_menu, &browse_langs, &voice_settings_menu );
384/* SETTINGS MENU */ 390/* SETTINGS MENU */
385/***********************************/ 391/***********************************/
392
393/* callback to display rtc menus dynamically */
394int rtc_detect_callback(int action,const struct menu_item_ex *this_item)
395{
396 if (action != ACTION_REQUEST_MENUITEM)
397 return action;
398
399#if defined(CONFIG_RTC) && CONFIG_RTC == RTC_DS1339_DS3231
400 if ((this_item == &time_menu) ||
401 (this_item == &alarm_screen_call))
402 {
403 if (!rtc_detected)
404 return ACTION_EXIT_MENUITEM;
405 }
406#else
407 (void)this_item;
408#endif
409
410 return action;
411}
diff --git a/apps/misc.c b/apps/misc.c
index 22f6fb50a6..339bc1d0b7 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -60,6 +60,7 @@
60#include "gui/gwps-common.h" 60#include "gui/gwps-common.h"
61 61
62#include "misc.h" 62#include "misc.h"
63#include "rtc.h"
63 64
64/* Format a large-range value for output, using the appropriate unit so that 65/* Format a large-range value for output, using the appropriate unit so that
65 * the displayed value is in the range 1 <= display < 1000 (1024 for "binary" 66 * the displayed value is in the range 1 <= display < 1000 (1024 for "binary"
@@ -414,6 +415,12 @@ void screen_dump(void)
414#endif 415#endif
415 416
416#ifdef CONFIG_RTC 417#ifdef CONFIG_RTC
418#if CONFIG_RTC == RTC_DS1339_DS3231
419 if(!rtc_detected)
420 create_numbered_filename(filename, "", "dump_", ".bmp", 4
421 IF_CNFN_NUM_(, NULL));
422 else
423#endif
417 create_datetime_filename(filename, "", "dump ", ".bmp", false); 424 create_datetime_filename(filename, "", "dump ", ".bmp", false);
418#else 425#else
419 create_numbered_filename(filename, "", "dump_", ".bmp", 4 426 create_numbered_filename(filename, "", "dump_", ".bmp", 4
diff --git a/apps/plugins/clock.c b/apps/plugins/clock.c
index 7e52e2b552..010e293bac 100644
--- a/apps/plugins/clock.c
+++ b/apps/plugins/clock.c
@@ -277,7 +277,7 @@ extern const fb_data clock_timesup[];
277#define EXIT_BUTTON BUTTON_MENU 277#define EXIT_BUTTON BUTTON_MENU
278#define MODE_NEXT_BUTTON BUTTON_RIGHT 278#define MODE_NEXT_BUTTON BUTTON_RIGHT
279#define MODE_PREV_BUTTON BUTTON_LEFT 279#define MODE_PREV_BUTTON BUTTON_LEFT
280#elif (CONFIG_KEYPAD == IRIVER_H300_PAD) 280#elif (CONFIG_KEYPAD == IRIVER_H300_PAD) || (CONFIG_KEYPAD == IRIVER_H100_PAD)
281#define COUNTER_TOGGLE_BUTTON (BUTTON_ON|BUTTON_REL) 281#define COUNTER_TOGGLE_BUTTON (BUTTON_ON|BUTTON_REL)
282#define COUNTER_RESET_BUTTON (BUTTON_ON|BUTTON_REPEAT) 282#define COUNTER_RESET_BUTTON (BUTTON_ON|BUTTON_REPEAT)
283#define MENU_BUTTON BUTTON_SELECT 283#define MENU_BUTTON BUTTON_SELECT
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c
index 8eea24d82d..2c5fc32b28 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -68,6 +68,9 @@
68#include "screen_access.h" 68#include "screen_access.h"
69#include "action.h" 69#include "action.h"
70#include "radio.h" 70#include "radio.h"
71#ifdef CONFIG_RTC
72#include "rtc.h"
73#endif
71#ifdef HAVE_RECORDING 74#ifdef HAVE_RECORDING
72 75
73static bool in_screen = false; 76static bool in_screen = false;
@@ -521,6 +524,12 @@ char *rec_create_filename(char *buffer)
521#ifdef CONFIG_RTC 524#ifdef CONFIG_RTC
522 /* We'll wait at least up to the start of the next second so no duplicate 525 /* We'll wait at least up to the start of the next second so no duplicate
523 names are created */ 526 names are created */
527#if CONFIG_RTC == RTC_DS1339_DS3231
528 if(!rtc_detected)
529 return create_numbered_filename(buffer, buffer, "rec_", ext, 4
530 IF_CNFN_NUM_(, &file_number));
531 else
532#endif
524 return create_datetime_filename(buffer, buffer, "R", ext, true); 533 return create_datetime_filename(buffer, buffer, "R", ext, true);
525#else 534#else
526 return create_numbered_filename(buffer, buffer, "rec_", ext, 4 535 return create_numbered_filename(buffer, buffer, "rec_", ext, 4
diff --git a/apps/scrobbler.c b/apps/scrobbler.c
index a339429cab..1c0d98cbc6 100644
--- a/apps/scrobbler.c
+++ b/apps/scrobbler.c
@@ -35,6 +35,7 @@ http://www.audioscrobbler.net/wiki/Portable_Player_Logging
35#ifdef CONFIG_RTC 35#ifdef CONFIG_RTC
36#include "time.h" 36#include "time.h"
37#include "timefuncs.h" 37#include "timefuncs.h"
38#include "rtc.h"
38#endif 39#endif
39 40
40#include "scrobbler.h" 41#include "scrobbler.h"
@@ -208,6 +209,11 @@ void scrobbler_change_event(struct mp3entry *id)
208 logf("SCROBBLER: add pending"); 209 logf("SCROBBLER: add pending");
209 copy_mp3entry(&scrobbler_entry, id); 210 copy_mp3entry(&scrobbler_entry, id);
210#ifdef CONFIG_RTC 211#ifdef CONFIG_RTC
212#if CONFIG_RTC == RTC_DS1339_DS3231
213 if(!rtc_detected)
214 timestamp = 0;
215 else
216#endif
211 timestamp = mktime(get_time()); 217 timestamp = mktime(get_time());
212#else 218#else
213 timestamp = 0; 219 timestamp = 0;
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 03d2b16d1d..f07145ca06 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -137,6 +137,8 @@ drivers/rtc/rtc_pcf50606.c
137drivers/rtc/rtc_pcf50605.c 137drivers/rtc/rtc_pcf50605.c
138#elif (CONFIG_RTC == RTC_E8564) 138#elif (CONFIG_RTC == RTC_E8564)
139drivers/rtc/rtc_e8564.c 139drivers/rtc/rtc_e8564.c
140#elif (CONFIG_RTC == RTC_DS1339_DS3231)
141drivers/rtc/rtc_ds1339_ds3231.c
140#elif (CONFIG_RTC == RTC_S3C2440) 142#elif (CONFIG_RTC == RTC_S3C2440)
141drivers/rtc/rtc_s3c2440.c 143drivers/rtc/rtc_s3c2440.c
142#elif (CONFIG_RTC == RTC_AS3514) 144#elif (CONFIG_RTC == RTC_AS3514)
@@ -380,6 +382,7 @@ target/coldfire/pcf50606-coldfire.c
380target/coldfire/iriver/ata-iriver.c 382target/coldfire/iriver/ata-iriver.c
381target/coldfire/iriver/lcd-remote-iriver.c 383target/coldfire/iriver/lcd-remote-iriver.c
382target/coldfire/iriver/system-iriver.c 384target/coldfire/iriver/system-iriver.c
385target/coldfire/iriver/h300/sw_i2c-h300.c
383target/coldfire/iriver/h300/adc-h300.c 386target/coldfire/iriver/h300/adc-h300.c
384target/coldfire/iriver/h300/backlight-h300.c 387target/coldfire/iriver/h300/backlight-h300.c
385target/coldfire/iriver/h300/button-h300.c 388target/coldfire/iriver/h300/button-h300.c
@@ -400,6 +403,7 @@ target/coldfire/ata-as-coldfire.S
400target/coldfire/iriver/ata-iriver.c 403target/coldfire/iriver/ata-iriver.c
401target/coldfire/iriver/lcd-remote-iriver.c 404target/coldfire/iriver/lcd-remote-iriver.c
402target/coldfire/iriver/system-iriver.c 405target/coldfire/iriver/system-iriver.c
406target/coldfire/iriver/h100/sw_i2c-h100.c
403target/coldfire/iriver/h100/adc-h100.c 407target/coldfire/iriver/h100/adc-h100.c
404target/coldfire/iriver/h100/backlight-h100.c 408target/coldfire/iriver/h100/backlight-h100.c
405target/coldfire/iriver/h100/button-h100.c 409target/coldfire/iriver/h100/button-h100.c
diff --git a/firmware/common/timefuncs.c b/firmware/common/timefuncs.c
index e48aadd0a2..881bc23e53 100644
--- a/firmware/common/timefuncs.c
+++ b/firmware/common/timefuncs.c
@@ -49,6 +49,19 @@ struct tm *get_time(void)
49#ifdef CONFIG_RTC 49#ifdef CONFIG_RTC
50 static long timeout = 0; 50 static long timeout = 0;
51 51
52#if CONFIG_RTC == RTC_DS1339_DS3231
53 if(!rtc_detected) {
54 tm.tm_sec = 0;
55 tm.tm_min = 0;
56 tm.tm_hour = 0;
57 tm.tm_mday = 1;
58 tm.tm_mon = 0;
59 tm.tm_year = 70;
60 tm.tm_wday = 1;
61 tm.tm_yday = 0; /* Not implemented for now */
62 tm.tm_isdst = -1; /* Not implemented for now */
63 } else
64#endif
52 /* Don't read the RTC more than once per second */ 65 /* Don't read the RTC more than once per second */
53 if (current_tick > timeout) { 66 if (current_tick > timeout) {
54 char rtcbuf[7]; 67 char rtcbuf[7];
diff --git a/firmware/drivers/eeprom_24cxx.c b/firmware/drivers/eeprom_24cxx.c
index 6016c0f841..a0d8f83eb7 100644
--- a/firmware/drivers/eeprom_24cxx.c
+++ b/firmware/drivers/eeprom_24cxx.c
@@ -16,274 +16,21 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#include "lcd.h" 19
20#include "cpu.h"
21#include "system.h"
22#include "kernel.h"
23#include "thread.h"
24#include "debug.h"
25#include "logf.h" 20#include "logf.h"
26#include "sprintf.h"
27#include "string.h" 21#include "string.h"
28#include "inttypes.h" 22#include "inttypes.h"
29 23
30#include "eeprom_24cxx.h" 24#include "sw_i2c.h"
31
32/**
33 * I2C-functions are copied and ported from fmradio.c.
34 */
35 25
36#define SW_I2C_WRITE 0 26#include "eeprom_24cxx.h"
37#define SW_I2C_READ 1
38 27
39/* Use cache to speedup writing to the chip. */ 28/* Use cache to speedup writing to the chip. */
40static char data_cache[EEPROM_SIZE]; 29static char data_cache[EEPROM_SIZE];
41static uint8_t cached_bitfield[EEPROM_SIZE/8]; 30static uint8_t cached_bitfield[EEPROM_SIZE/8];
42 31
43#define IS_CACHED(addr) (cached_bitfield[addr/8] & (1 << (addr % 8))) 32#define IS_CACHED(addr) (cached_bitfield[addr/8] & (1 << (addr % 8)))
44#define SET_CACHED(addr) (cached_bitfield[addr/8] |= 1 << (addr % 8)) 33#define SET_CACHED(addr) (cached_bitfield[addr/8] |= 1 << (addr % 8))
45
46/* h1x0 needs its own i2c driver,
47 h3x0 uses the pcf i2c driver */
48
49#ifdef IRIVER_H100_SERIES
50
51/* cute little functions, atomic read-modify-write */
52
53/* SCL is GPIO, 12 */
54#define SCL ( 0x00001000 & GPIO_READ)
55#define SCL_OUT_LO and_l(~0x00001000, &GPIO_OUT)
56#define SCL_LO or_l( 0x00001000, &GPIO_ENABLE)
57#define SCL_HI and_l(~0x00001000, &GPIO_ENABLE)
58
59/* SDA is GPIO1, 13 */
60#define SDA ( 0x00002000 & GPIO1_READ)
61#define SDA_OUT_LO and_l(~0x00002000, &GPIO1_OUT)
62#define SDA_LO or_l( 0x00002000, &GPIO1_ENABLE)
63#define SDA_HI and_l(~0x00002000, &GPIO1_ENABLE)
64
65/* delay loop to achieve 400kHz at 120MHz CPU frequency */
66#define DELAY do { int _x; for(_x=0;_x<22;_x++);} while(0)
67
68static void sw_i2c_init(void)
69{
70 logf("sw_i2c_init");
71 or_l(0x00001000, &GPIO_FUNCTION);
72 or_l(0x00002000, &GPIO1_FUNCTION);
73 SDA_HI;
74 SCL_HI;
75 SDA_OUT_LO;
76 SCL_OUT_LO;
77}
78
79static void sw_i2c_start(void)
80{
81 SCL_LO;
82 DELAY;
83 SDA_HI;
84 DELAY;
85 SCL_HI;
86 DELAY;
87 SDA_LO;
88 DELAY;
89 SCL_LO;
90}
91
92static void sw_i2c_stop(void)
93{
94 SCL_HI;
95 DELAY;
96 SDA_HI;
97 DELAY;
98}
99
100static void sw_i2c_ack(void)
101{
102 SCL_LO;
103 DELAY;
104 SDA_LO;
105 DELAY;
106
107 SCL_HI;
108 DELAY;
109}
110
111static bool sw_i2c_getack(void)
112{
113 bool ret = true;
114 int count = 10;
115
116 SCL_LO;
117 DELAY;
118 SDA_HI; /* sets to input */
119 DELAY;
120 SCL_HI;
121 DELAY;
122
123 while (SDA && count--)
124 DELAY;
125
126 if (SDA)
127 /* ack failed */
128 ret = false;
129
130 SCL_LO;
131 DELAY;
132 SDA_LO;
133
134 return ret;
135}
136
137static void sw_i2c_outb(unsigned char byte)
138{
139 int i;
140
141 /* clock out each bit, MSB first */
142 for ( i=0x80; i; i>>=1 )
143 {
144 SCL_LO;
145 DELAY;
146 if ( i & byte )
147 SDA_HI;
148 else
149 SDA_LO;
150 DELAY;
151 SCL_HI;
152 DELAY;
153 }
154}
155
156static unsigned char sw_i2c_inb(void)
157{
158 int i;
159 unsigned char byte = 0;
160
161 SDA_HI; /* sets to input */
162
163 /* clock in each bit, MSB first */
164 for ( i=0x80; i; i>>=1 )
165 {
166 SCL_HI;
167 DELAY;
168 if ( SDA )
169 byte |= i;
170 SCL_LO;
171 DELAY;
172 }
173
174 sw_i2c_ack();
175
176 return byte;
177}
178
179#else
180
181#include "pcf50606.h"
182
183#define sw_i2c_init() /* no extra init required */
184#define sw_i2c_start() pcf50606_i2c_start()
185#define sw_i2c_stop() pcf50606_i2c_stop()
186#define sw_i2c_ack() pcf50606_i2c_ack(true)
187#define sw_i2c_getack() pcf50606_i2c_getack()
188#define sw_i2c_outb(x) pcf50606_i2c_outb(x)
189#define sw_i2c_inb() pcf50606_i2c_inb(false)
190
191#endif /* IRIVER_H100_SERIES */
192
193
194int sw_i2c_write(int location, const unsigned char* buf, int count)
195{
196 int i;
197
198 sw_i2c_start();
199 sw_i2c_outb((EEPROM_ADDR & 0xfe) | SW_I2C_WRITE);
200 if (!sw_i2c_getack())
201 {
202 sw_i2c_stop();
203 return -1;
204 }
205
206 sw_i2c_outb(location);
207 if (!sw_i2c_getack())
208 {
209 sw_i2c_stop();
210 return -2;
211 }
212
213 for (i=0; i<count; i++)
214 {
215 sw_i2c_outb(buf[i]);
216 if (!sw_i2c_getack())
217 {
218 sw_i2c_stop();
219 return -3;
220 }
221 }
222
223 sw_i2c_stop();
224
225 return 0;
226}
227
228int sw_i2c_write_byte(int location, unsigned char byte)
229{
230 sw_i2c_start();
231 sw_i2c_outb((EEPROM_ADDR & 0xfe) | SW_I2C_WRITE);
232 if (!sw_i2c_getack())
233 {
234 sw_i2c_stop();
235 return -1;
236 }
237
238 sw_i2c_outb(location);
239 if (!sw_i2c_getack())
240 {
241 sw_i2c_stop();
242 return -2;
243 }
244
245 sw_i2c_outb(byte);
246 if (!sw_i2c_getack())
247 {
248 sw_i2c_stop();
249 return -3;
250 }
251
252 sw_i2c_stop();
253
254 return 0;
255}
256
257int sw_i2c_read(unsigned char location, unsigned char* byte)
258{
259 sw_i2c_start();
260 sw_i2c_outb((EEPROM_ADDR & 0xfe) | SW_I2C_WRITE);
261 if (!sw_i2c_getack())
262 {
263 sw_i2c_stop();
264 return -1;
265 }
266
267 sw_i2c_outb(location);
268 if (!sw_i2c_getack())
269 {
270 sw_i2c_stop();
271 return -2;
272 }
273
274 sw_i2c_start();
275 sw_i2c_outb((EEPROM_ADDR & 0xfe) | SW_I2C_READ);
276 if (!sw_i2c_getack())
277 {
278 sw_i2c_stop();
279 return -3;
280 }
281
282 *byte = sw_i2c_inb();
283 sw_i2c_stop();
284
285 return 0;
286}
287 34
288void eeprom_24cxx_init(void) 35void eeprom_24cxx_init(void)
289{ 36{
@@ -314,7 +61,7 @@ int eeprom_24cxx_read_byte(unsigned int address, char *c)
314 *c = 0; 61 *c = 0;
315 do 62 do
316 { 63 {
317 ret = sw_i2c_read(address, &byte); 64 ret = sw_i2c_read(EEPROM_ADDR, address, &byte, 1);
318 } while (ret < 0 && count++ < 200); 65 } while (ret < 0 && count++ < 200);
319 66
320 if (ret < 0) 67 if (ret < 0)
@@ -357,7 +104,7 @@ int eeprom_24cxx_write_byte(unsigned int address, char c)
357 104
358 do 105 do
359 { 106 {
360 ret = sw_i2c_write_byte(address, c); 107 ret = sw_i2c_write(EEPROM_ADDR, address, &c, 1);
361 } while (ret < 0 && count++ < 200) ; 108 } while (ret < 0 && count++ < 200) ;
362 109
363 if (ret < 0) 110 if (ret < 0)
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index e3e1a755cb..e4e77627d0 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -31,6 +31,9 @@
31#include "rbunicode.h" 31#include "rbunicode.h"
32#include "logf.h" 32#include "logf.h"
33#include "atoi.h" 33#include "atoi.h"
34#ifdef CONFIG_RTC
35#include "rtc.h"
36#endif
34 37
35#define BYTES2INT16(array,pos) \ 38#define BYTES2INT16(array,pos) \
36 (array[pos] | (array[pos+1] << 8 )) 39 (array[pos] | (array[pos+1] << 8 ))
@@ -945,6 +948,10 @@ static void fat_time(unsigned short* date,
945{ 948{
946#ifdef CONFIG_RTC 949#ifdef CONFIG_RTC
947 struct tm* tm = get_time(); 950 struct tm* tm = get_time();
951#if CONFIG_RTC == RTC_DS1339_DS3231
952 if(rtc_detected)
953 {
954#endif /* CONFIG_RTC == RTC_DS1339_DS3231 */
948 955
949 if (date) 956 if (date)
950 *date = ((tm->tm_year - 80) << 9) | 957 *date = ((tm->tm_year - 80) << 9) |
@@ -958,7 +965,14 @@ static void fat_time(unsigned short* date,
958 965
959 if (tenth) 966 if (tenth)
960 *tenth = (tm->tm_sec & 1) * 100; 967 *tenth = (tm->tm_sec & 1) * 100;
961#else 968
969#if CONFIG_RTC == RTC_DS1339_DS3231
970 }
971 else
972#endif /* CONFIG_RTC == RTC_DS1339_DS3231 */
973#endif /* CONFIG_RTC */
974#if !defined(CONFIG_RTC) || CONFIG_RTC == RTC_DS1339_DS3231
975 {
962 /* non-RTC version returns an increment from the supplied time, or a 976 /* non-RTC version returns an increment from the supplied time, or a
963 * fixed standard time/date if no time given as input */ 977 * fixed standard time/date if no time given as input */
964 bool next_day = false; 978 bool next_day = false;
@@ -1025,9 +1039,9 @@ static void fat_time(unsigned short* date,
1025 } 1039 }
1026 if (tenth) 1040 if (tenth)
1027 *tenth = 0; 1041 *tenth = 0;
1028#endif /* CONFIG_RTC */ 1042 }
1043#endif /* !defined(CONFIG_RTC) || CONFIG_RTC == RTC_DS1339_DS3231 */
1029} 1044}
1030
1031static int write_long_name(struct fat_file* file, 1045static int write_long_name(struct fat_file* file,
1032 unsigned int firstentry, 1046 unsigned int firstentry,
1033 unsigned int numentries, 1047 unsigned int numentries,
diff --git a/firmware/drivers/rtc/rtc_ds1339_ds3231.c b/firmware/drivers/rtc/rtc_ds1339_ds3231.c
new file mode 100644
index 0000000000..df67fed735
--- /dev/null
+++ b/firmware/drivers/rtc/rtc_ds1339_ds3231.c
@@ -0,0 +1,144 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Robert Kukla
11 * based on Archos code by Linus Nielsen Feltzing, Uwe Freese, Laurent Baum
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "rtc.h"
20#include "logf.h"
21#include "sw_i2c.h"
22
23#define RTC_ADDR 0xD0
24
25bool rtc_detected = false;
26
27void rtc_init(void)
28{
29 char byte;
30
31 sw_i2c_init();
32
33 /* read one byte from RTC; 0 on success */
34 rtc_detected = !sw_i2c_read(RTC_ADDR, 0, &byte, 1);
35
36#ifdef HAVE_ALARM_MOD
37 /* Check + save alarm bit first, before the power thread starts watching */
38 rtc_check_alarm_started(false);
39#endif
40
41}
42
43#ifdef HAVE_ALARM_MOD
44
45/* check whether the unit has been started by the RTC alarm function */
46/* (check for A2F, which => started using wakeup alarm) */
47bool rtc_check_alarm_started(bool release_alarm)
48{
49 static bool alarm_state, run_before;
50 bool rc;
51
52 if (run_before) {
53 rc = alarm_state;
54 alarm_state &= ~release_alarm;
55 } else {
56 /* This call resets AF, so we store the state for later recall */
57 rc = alarm_state = rtc_check_alarm_flag();
58 run_before = true;
59 }
60
61 return rc;
62}
63/*
64 * Checks the A2F flag. This call resets A2F once read.
65 *
66 */
67bool rtc_check_alarm_flag(void)
68{
69 unsigned char buf[1];
70 bool flag = false;
71
72 sw_i2c_read(RTC_ADDR, 0x0f, buf, 1);
73 if (buf[0] & 0x02) flag = true;
74
75 rtc_enable_alarm(false);
76
77 return flag;
78}
79
80/* set alarm time registers to the given time (repeat once per day) */
81void rtc_set_alarm(int h, int m)
82{
83 unsigned char buf[3];
84
85 buf[0] = (((m / 10) << 4) | (m % 10)) & 0x7f; /* minutes */
86 buf[1] = (((h / 10) << 4) | (h % 10)) & 0x3f; /* hour */
87 buf[2] = 0x80; /* repeat every day */
88
89 sw_i2c_write(RTC_ADDR, 0x0b, buf, 3);
90}
91
92/* read out the current alarm time */
93void rtc_get_alarm(int *h, int *m)
94{
95 unsigned char buf[2];
96
97 sw_i2c_read(RTC_ADDR, 0x0b, buf, 2);
98
99 *m = ((buf[0] & 0x70) >> 4) * 10 + (buf[0] & 0x0f);
100 *h = ((buf[1] & 0x30) >> 4) * 10 + (buf[1] & 0x0f);
101}
102
103/* turn alarm on or off by setting the alarm flag enable */
104/* the alarm is automatically disabled when the RTC gets Vcc power at startup */
105/* avoid that an alarm occurs when the device is on because this locks the ON key forever */
106/* returns false if alarm was set and alarm flag (output) is off */
107/* returns true if alarm flag went on, which would lock the device, so the alarm was disabled again */
108bool rtc_enable_alarm(bool enable)
109{
110 unsigned char buf[2];
111
112 buf[0] = enable ? 0x26 : 0x04; /* BBSQI INTCN A2IE vs INTCH only */
113 buf[1] = 0x00; /* reset alarm flags (and OSF for good measure) */
114
115 sw_i2c_write(RTC_ADDR, 0x0e, buf, 2);
116
117 return false; /* all ok */
118}
119
120#endif /* HAVE_ALARM_MOD */
121
122int rtc_read_datetime(unsigned char* buf)
123{
124 int i;
125
126 i = sw_i2c_read(RTC_ADDR, 0, buf, 7);
127
128 buf[3]--; /* timefuncs wants 0..6 for wday */
129
130 return i;
131}
132
133int rtc_write_datetime(unsigned char* buf)
134{
135 int i;
136
137 buf[3]++; /* chip wants 1..7 for wday */
138 buf[5]|=0x80; /* chip wants century (always 20xx) */
139
140 i = sw_i2c_write(RTC_ADDR, 0, buf, 7);
141
142 return i;
143}
144
diff --git a/firmware/export/config-h120.h b/firmware/export/config-h120.h
index e7fb73ea0f..9dccf22d0e 100644
--- a/firmware/export/config-h120.h
+++ b/firmware/export/config-h120.h
@@ -45,7 +45,13 @@
45/* Define this if you do software codec */ 45/* Define this if you do software codec */
46#define CONFIG_CODEC SWCODEC 46#define CONFIG_CODEC SWCODEC
47 47
48/* Define this if you have an remote lcd */ 48#ifndef SIMULATOR
49/* RTC is autodetected on target only */
50#define CONFIG_RTC RTC_DS1339_DS3231
51#define HAVE_ALARM_MOD
52#endif
53
54 /* Define this if you have an remote lcd */
49#define HAVE_REMOTE_LCD 55#define HAVE_REMOTE_LCD
50 56
51#define CONFIG_LCD LCD_S1D15E06 57#define CONFIG_LCD LCD_S1D15E06
diff --git a/firmware/export/config.h b/firmware/export/config.h
index ac2ee688e4..085f86af53 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -153,6 +153,7 @@
153#define RTC_S3C2440 4 153#define RTC_S3C2440 4
154#define RTC_E8564 5 /* iriver H10 */ 154#define RTC_E8564 5 /* iriver H10 */
155#define RTC_AS3514 6 /* Sandisk Sansa e200 series */ 155#define RTC_AS3514 6 /* Sandisk Sansa e200 series */
156#define RTC_DS1339_DS3231 7 /* h1x0 RTC mod */
156 157
157/* USB On-the-go */ 158/* USB On-the-go */
158#define USBOTG_ISP1362 1362 /* iriver H300 */ 159#define USBOTG_ISP1362 1362 /* iriver H300 */
diff --git a/firmware/export/rtc.h b/firmware/export/rtc.h
index c7e3c4a96b..2f13cbb578 100644
--- a/firmware/export/rtc.h
+++ b/firmware/export/rtc.h
@@ -20,6 +20,7 @@
20#define _RTC_H_ 20#define _RTC_H_
21 21
22#include <stdbool.h> 22#include <stdbool.h>
23#include <system.h>
23 24
24#ifdef CONFIG_RTC 25#ifdef CONFIG_RTC
25 26
@@ -27,6 +28,10 @@ extern const int dayname[];
27 28
28extern const int monthname[]; 29extern const int monthname[];
29 30
31#if CONFIG_RTC == RTC_DS1339_DS3231
32extern bool rtc_detected;
33#endif
34
30/* Common functions for all targets */ 35/* Common functions for all targets */
31void rtc_init(void); 36void rtc_init(void);
32int rtc_read_datetime(unsigned char* buf); 37int rtc_read_datetime(unsigned char* buf);
@@ -40,6 +45,8 @@ int rtc_read(unsigned char address);
40int rtc_read_multiple(unsigned char address, unsigned char *buf, int numbytes); 45int rtc_read_multiple(unsigned char address, unsigned char *buf, int numbytes);
41int rtc_write(unsigned char address, unsigned char value); 46int rtc_write(unsigned char address, unsigned char value);
42 47
48#endif /* RTC_M41ST84W */
49
43#ifdef HAVE_ALARM_MOD 50#ifdef HAVE_ALARM_MOD
44void rtc_set_alarm(int h, int m); 51void rtc_set_alarm(int h, int m);
45void rtc_get_alarm(int *h, int *m); 52void rtc_get_alarm(int *h, int *m);
@@ -48,8 +55,6 @@ bool rtc_check_alarm_started(bool release_alarm);
48bool rtc_check_alarm_flag(void); 55bool rtc_check_alarm_flag(void);
49#endif /* HAVE_ALARM_MOD */ 56#endif /* HAVE_ALARM_MOD */
50 57
51#endif /* RTC_M41ST84W */
52
53#endif /* CONFIG_RTC */ 58#endif /* CONFIG_RTC */
54 59
55#endif 60#endif
diff --git a/firmware/export/sw_i2c.h b/firmware/export/sw_i2c.h
new file mode 100644
index 0000000000..42dccad742
--- /dev/null
+++ b/firmware/export/sw_i2c.h
@@ -0,0 +1,30 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Robert Kukla
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef _SW_I2C_H
21#define _SW_I2C_H
22
23#define SW_I2C_WRITE 0
24#define SW_I2C_READ 1
25
26void sw_i2c_init(void);
27int sw_i2c_write(unsigned char chip, unsigned char location, const unsigned char* buf, int count);
28int sw_i2c_read (unsigned char chip, unsigned char location, unsigned char* buf, int count);
29
30#endif
diff --git a/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c b/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c
new file mode 100644
index 0000000000..cb061875e0
--- /dev/null
+++ b/firmware/target/coldfire/iriver/h100/sw_i2c-h100.c
@@ -0,0 +1,259 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Miika Pekkarinen
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "system.h"
20#include "logf.h"
21#include "inttypes.h"
22
23#include "sw_i2c.h"
24
25/**
26 * I2C-functions are copied and ported from fmradio.c.
27 * later fixed, adapted and moved to a seperate file so they can be re-used by the rtc-ds1339c code by Robert Kukla
28 */
29
30/* cute little functions, atomic read-modify-write */
31
32/* SCL is GPIO, 12 */
33#define SCL ( 0x00001000 & GPIO_READ)
34#define SCL_OUT_LO and_l(~0x00001000, &GPIO_OUT)
35#define SCL_LO or_l( 0x00001000, &GPIO_ENABLE)
36#define SCL_HI and_l(~0x00001000, &GPIO_ENABLE)
37
38/* SDA is GPIO1, 13 */
39#define SDA ( 0x00002000 & GPIO1_READ)
40#define SDA_OUT_LO and_l(~0x00002000, &GPIO1_OUT)
41#define SDA_LO or_l( 0x00002000, &GPIO1_ENABLE)
42#define SDA_HI and_l(~0x00002000, &GPIO1_ENABLE)
43
44/* delay loop to achieve 400kHz at 120MHz CPU frequency */
45#define DELAY do { int _x; for(_x=0;_x<22;_x++);} while(0)
46
47void sw_i2c_init(void)
48{
49 or_l(0x00001000, &GPIO_FUNCTION);
50 or_l(0x00002000, &GPIO1_FUNCTION);
51 SDA_HI;
52 SCL_HI;
53 SDA_OUT_LO;
54 SCL_OUT_LO;
55}
56
57/* in: C=? D=?
58 * out: C=L D=L
59 */
60static void sw_i2c_start(void)
61{
62 SCL_LO;
63 DELAY;
64 SDA_HI;
65 DELAY;
66 SCL_HI;
67 DELAY;
68 SDA_LO;
69 DELAY;
70 SCL_LO;
71}
72
73/* in: C=L D=?
74 * out: C=H D=H
75 */
76static void sw_i2c_stop(void)
77{
78 SDA_LO;
79 DELAY;
80 SCL_HI;
81 DELAY;
82 SDA_HI;
83}
84
85/* in: C=L D=H
86 * out: C=L D=L
87 */
88static void sw_i2c_ack(void)
89{
90 SDA_LO;
91 DELAY;
92
93 SCL_HI;
94 DELAY;
95 SCL_LO;
96}
97
98/* in: C=L D=H
99 * out: C=L D=H
100 */
101static void sw_i2c_nack(void)
102{
103 SDA_HI; /* redundant */
104 DELAY;
105
106 SCL_HI;
107 DELAY;
108 SCL_LO;
109}
110
111/* in: C=L D=?
112 * out: C=L D=H
113 */
114static bool sw_i2c_getack(void)
115{
116 bool ret = true;
117/* int count = 10; */
118
119 SDA_HI; /* sets to input */
120 DELAY;
121 SCL_HI;
122 DELAY;
123
124/* while (SDA && count--) */
125/* DELAY; */
126
127 if (SDA)
128 /* ack failed */
129 ret = false;
130
131 SCL_LO;
132
133 return ret;
134}
135
136/* in: C=L D=?
137 * out: C=L D=?
138 */
139static void sw_i2c_outb(unsigned char byte)
140{
141 int i;
142
143 /* clock out each bit, MSB first */
144 for ( i=0x80; i; i>>=1 )
145 {
146 if ( i & byte )
147 SDA_HI;
148 else
149 SDA_LO;
150 DELAY;
151
152 SCL_HI;
153 DELAY;
154 SCL_LO;
155 }
156}
157
158/* in: C=L D=?
159 * out: C=L D=H
160 */
161static unsigned char sw_i2c_inb(void)
162{
163 int i;
164 unsigned char byte = 0;
165
166 SDA_HI; /* sets to input */
167
168 /* clock in each bit, MSB first */
169 for ( i=0x80; i; i>>=1 )
170 {
171 DELAY;
172 do {
173 SCL_HI;
174 DELAY;
175 }
176 while(SCL==0); /* wait for any SCL clock stretching */
177 if ( SDA )
178 byte |= i;
179 SCL_LO;
180 }
181
182 return byte;
183}
184
185int sw_i2c_write(unsigned char chip, unsigned char location, const unsigned char* buf, int count)
186{
187 int i;
188
189 sw_i2c_start();
190 sw_i2c_outb((chip & 0xfe) | SW_I2C_WRITE);
191 if (!sw_i2c_getack())
192 {
193 sw_i2c_stop();
194 return -1;
195 }
196
197 sw_i2c_outb(location);
198 if (!sw_i2c_getack())
199 {
200 sw_i2c_stop();
201 return -2;
202 }
203
204 for (i=0; i<count; i++)
205 {
206 sw_i2c_outb(buf[i]);
207 if (!sw_i2c_getack())
208 {
209 sw_i2c_stop();
210 return -3;
211 }
212 }
213
214 sw_i2c_stop();
215
216 return 0;
217}
218
219int sw_i2c_read(unsigned char chip, unsigned char location, unsigned char* buf, int count)
220{
221 int i;
222
223 sw_i2c_start();
224 sw_i2c_outb((chip & 0xfe) | SW_I2C_WRITE);
225 if (!sw_i2c_getack())
226 {
227 sw_i2c_stop();
228 return -1;
229 }
230
231 sw_i2c_outb(location);
232 if (!sw_i2c_getack())
233 {
234 sw_i2c_stop();
235 return -2;
236 }
237
238 sw_i2c_start();
239 sw_i2c_outb((chip & 0xfe) | SW_I2C_READ);
240 if (!sw_i2c_getack())
241 {
242 sw_i2c_stop();
243 return -3;
244 }
245
246 for (i=0; i<count-1; i++)
247 {
248 buf[i] = sw_i2c_inb();
249 sw_i2c_ack();
250 }
251
252 /* 1byte min */
253 buf[i] = sw_i2c_inb();
254 sw_i2c_nack();
255
256 sw_i2c_stop();
257
258 return 0;
259}
diff --git a/firmware/target/coldfire/iriver/h300/sw_i2c-h300.c b/firmware/target/coldfire/iriver/h300/sw_i2c-h300.c
new file mode 100644
index 0000000000..f0937463e3
--- /dev/null
+++ b/firmware/target/coldfire/iriver/h300/sw_i2c-h300.c
@@ -0,0 +1,105 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Miika Pekkarinen
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "system.h"
20#include "logf.h"
21#include "inttypes.h"
22
23#include "sw_i2c.h"
24
25#include "pcf50606.h"
26
27void sw_i2c_init(void)
28{
29 /* no extra init required */
30}
31
32int sw_i2c_write(unsigned char chip, unsigned char location, const unsigned char* buf, int count)
33{
34 int i;
35
36 pcf50606_i2c_start();
37 pcf50606_i2c_outb((chip & 0xfe) | SW_I2C_WRITE);
38 if (!pcf50606_i2c_getack())
39 {
40 pcf50606_i2c_stop();
41 return -1;
42 }
43
44 pcf50606_i2c_outb(location);
45 if (!pcf50606_i2c_getack())
46 {
47 pcf50606_i2c_stop();
48 return -2;
49 }
50
51 for (i=0; i<count; i++)
52 {
53 pcf50606_i2c_outb(buf[i]);
54 if (!pcf50606_i2c_getack())
55 {
56 pcf50606_i2c_stop();
57 return -3;
58 }
59 }
60
61 pcf50606_i2c_stop();
62
63 return 0;
64}
65
66int sw_i2c_read(unsigned char chip, unsigned char location, unsigned char* buf, int count)
67{
68 int i;
69
70 pcf50606_i2c_start();
71 pcf50606_i2c_outb((chip & 0xfe) | SW_I2C_WRITE);
72 if (!pcf50606_i2c_getack())
73 {
74 pcf50606_i2c_stop();
75 return -1;
76 }
77
78 pcf50606_i2c_outb(location);
79 if (!pcf50606_i2c_getack())
80 {
81 pcf50606_i2c_stop();
82 return -2;
83 }
84
85 pcf50606_i2c_start();
86 pcf50606_i2c_outb((chip & 0xfe) | SW_I2C_READ);
87 if (!pcf50606_i2c_getack())
88 {
89 pcf50606_i2c_stop();
90 return -3;
91 }
92
93 for (i=0; i<count-1; i++)
94 {
95 buf[i] = pcf50606_i2c_inb(true);
96 }
97
98 /* 1byte min */
99 buf[i] = pcf50606_i2c_inb(false);
100
101
102 pcf50606_i2c_stop();
103
104 return 0;
105}