uboot/cpu/s3c44b0/cpu.c
<<
>>
Prefs
   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
  35static 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
  46int cpu_init (void)
  47{
  48        icache_enable();
  49
  50        return 0;
  51}
  52
  53int 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
  66void 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
  87int 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
  96void 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
 118void icache_disable (void)
 119{
 120        ulong reg;
 121
 122        reg = SYSCFG;
 123        reg &= ~0x00000006; /* 8kB */
 124        SYSCFG = reg;
 125}
 126
 127int icache_status (void)
 128{
 129        return 0;
 130}
 131
 132void dcache_enable (void)
 133{
 134        icache_enable();
 135}
 136
 137void dcache_disable (void)
 138{
 139        icache_disable();
 140}
 141
 142int 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
 158int 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
 191int 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
 211void 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 */
 233void 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 */
 271int 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
 299int 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
 428int 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}
 514