#include "s3c_board.h" #include "s3c2440.h" unsigned int s3c2440_get_fclk(void) { struct s3c2440_clock_power *clk_power = s3c2440_get_base_clock_power(); unsigned int r, m, p, s; r = clk_power->MPLLCON; m = ((r & 0xFF000) >> 12) + 8; p = ((r & 0x003F0) >> 4) + 2; s = r & 0x3; return (SYS_CLK_FREQ * m * 2) / (p << s); } unsigned int s3c2440_get_hclk(void) { struct s3c2440_clock_power * const clk_power = s3c2440_get_base_clock_power(); unsigned int fclk = s3c2440_get_fclk(); if (clk_power->CLKDIVN & 0x6) { if ((clk_power->CLKDIVN & 0x6)==2) return fclk/2; if ((clk_power->CLKDIVN & 0x6)==6) return (clk_power->CAMDIVN & 0x100) ? fclk/6 : fclk/3; if ((clk_power->CLKDIVN & 0x6)==4) return (clk_power->CAMDIVN & 0x200) ? fclk/8 : fclk/4; return fclk; } return fclk; } unsigned int s3c2440_get_pclk(void) { struct s3c2440_clock_power * const clk_power = s3c2440_get_base_clock_power(); unsigned int hclk = s3c2440_get_hclk(); return (clk_power->CLKDIVN & 0x1) ? hclk/2 : hclk; } unsigned int s3c2440_get_uclk(void) { struct s3c2440_clock_power *clk_power = s3c2440_get_base_clock_power(); unsigned int r, m, p, s; r = clk_power->UPLLCON; m = ((r & 0xFF000) >> 12) + 8; p = ((r & 0x003F0) >> 4) + 2; s = r & 0x3; return (SYS_CLK_FREQ * m) / (p << s); } void s3c2440_set_baudrate(unsigned int baudrate, int index) { struct s3c2440_uart *uart = s3c2440_get_base_uart(index); unsigned int reg = 0; int i; reg = s3c2440_get_pclk() / (16 * baudrate) - 1; uart->UBRDIV = reg; for (i = 0; i < 100; i++); } int s3c2440_serial_init(unsigned int baudrate, int index) { struct s3c2440_uart *uart = s3c2440_get_base_uart(index); /* FIFO enable, Tx/Rx FIFO clear */ uart->UFCON = 0x07; uart->UMCON = 0x0; /* Normal,No parity,1 stop,8 bit */ uart->ULCON = 0x3; /* * tx=level,rx=edge,disable timeout int.,enable rx error int., * normal,interrupt or polling */ uart->UCON = (1<<8) | (1<<2) | (1<<0); // uart->UMCON = 0x1; /* RTS up */ s3c2440_set_baudrate(baudrate, index); return (0); } int s3c2440_serail_set_afc(int enable, int index) { if (index != S3C2440_UART0 || index != S3C2440_UART1) return -1; struct s3c2440_uart *uart = s3c2440_get_base_uart(index); if (enable) { uart->UMCON = (1<<4); } else { uart->UMCON = 0; uart->UMCON = 0; uart->UMCON = 0; uart->UMCON = 1; } return 0; } /* * Read a single byte from the serial port. Returns 1 on success, 0 * otherwise. When the function is succesfull, the character read is * written into its argument c. */ int s3c2440_serial_getc (int index) { struct s3c2440_uart *uart = s3c2440_get_base_uart(index); /* wait for character to arrive */ //while (!(uart->UTRSTAT & 0x1)); while(!(uart->UFSTAT & 0x1F)); return uart->URXH & 0xff; } #if 0 static int hwflow = 0; /* turned off by default */ int hwflow_onoff(int on) { switch(on) { case 0: default: break; /* return current */ case 1: hwflow = 1; /* turn on */ break; case -1: hwflow = 0; /* turn off */ break; } return hwflow; } #endif #if 0 static int be_quiet = 0; void disable_putc(void) { be_quiet = 1; } void enable_putc(void) { be_quiet = 0; } #endif /* * Output a single byte to the serial port. */ void s3c2440_serial_putc (char c, int index) { struct s3c2440_uart *uart = s3c2440_get_base_uart(index); /* wait for room in the tx FIFO */ //while ((!(uart->UTRSTAT & 0x2))); while (uart->UFSTAT & (1<<14)); uart->UTXH = c; } void s3c2440_serial_puts(const char *s, int index) { while (*s) { if (*s == '\n') /* If \n, also do \r */ s3c2440_serial_putc('\r', index); s3c2440_serial_putc (*s++, index); } } void s3c2440_interrupt_enable(unsigned int mask) { mask = ~mask; struct s3c2440_interrupt *interrupt = s3c2440_get_base_interrupt(); interrupt->INTMSK &= mask; } void s3c2440_interrupt_disable(unsigned int mask) { struct s3c2440_interrupt *interrupt = s3c2440_get_base_interrupt(); interrupt->INTMSK |= mask; } void s3c2440_sub_interrupt_enable(unsigned int mask) { mask = ~mask; struct s3c2440_interrupt *interrupt = s3c2440_get_base_interrupt(); interrupt->INTSUBMSK &= mask; } void s3c2440_sub_interrupt_disable(unsigned int mask) { struct s3c2440_interrupt *interrupt = s3c2440_get_base_interrupt(); interrupt->INTSUBMSK |= mask; }