]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/s3c44b0/cpu.c
Cleanup: fix "MHz" spelling
[karo-tx-uboot.git] / 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 int 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         return 0;
189 }
190
191 int rtc_set (struct rtc_time* tm)
192 {
193         if(tm->tm_year < 2000)
194                 tm->tm_year -= 1900;
195         else
196                 tm->tm_year -= 2000;
197
198         RTCCON |= 1;
199         BCDYEAR = HEX2BCD(tm->tm_year);
200         BCDMON = HEX2BCD(tm->tm_mon);
201         BCDDAY = HEX2BCD(tm->tm_mday);
202         BCDDATE = HEX2BCD(tm->tm_wday);
203         BCDHOUR = HEX2BCD(tm->tm_hour);
204         BCDMIN = HEX2BCD(tm->tm_min);
205         BCDSEC = HEX2BCD(tm->tm_sec);
206         RTCCON &= 1;
207
208         return 0;
209 }
210
211 void rtc_reset (void)
212 {
213         RTCCON |= 1;
214         BCDYEAR = 0;
215         BCDMON = 0;
216         BCDDAY = 0;
217         BCDDATE = 0;
218         BCDHOUR = 0;
219         BCDMIN = 0;
220         BCDSEC = 0;
221         RTCCON &= 1;
222 }
223
224
225 /*
226         I2C stuff
227 */
228
229 /*
230  * Initialization, must be called once on start up, may be called
231  * repeatedly to change the speed and slave addresses.
232  */
233 void i2c_init(int speed, int slaveaddr)
234 {
235         /*
236                 setting up I2C support
237         */
238         unsigned int save_F,save_PF,rIICCON,rPCONA,rPDATA,rPCONF,rPUPF;
239
240         save_F = PCONF;
241         save_PF = PUPF;
242
243         rPCONF = ((save_F & ~(0xF))| 0xa);
244         rPUPF = (save_PF | 0x3);
245         PCONF = rPCONF; /*PF0:IICSCL, PF1:IICSDA*/
246         PUPF = rPUPF; /* Disable pull-up */
247
248         /* Configuring pin for WC pin of EEprom */
249         rPCONA = PCONA;
250         rPCONA &= ~(1<<9);
251         PCONA = rPCONA;
252
253         rPDATA = PDATA;
254         rPDATA &= ~(1<<9);
255         PDATA = rPDATA;
256
257         /*
258                 Enable ACK, IICCLK=MCLK/16, enable interrupt
259                 75MHz/16/(12+1) = 390625 Hz
260         */
261         rIICCON=(1<<7)|(0<<6)|(1<<5)|(0xC);
262         IICCON = rIICCON;
263
264         IICADD = slaveaddr;
265 }
266
267 /*
268  * Probe the given I2C chip address.  Returns 0 if a chip responded,
269  * not 0 on failure.
270  */
271 int i2c_probe(uchar chip)
272 {
273         /*
274                 not implemented
275         */
276
277         printf("i2c_probe chip %d\n", (int) chip);
278         return -1;
279 }
280
281 /*
282  * Read/Write interface:
283  *   chip:    I2C chip address, range 0..127
284  *   addr:    Memory (register) address within the chip
285  *   alen:    Number of bytes to use for addr (typically 1, 2 for larger
286  *              memories, 0 for register type devices with only one
287  *              register)
288  *   buffer:  Where to read/write the data
289  *   len:     How many bytes to read/write
290  *
291  *   Returns: 0 on success, not 0 on failure
292  */
293
294 #define S3C44B0X_rIIC_INTPEND               (1<<4)
295 #define S3C44B0X_rIIC_LAST_RECEIV_BIT       (1<<0)
296 #define S3C44B0X_rIIC_INTERRUPT_ENABLE      (1<<5)
297 #define S3C44B0_IIC_TIMEOUT 100
298
299 int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
300 {
301
302         int k, j, temp;
303         u32 rIICSTAT;
304
305         /*
306                 send the device offset
307         */
308
309         rIICSTAT = 0xD0;
310         IICSTAT = rIICSTAT;
311
312         IICDS = chip;   /* this is a write operation... */
313
314         rIICSTAT |= (1<<5);
315         IICSTAT = rIICSTAT;
316
317         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
318                 temp = IICCON;
319                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
320                 break;
321                 udelay(2000);
322         }
323         if (k==S3C44B0_IIC_TIMEOUT)
324                 return -1;
325
326         /* wait and check ACK */
327         temp = IICSTAT;
328         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
329                 return -1;
330
331         IICDS = addr;
332         IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
333
334         /* wait and check ACK */
335         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
336                 temp = IICCON;
337                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
338                 break;
339                 udelay(2000);
340         }
341         if (k==S3C44B0_IIC_TIMEOUT)
342                 return -1;
343
344         temp = IICSTAT;
345         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
346                 return -1;
347
348         /*
349                 now we can start with the read operation...
350         */
351
352         IICDS = chip | 0x01;    /* this is a read operation... */
353
354         rIICSTAT = 0x90; /*master recv*/
355         rIICSTAT |= (1<<5);
356         IICSTAT = rIICSTAT;
357
358         IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
359
360         /* wait and check ACK */
361         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
362                 temp = IICCON;
363                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
364                 break;
365                 udelay(2000);
366         }
367         if (k==S3C44B0_IIC_TIMEOUT)
368                 return -1;
369
370         temp = IICSTAT;
371         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
372                 return -1;
373
374         for (j=0; j<len-1; j++) {
375
376         /*clear pending bit to resume */
377
378         temp = IICCON & ~(S3C44B0X_rIIC_INTPEND);
379         IICCON = temp;
380
381         /* wait and check ACK */
382         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
383                 temp = IICCON;
384                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
385                 break;
386                 udelay(2000);
387         }
388         if (k==S3C44B0_IIC_TIMEOUT)
389                 return -1;
390
391
392                 buffer[j] = IICDS; /*save readed data*/
393
394     } /*end for(j)*/
395
396         /*
397                 reading the last data
398                 unset ACK generation
399         */
400         temp = IICCON & ~(S3C44B0X_rIIC_INTPEND | (1<<7));
401         IICCON = temp;
402
403         /* wait but NOT check ACK */
404         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
405                 temp = IICCON;
406                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
407                 break;
408                 udelay(2000);
409         }
410         if (k==S3C44B0_IIC_TIMEOUT)
411                 return -1;
412
413         buffer[j] = IICDS; /*save readed data*/
414
415         rIICSTAT = 0x90; /*master recv*/
416
417         /* Write operation Terminate sending STOP */
418         IICSTAT = rIICSTAT;
419         /*Clear Int Pending Bit to RESUME*/
420         temp = IICCON;
421         IICCON = temp & (~S3C44B0X_rIIC_INTPEND);
422
423         IICCON = IICCON | (1<<7);       /*restore ACK generation*/
424
425         return 0;
426 }
427
428 int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
429 {
430         int j, k;
431         u32 rIICSTAT, temp;
432
433
434         /*
435                 send the device offset
436         */
437
438         rIICSTAT = 0xD0;
439         IICSTAT = rIICSTAT;
440
441         IICDS = chip;   /* this is a write operation... */
442
443         rIICSTAT |= (1<<5);
444         IICSTAT = rIICSTAT;
445
446         IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
447
448         /* wait and check ACK */
449         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
450                 temp = IICCON;
451                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
452                 break;
453                 udelay(2000);
454         }
455         if (k==S3C44B0_IIC_TIMEOUT)
456                 return -1;
457
458         temp = IICSTAT;
459         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
460                 return -1;
461
462         IICDS = addr;
463         IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
464
465         /* wait and check ACK */
466         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
467                 temp = IICCON;
468                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
469                 break;
470                 udelay(2000);
471         }
472         if (k==S3C44B0_IIC_TIMEOUT)
473           return -1;
474
475         temp = IICSTAT;
476         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
477                 return -1;
478
479         /*
480                 now we can start with the read write operation
481         */
482         for (j=0; j<len; j++) {
483
484                 IICDS = buffer[j]; /*prerare data to write*/
485
486                 /*clear pending bit to resume*/
487
488                 temp = IICCON & ~(S3C44B0X_rIIC_INTPEND);
489                 IICCON = temp;
490
491                 /* wait but NOT check ACK */
492                 for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
493                         temp = IICCON;
494                         if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
495                         break;
496
497                         udelay(2000);
498                 }
499
500                 if (k==S3C44B0_IIC_TIMEOUT)
501                         return -1;
502
503         } /* end for(j) */
504
505         /* sending stop to terminate */
506         rIICSTAT = 0xD0;  /*master send*/
507         IICSTAT = rIICSTAT;
508         /*Clear Int Pending Bit to RESUME*/
509         temp = IICCON;
510         IICCON = temp & (~S3C44B0X_rIIC_INTPEND);
511
512         return 0;
513 }