]> git.sur5r.net Git - u-boot/blob - cpu/s3c44b0/cpu.c
5d50b3cea04ef03547eb91a81c62fe9a8c3a5369
[u-boot] / cpu / s3c44b0 / cpu.c
1 /*
2  * (C) Copyright 2004
3  * DAVE Srl
4  * http://www.dave-tech.it
5  * http://www.wawnet.biz
6  * mailto:info@wawnet.biz
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26
27 /*
28  * S3C44B0 CPU specific code
29  */
30
31 #include <common.h>
32 #include <command.h>
33 #include <asm/hardware.h>
34
35 static void s3c44b0_flush_cache(void)
36 {
37         volatile int i;
38         /* flush cycle */
39         for(i=0x10002000;i<0x10004800;i+=16)
40         {
41                 *((int *)i)=0x0;
42         }
43 }
44
45
46 int cpu_init (void)
47 {
48         icache_enable();
49
50         return 0;
51 }
52
53 int cleanup_before_linux (void)
54 {
55         /*
56                 cache memory should be enabled before calling
57                 Linux to make the kernel uncompression faster
58         */
59         icache_enable();
60
61         disable_interrupts ();
62
63         return 0;
64 }
65
66 void reset_cpu (ulong addr)
67 {
68         /*
69                 reset the cpu using watchdog
70         */
71
72         /* Disable the watchdog.*/
73         WTCON&=~(1<<5);
74
75         /* set the timeout value to a short time... */
76         WTCNT = 0x1;
77
78         /* Enable the watchdog. */
79         WTCON|=1;
80         WTCON|=(1<<5);
81
82         while(1) {
83                 /*NOP*/
84         }
85 }
86
87 int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
88 {
89         disable_interrupts ();
90         reset_cpu (0);
91
92         /*NOTREACHED*/
93         return (0);
94 }
95
96 void icache_enable (void)
97 {
98         ulong reg;
99
100         s3c44b0_flush_cache();
101
102         /*
103                 Init cache
104                 Non-cacheable area (everything outside RAM)
105                 0x0000:0000 - 0x0C00:0000
106          */
107         NCACHBE0 = 0xC0000000;
108         NCACHBE1 = 0x00000000;
109
110         /*
111                 Enable chache
112         */
113         reg = SYSCFG;
114         reg |= 0x00000006; /* 8kB */
115         SYSCFG = reg;
116 }
117
118 void icache_disable (void)
119 {
120         ulong reg;
121
122         reg = SYSCFG;
123         reg &= ~0x00000006; /* 8kB */
124         SYSCFG = reg;
125 }
126
127 int icache_status (void)
128 {
129         return 0;
130 }
131
132 void dcache_enable (void)
133 {
134         icache_enable();
135 }
136
137 void dcache_disable (void)
138 {
139         icache_disable();
140 }
141
142 int dcache_status (void)
143 {
144         return dcache_status();
145 }
146
147 /*
148         RTC stuff
149 */
150 #include <rtc.h>
151 #ifndef BCD2HEX
152         #define BCD2HEX(n)  ((n>>4)*10+(n&0x0f))
153 #endif
154 #ifndef HEX2BCD
155         #define HEX2BCD(x) ((((x) / 10) << 4) + (x) % 10)
156 #endif
157
158 void rtc_get (struct rtc_time* tm)
159 {
160         RTCCON |= 1;
161         tm->tm_year  = BCD2HEX(BCDYEAR);
162         tm->tm_mon   = BCD2HEX(BCDMON);
163         tm->tm_wday   = BCD2HEX(BCDDATE);
164         tm->tm_mday   = BCD2HEX(BCDDAY);
165         tm->tm_hour  = BCD2HEX(BCDHOUR);
166         tm->tm_min  = BCD2HEX(BCDMIN);
167         tm->tm_sec  = BCD2HEX(BCDSEC);
168
169         if (tm->tm_sec==0) {
170                 /* we have to re-read the rtc data because of the "one second deviation" problem */
171                 /* see RTC datasheet for more info about it */
172                 tm->tm_year  = BCD2HEX(BCDYEAR);
173                 tm->tm_mon   = BCD2HEX(BCDMON);
174                 tm->tm_mday   = BCD2HEX(BCDDAY);
175                 tm->tm_wday   = BCD2HEX(BCDDATE);
176                 tm->tm_hour  = BCD2HEX(BCDHOUR);
177                 tm->tm_min  = BCD2HEX(BCDMIN);
178                 tm->tm_sec  = BCD2HEX(BCDSEC);
179         }
180
181         RTCCON &= ~1;
182
183         if(tm->tm_year >= 70)
184                 tm->tm_year += 1900;
185         else
186                 tm->tm_year += 2000;
187 }
188
189 void rtc_set (struct rtc_time* tm)
190 {
191         if(tm->tm_year < 2000)
192                 tm->tm_year -= 1900;
193         else
194                 tm->tm_year -= 2000;
195
196         RTCCON |= 1;
197         BCDYEAR = HEX2BCD(tm->tm_year);
198         BCDMON = HEX2BCD(tm->tm_mon);
199         BCDDAY = HEX2BCD(tm->tm_mday);
200         BCDDATE = HEX2BCD(tm->tm_wday);
201         BCDHOUR = HEX2BCD(tm->tm_hour);
202         BCDMIN = HEX2BCD(tm->tm_min);
203         BCDSEC = HEX2BCD(tm->tm_sec);
204         RTCCON &= 1;
205 }
206
207 void rtc_reset (void)
208 {
209         RTCCON |= 1;
210         BCDYEAR = 0;
211         BCDMON = 0;
212         BCDDAY = 0;
213         BCDDATE = 0;
214         BCDHOUR = 0;
215         BCDMIN = 0;
216         BCDSEC = 0;
217         RTCCON &= 1;
218 }
219
220
221 /*
222         I2C stuff
223 */
224
225 /*
226  * Initialization, must be called once on start up, may be called
227  * repeatedly to change the speed and slave addresses.
228  */
229 void i2c_init(int speed, int slaveaddr)
230 {
231         /*
232                 setting up I2C support
233         */
234         unsigned int save_F,save_PF,rIICCON,rPCONA,rPDATA,rPCONF,rPUPF;
235
236         save_F = PCONF;
237         save_PF = PUPF;
238
239         rPCONF = ((save_F & ~(0xF))| 0xa);
240         rPUPF = (save_PF | 0x3);
241         PCONF = rPCONF; /*PF0:IICSCL, PF1:IICSDA*/
242         PUPF = rPUPF; /* Disable pull-up */
243
244         /* Configuring pin for WC pin of EEprom */
245         rPCONA = PCONA;
246         rPCONA &= ~(1<<9);
247         PCONA = rPCONA;
248
249         rPDATA = PDATA;
250         rPDATA &= ~(1<<9);
251         PDATA = rPDATA;
252
253         /*
254                 Enable ACK, IICCLK=MCLK/16, enable interrupt
255                 75Mhz/16/(12+1) = 390625 Hz
256         */
257         rIICCON=(1<<7)|(0<<6)|(1<<5)|(0xC);
258         IICCON = rIICCON;
259
260         IICADD = slaveaddr;
261 }
262
263 /*
264  * Probe the given I2C chip address.  Returns 0 if a chip responded,
265  * not 0 on failure.
266  */
267 int i2c_probe(uchar chip)
268 {
269         /*
270                 not implemented
271         */
272
273         printf("i2c_probe chip %d\n", (int) chip);
274         return -1;
275 }
276
277 /*
278  * Read/Write interface:
279  *   chip:    I2C chip address, range 0..127
280  *   addr:    Memory (register) address within the chip
281  *   alen:    Number of bytes to use for addr (typically 1, 2 for larger
282  *              memories, 0 for register type devices with only one
283  *              register)
284  *   buffer:  Where to read/write the data
285  *   len:     How many bytes to read/write
286  *
287  *   Returns: 0 on success, not 0 on failure
288  */
289
290 #define S3C44B0X_rIIC_INTPEND               (1<<4)
291 #define S3C44B0X_rIIC_LAST_RECEIV_BIT       (1<<0)
292 #define S3C44B0X_rIIC_INTERRUPT_ENABLE      (1<<5)
293 #define S3C44B0_IIC_TIMEOUT 100
294
295 int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
296 {
297
298         int k, j, temp;
299         u32 rIICSTAT;
300
301         /*
302                 send the device offset
303         */
304
305         rIICSTAT = 0xD0;
306         IICSTAT = rIICSTAT;
307
308         IICDS = chip;   /* this is a write operation... */
309
310         rIICSTAT |= (1<<5);
311         IICSTAT = rIICSTAT;
312
313         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
314                 temp = IICCON;
315                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
316                 break;
317                 udelay(2000);
318         }
319         if (k==S3C44B0_IIC_TIMEOUT)
320                 return -1;
321
322         /* wait and check ACK */
323         temp = IICSTAT;
324         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
325                 return -1;
326
327         IICDS = addr;
328         IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
329
330         /* wait and check ACK */
331         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
332                 temp = IICCON;
333                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
334                 break;
335                 udelay(2000);
336         }
337         if (k==S3C44B0_IIC_TIMEOUT)
338                 return -1;
339
340         temp = IICSTAT;
341         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
342                 return -1;
343
344         /*
345                 now we can start with the read operation...
346         */
347
348         IICDS = chip | 0x01;    /* this is a read operation... */
349
350         rIICSTAT = 0x90; /*master recv*/
351         rIICSTAT |= (1<<5);
352         IICSTAT = rIICSTAT;
353
354         IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
355
356         /* wait and check ACK */
357         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
358                 temp = IICCON;
359                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
360                 break;
361                 udelay(2000);
362         }
363         if (k==S3C44B0_IIC_TIMEOUT)
364                 return -1;
365
366         temp = IICSTAT;
367         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
368                 return -1;
369
370         for (j=0; j<len-1; j++) {
371
372         /*clear pending bit to resume */
373
374         temp = IICCON & ~(S3C44B0X_rIIC_INTPEND);
375         IICCON = temp;
376
377         /* wait and check ACK */
378         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
379                 temp = IICCON;
380                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
381                 break;
382                 udelay(2000);
383         }
384         if (k==S3C44B0_IIC_TIMEOUT)
385                 return -1;
386
387
388                 buffer[j] = IICDS; /*save readed data*/
389
390     } /*end for(j)*/
391
392         /*
393                 reading the last data
394                 unset ACK generation
395         */
396         temp = IICCON & ~(S3C44B0X_rIIC_INTPEND | (1<<7));
397         IICCON = temp;
398
399         /* wait but NOT check ACK */
400         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
401                 temp = IICCON;
402                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
403                 break;
404                 udelay(2000);
405         }
406         if (k==S3C44B0_IIC_TIMEOUT)
407                 return -1;
408
409         buffer[j] = IICDS; /*save readed data*/
410
411         rIICSTAT = 0x90; /*master recv*/
412
413         /* Write operation Terminate sending STOP */
414         IICSTAT = rIICSTAT;
415         /*Clear Int Pending Bit to RESUME*/
416         temp = IICCON;
417         IICCON = temp & (~S3C44B0X_rIIC_INTPEND);
418
419         IICCON = IICCON | (1<<7);       /*restore ACK generation*/
420
421         return 0;
422 }
423
424 int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
425 {
426         int j, k;
427         u32 rIICSTAT, temp;
428
429
430         /*
431                 send the device offset
432         */
433
434         rIICSTAT = 0xD0;
435         IICSTAT = rIICSTAT;
436
437         IICDS = chip;   /* this is a write operation... */
438
439         rIICSTAT |= (1<<5);
440         IICSTAT = rIICSTAT;
441
442         IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
443
444         /* wait and check ACK */
445         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
446                 temp = IICCON;
447                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
448                 break;
449                 udelay(2000);
450         }
451         if (k==S3C44B0_IIC_TIMEOUT)
452                 return -1;
453
454         temp = IICSTAT;
455         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
456                 return -1;
457
458         IICDS = addr;
459         IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
460
461         /* wait and check ACK */
462         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
463                 temp = IICCON;
464                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
465                 break;
466                 udelay(2000);
467         }
468         if (k==S3C44B0_IIC_TIMEOUT)
469           return -1;
470
471         temp = IICSTAT;
472         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
473                 return -1;
474
475         /*
476                 now we can start with the read write operation
477         */
478         for (j=0; j<len; j++) {
479
480                 IICDS = buffer[j]; /*prerare data to write*/
481
482                 /*clear pending bit to resume*/
483
484                 temp = IICCON & ~(S3C44B0X_rIIC_INTPEND);
485                 IICCON = temp;
486
487                 /* wait but NOT check ACK */
488                 for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
489                         temp = IICCON;
490                         if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
491                         break;
492
493                         udelay(2000);
494                 }
495
496                 if (k==S3C44B0_IIC_TIMEOUT)
497                         return -1;
498
499         } /* end for(j) */
500
501         /* sending stop to terminate */
502         rIICSTAT = 0xD0;  /*master send*/
503         IICSTAT = rIICSTAT;
504         /*Clear Int Pending Bit to RESUME*/
505         temp = IICCON;
506         IICCON = temp & (~S3C44B0X_rIIC_INTPEND);
507
508         return 0;
509 }