1379be585SJean-Christophe PLAGNIOL-VILLARD /* 2237ce0feSMarek Vasut * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> 3237ce0feSMarek Vasut * 4379be585SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2002 5379be585SJean-Christophe PLAGNIOL-VILLARD * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> 6379be585SJean-Christophe PLAGNIOL-VILLARD * 7379be585SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2002 8379be585SJean-Christophe PLAGNIOL-VILLARD * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 9379be585SJean-Christophe PLAGNIOL-VILLARD * Marius Groeger <mgroeger@sysgo.de> 10379be585SJean-Christophe PLAGNIOL-VILLARD * 11379be585SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2002 12379be585SJean-Christophe PLAGNIOL-VILLARD * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 13379be585SJean-Christophe PLAGNIOL-VILLARD * Alex Zuepke <azu@sysgo.de> 14379be585SJean-Christophe PLAGNIOL-VILLARD * 15379be585SJean-Christophe PLAGNIOL-VILLARD * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) 16379be585SJean-Christophe PLAGNIOL-VILLARD * 17379be585SJean-Christophe PLAGNIOL-VILLARD * This program is free software; you can redistribute it and/or modify 18379be585SJean-Christophe PLAGNIOL-VILLARD * it under the terms of the GNU General Public License as published by 19379be585SJean-Christophe PLAGNIOL-VILLARD * the Free Software Foundation; either version 2 of the License, or 20379be585SJean-Christophe PLAGNIOL-VILLARD * (at your option) any later version. 21379be585SJean-Christophe PLAGNIOL-VILLARD * 22379be585SJean-Christophe PLAGNIOL-VILLARD * This program is distributed in the hope that it will be useful, 23379be585SJean-Christophe PLAGNIOL-VILLARD * but WITHOUT ANY WARRANTY; without even the implied warranty of 24379be585SJean-Christophe PLAGNIOL-VILLARD * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25379be585SJean-Christophe PLAGNIOL-VILLARD * GNU General Public License for more details. 26379be585SJean-Christophe PLAGNIOL-VILLARD * 27379be585SJean-Christophe PLAGNIOL-VILLARD * You should have received a copy of the GNU General Public License 28379be585SJean-Christophe PLAGNIOL-VILLARD * along with this program; if not, write to the Free Software 29379be585SJean-Christophe PLAGNIOL-VILLARD * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 30379be585SJean-Christophe PLAGNIOL-VILLARD * 31379be585SJean-Christophe PLAGNIOL-VILLARD */ 32379be585SJean-Christophe PLAGNIOL-VILLARD 33379be585SJean-Christophe PLAGNIOL-VILLARD #include <common.h> 34379be585SJean-Christophe PLAGNIOL-VILLARD #include <watchdog.h> 35379be585SJean-Christophe PLAGNIOL-VILLARD #include <serial.h> 36379be585SJean-Christophe PLAGNIOL-VILLARD #include <asm/arch/pxa-regs.h> 37237ce0feSMarek Vasut #include <asm/arch/regs-uart.h> 383ba8bf7cSMarek Vasut #include <asm/io.h> 39407e6a28SMarek Vasut #include <linux/compiler.h> 40379be585SJean-Christophe PLAGNIOL-VILLARD 41379be585SJean-Christophe PLAGNIOL-VILLARD DECLARE_GLOBAL_DATA_PTR; 42379be585SJean-Christophe PLAGNIOL-VILLARD 43237ce0feSMarek Vasut /* 44237ce0feSMarek Vasut * The numbering scheme differs here for PXA25x, PXA27x and PXA3xx so we can 45237ce0feSMarek Vasut * easily handle enabling of clock. 46237ce0feSMarek Vasut */ 47237ce0feSMarek Vasut #ifdef CONFIG_CPU_MONAHANS 48237ce0feSMarek Vasut #define UART_CLK_BASE CKENA_21_BTUART 49237ce0feSMarek Vasut #define UART_CLK_REG CKENA 50237ce0feSMarek Vasut #define BTUART_INDEX 0 51237ce0feSMarek Vasut #define FFUART_INDEX 1 52379be585SJean-Christophe PLAGNIOL-VILLARD #define STUART_INDEX 2 53abc20abaSMarek Vasut #elif CONFIG_CPU_PXA25X 54237ce0feSMarek Vasut #define UART_CLK_BASE (1 << 4) /* HWUART */ 55237ce0feSMarek Vasut #define UART_CLK_REG CKEN 56237ce0feSMarek Vasut #define HWUART_INDEX 0 57237ce0feSMarek Vasut #define STUART_INDEX 1 58237ce0feSMarek Vasut #define FFUART_INDEX 2 59237ce0feSMarek Vasut #define BTUART_INDEX 3 60237ce0feSMarek Vasut #else /* PXA27x */ 61237ce0feSMarek Vasut #define UART_CLK_BASE CKEN5_STUART 62237ce0feSMarek Vasut #define UART_CLK_REG CKEN 63237ce0feSMarek Vasut #define STUART_INDEX 0 64237ce0feSMarek Vasut #define FFUART_INDEX 1 65237ce0feSMarek Vasut #define BTUART_INDEX 2 66237ce0feSMarek Vasut #endif 67237ce0feSMarek Vasut 68237ce0feSMarek Vasut /* 69237ce0feSMarek Vasut * Only PXA250 has HWUART, to avoid poluting the code with more macros, 70237ce0feSMarek Vasut * artificially introduce this. 71237ce0feSMarek Vasut */ 72abc20abaSMarek Vasut #ifndef CONFIG_CPU_PXA25X 73237ce0feSMarek Vasut #define HWUART_INDEX 0xff 74237ce0feSMarek Vasut #endif 75379be585SJean-Christophe PLAGNIOL-VILLARD 76379be585SJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SERIAL_MULTI 77379be585SJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_FFUART) 78379be585SJean-Christophe PLAGNIOL-VILLARD #define UART_INDEX FFUART_INDEX 79379be585SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_BTUART) 80379be585SJean-Christophe PLAGNIOL-VILLARD #define UART_INDEX BTUART_INDEX 81379be585SJean-Christophe PLAGNIOL-VILLARD #elif defined(CONFIG_STUART) 82379be585SJean-Christophe PLAGNIOL-VILLARD #define UART_INDEX STUART_INDEX 83237ce0feSMarek Vasut #elif defined(CONFIG_HWUART) 84237ce0feSMarek Vasut #define UART_INDEX HWUART_INDEX 85379be585SJean-Christophe PLAGNIOL-VILLARD #else 86237ce0feSMarek Vasut #error "Please select CONFIG_(FF|BT|ST|HW)UART in board config file." 87379be585SJean-Christophe PLAGNIOL-VILLARD #endif 88379be585SJean-Christophe PLAGNIOL-VILLARD #endif 89379be585SJean-Christophe PLAGNIOL-VILLARD 90*4808f106SMarek Vasut static uint32_t pxa_uart_get_baud_divider(void) 91379be585SJean-Christophe PLAGNIOL-VILLARD { 92379be585SJean-Christophe PLAGNIOL-VILLARD if (gd->baudrate == 1200) 93237ce0feSMarek Vasut return 768; 94379be585SJean-Christophe PLAGNIOL-VILLARD else if (gd->baudrate == 9600) 95237ce0feSMarek Vasut return 96; 96379be585SJean-Christophe PLAGNIOL-VILLARD else if (gd->baudrate == 19200) 97237ce0feSMarek Vasut return 48; 98379be585SJean-Christophe PLAGNIOL-VILLARD else if (gd->baudrate == 38400) 99237ce0feSMarek Vasut return 24; 100379be585SJean-Christophe PLAGNIOL-VILLARD else if (gd->baudrate == 57600) 101237ce0feSMarek Vasut return 16; 102379be585SJean-Christophe PLAGNIOL-VILLARD else if (gd->baudrate == 115200) 103237ce0feSMarek Vasut return 8; 104237ce0feSMarek Vasut else /* Unsupported baudrate */ 105237ce0feSMarek Vasut return 0; 106237ce0feSMarek Vasut } 107379be585SJean-Christophe PLAGNIOL-VILLARD 108*4808f106SMarek Vasut static struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index) 109237ce0feSMarek Vasut { 110379be585SJean-Christophe PLAGNIOL-VILLARD switch (uart_index) { 111237ce0feSMarek Vasut case FFUART_INDEX: return (struct pxa_uart_regs *)FFUART_BASE; 112237ce0feSMarek Vasut case BTUART_INDEX: return (struct pxa_uart_regs *)BTUART_BASE; 113237ce0feSMarek Vasut case STUART_INDEX: return (struct pxa_uart_regs *)STUART_BASE; 114237ce0feSMarek Vasut case HWUART_INDEX: return (struct pxa_uart_regs *)HWUART_BASE; 115379be585SJean-Christophe PLAGNIOL-VILLARD default: 116237ce0feSMarek Vasut return NULL; 117379be585SJean-Christophe PLAGNIOL-VILLARD } 118379be585SJean-Christophe PLAGNIOL-VILLARD } 119379be585SJean-Christophe PLAGNIOL-VILLARD 120*4808f106SMarek Vasut static void pxa_uart_toggle_clock(uint32_t uart_index, int enable) 121237ce0feSMarek Vasut { 122237ce0feSMarek Vasut uint32_t clk_reg, clk_offset, reg; 123237ce0feSMarek Vasut 124237ce0feSMarek Vasut clk_reg = UART_CLK_REG; 125237ce0feSMarek Vasut clk_offset = UART_CLK_BASE << uart_index; 126237ce0feSMarek Vasut 127237ce0feSMarek Vasut reg = readl(clk_reg); 128237ce0feSMarek Vasut 129237ce0feSMarek Vasut if (enable) 130237ce0feSMarek Vasut reg |= clk_offset; 131237ce0feSMarek Vasut else 132237ce0feSMarek Vasut reg &= ~clk_offset; 133237ce0feSMarek Vasut 134237ce0feSMarek Vasut writel(reg, clk_reg); 135237ce0feSMarek Vasut } 136237ce0feSMarek Vasut 137237ce0feSMarek Vasut /* 138237ce0feSMarek Vasut * Enable clock and set baud rate, parity etc. 139237ce0feSMarek Vasut */ 140237ce0feSMarek Vasut void pxa_setbrg_dev(uint32_t uart_index) 141237ce0feSMarek Vasut { 142237ce0feSMarek Vasut uint32_t divider = 0; 143237ce0feSMarek Vasut struct pxa_uart_regs *uart_regs; 144237ce0feSMarek Vasut 145237ce0feSMarek Vasut divider = pxa_uart_get_baud_divider(); 146237ce0feSMarek Vasut if (!divider) 147237ce0feSMarek Vasut hang(); 148237ce0feSMarek Vasut 149237ce0feSMarek Vasut uart_regs = pxa_uart_index_to_regs(uart_index); 150237ce0feSMarek Vasut if (!uart_regs) 151237ce0feSMarek Vasut hang(); 152237ce0feSMarek Vasut 153237ce0feSMarek Vasut pxa_uart_toggle_clock(uart_index, 1); 154237ce0feSMarek Vasut 155237ce0feSMarek Vasut /* Disable interrupts and FIFOs */ 156237ce0feSMarek Vasut writel(0, &uart_regs->ier); 157237ce0feSMarek Vasut writel(0, &uart_regs->fcr); 158237ce0feSMarek Vasut 159237ce0feSMarek Vasut /* Set baud rate */ 160237ce0feSMarek Vasut writel(LCR_WLS0 | LCR_WLS1 | LCR_DLAB, &uart_regs->lcr); 161237ce0feSMarek Vasut writel(divider & 0xff, &uart_regs->dll); 162237ce0feSMarek Vasut writel(divider >> 8, &uart_regs->dlh); 163237ce0feSMarek Vasut writel(LCR_WLS0 | LCR_WLS1, &uart_regs->lcr); 164237ce0feSMarek Vasut 165237ce0feSMarek Vasut /* Enable UART */ 166237ce0feSMarek Vasut writel(IER_UUE, &uart_regs->ier); 167237ce0feSMarek Vasut } 168379be585SJean-Christophe PLAGNIOL-VILLARD 169379be585SJean-Christophe PLAGNIOL-VILLARD /* 170379be585SJean-Christophe PLAGNIOL-VILLARD * Initialise the serial port with the given baudrate. The settings 171379be585SJean-Christophe PLAGNIOL-VILLARD * are always 8 data bits, no parity, 1 stop bit, no start bits. 172379be585SJean-Christophe PLAGNIOL-VILLARD */ 173379be585SJean-Christophe PLAGNIOL-VILLARD int pxa_init_dev(unsigned int uart_index) 174379be585SJean-Christophe PLAGNIOL-VILLARD { 175379be585SJean-Christophe PLAGNIOL-VILLARD pxa_setbrg_dev (uart_index); 176237ce0feSMarek Vasut return 0; 177379be585SJean-Christophe PLAGNIOL-VILLARD } 178379be585SJean-Christophe PLAGNIOL-VILLARD 179379be585SJean-Christophe PLAGNIOL-VILLARD /* 180379be585SJean-Christophe PLAGNIOL-VILLARD * Output a single byte to the serial port. 181379be585SJean-Christophe PLAGNIOL-VILLARD */ 182379be585SJean-Christophe PLAGNIOL-VILLARD void pxa_putc_dev(unsigned int uart_index, const char c) 183379be585SJean-Christophe PLAGNIOL-VILLARD { 184237ce0feSMarek Vasut struct pxa_uart_regs *uart_regs; 185379be585SJean-Christophe PLAGNIOL-VILLARD 186237ce0feSMarek Vasut uart_regs = pxa_uart_index_to_regs(uart_index); 187237ce0feSMarek Vasut if (!uart_regs) 188237ce0feSMarek Vasut hang(); 189379be585SJean-Christophe PLAGNIOL-VILLARD 190237ce0feSMarek Vasut while (!(readl(&uart_regs->lsr) & LSR_TEMT)) 191237ce0feSMarek Vasut WATCHDOG_RESET(); 192237ce0feSMarek Vasut writel(c, &uart_regs->thr); 193379be585SJean-Christophe PLAGNIOL-VILLARD 194379be585SJean-Christophe PLAGNIOL-VILLARD /* If \n, also do \r */ 195379be585SJean-Christophe PLAGNIOL-VILLARD if (c == '\n') 196379be585SJean-Christophe PLAGNIOL-VILLARD pxa_putc_dev (uart_index,'\r'); 197379be585SJean-Christophe PLAGNIOL-VILLARD } 198379be585SJean-Christophe PLAGNIOL-VILLARD 199379be585SJean-Christophe PLAGNIOL-VILLARD /* 200379be585SJean-Christophe PLAGNIOL-VILLARD * Read a single byte from the serial port. Returns 1 on success, 0 201379be585SJean-Christophe PLAGNIOL-VILLARD * otherwise. When the function is succesfull, the character read is 202379be585SJean-Christophe PLAGNIOL-VILLARD * written into its argument c. 203379be585SJean-Christophe PLAGNIOL-VILLARD */ 204379be585SJean-Christophe PLAGNIOL-VILLARD int pxa_tstc_dev(unsigned int uart_index) 205379be585SJean-Christophe PLAGNIOL-VILLARD { 206237ce0feSMarek Vasut struct pxa_uart_regs *uart_regs; 207237ce0feSMarek Vasut 208237ce0feSMarek Vasut uart_regs = pxa_uart_index_to_regs(uart_index); 209237ce0feSMarek Vasut if (!uart_regs) 210379be585SJean-Christophe PLAGNIOL-VILLARD return -1; 211237ce0feSMarek Vasut 212237ce0feSMarek Vasut return readl(&uart_regs->lsr) & LSR_DR; 213379be585SJean-Christophe PLAGNIOL-VILLARD } 214379be585SJean-Christophe PLAGNIOL-VILLARD 215379be585SJean-Christophe PLAGNIOL-VILLARD /* 216379be585SJean-Christophe PLAGNIOL-VILLARD * Read a single byte from the serial port. Returns 1 on success, 0 217379be585SJean-Christophe PLAGNIOL-VILLARD * otherwise. When the function is succesfull, the character read is 218379be585SJean-Christophe PLAGNIOL-VILLARD * written into its argument c. 219379be585SJean-Christophe PLAGNIOL-VILLARD */ 220379be585SJean-Christophe PLAGNIOL-VILLARD int pxa_getc_dev(unsigned int uart_index) 221379be585SJean-Christophe PLAGNIOL-VILLARD { 222237ce0feSMarek Vasut struct pxa_uart_regs *uart_regs; 223379be585SJean-Christophe PLAGNIOL-VILLARD 224237ce0feSMarek Vasut uart_regs = pxa_uart_index_to_regs(uart_index); 225237ce0feSMarek Vasut if (!uart_regs) 226379be585SJean-Christophe PLAGNIOL-VILLARD return -1; 227237ce0feSMarek Vasut 228237ce0feSMarek Vasut while (!(readl(&uart_regs->lsr) & LSR_DR)) 229237ce0feSMarek Vasut WATCHDOG_RESET(); 230237ce0feSMarek Vasut return readl(&uart_regs->rbr) & 0xff; 231379be585SJean-Christophe PLAGNIOL-VILLARD } 232379be585SJean-Christophe PLAGNIOL-VILLARD 233237ce0feSMarek Vasut void pxa_puts_dev(unsigned int uart_index, const char *s) 234379be585SJean-Christophe PLAGNIOL-VILLARD { 235237ce0feSMarek Vasut while (*s) 236379be585SJean-Christophe PLAGNIOL-VILLARD pxa_putc_dev(uart_index, *s++); 237379be585SJean-Christophe PLAGNIOL-VILLARD } 238379be585SJean-Christophe PLAGNIOL-VILLARD 239237ce0feSMarek Vasut #define pxa_uart(uart, UART) \ 240237ce0feSMarek Vasut int uart##_init(void) \ 241237ce0feSMarek Vasut { \ 242237ce0feSMarek Vasut return pxa_init_dev(UART##_INDEX); \ 243237ce0feSMarek Vasut } \ 244237ce0feSMarek Vasut \ 245237ce0feSMarek Vasut void uart##_setbrg(void) \ 246237ce0feSMarek Vasut { \ 247237ce0feSMarek Vasut return pxa_setbrg_dev(UART##_INDEX); \ 248237ce0feSMarek Vasut } \ 249237ce0feSMarek Vasut \ 250237ce0feSMarek Vasut void uart##_putc(const char c) \ 251237ce0feSMarek Vasut { \ 252237ce0feSMarek Vasut return pxa_putc_dev(UART##_INDEX, c); \ 253237ce0feSMarek Vasut } \ 254237ce0feSMarek Vasut \ 255237ce0feSMarek Vasut void uart##_puts(const char *s) \ 256237ce0feSMarek Vasut { \ 257237ce0feSMarek Vasut return pxa_puts_dev(UART##_INDEX, s); \ 258237ce0feSMarek Vasut } \ 259237ce0feSMarek Vasut \ 260237ce0feSMarek Vasut int uart##_getc(void) \ 261237ce0feSMarek Vasut { \ 262237ce0feSMarek Vasut return pxa_getc_dev(UART##_INDEX); \ 263237ce0feSMarek Vasut } \ 264237ce0feSMarek Vasut \ 265237ce0feSMarek Vasut int uart##_tstc(void) \ 266237ce0feSMarek Vasut { \ 267237ce0feSMarek Vasut return pxa_tstc_dev(UART##_INDEX); \ 268237ce0feSMarek Vasut } \ 269379be585SJean-Christophe PLAGNIOL-VILLARD 270237ce0feSMarek Vasut #define pxa_uart_desc(uart) \ 271237ce0feSMarek Vasut struct serial_device serial_##uart##_device = \ 272237ce0feSMarek Vasut { \ 27390bad891SMarek Vasut .name = "serial_"#uart, \ 27490bad891SMarek Vasut .start = uart##_init, \ 27590bad891SMarek Vasut .stop = NULL, \ 27690bad891SMarek Vasut .setbrg = uart##_setbrg, \ 27790bad891SMarek Vasut .getc = uart##_getc, \ 27890bad891SMarek Vasut .tstc = uart##_tstc, \ 27990bad891SMarek Vasut .putc = uart##_putc, \ 28090bad891SMarek Vasut .puts = uart##_puts, \ 281379be585SJean-Christophe PLAGNIOL-VILLARD }; 282237ce0feSMarek Vasut 283237ce0feSMarek Vasut #define pxa_uart_multi(uart, UART) \ 284237ce0feSMarek Vasut pxa_uart(uart, UART) \ 285237ce0feSMarek Vasut pxa_uart_desc(uart) 286237ce0feSMarek Vasut 287237ce0feSMarek Vasut #if defined(CONFIG_HWUART) 288237ce0feSMarek Vasut pxa_uart_multi(hwuart, HWUART) 289379be585SJean-Christophe PLAGNIOL-VILLARD #endif 290379be585SJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_STUART) 291237ce0feSMarek Vasut pxa_uart_multi(stuart, STUART) 292379be585SJean-Christophe PLAGNIOL-VILLARD #endif 293237ce0feSMarek Vasut #if defined(CONFIG_FFUART) 294237ce0feSMarek Vasut pxa_uart_multi(ffuart, FFUART) 295237ce0feSMarek Vasut #endif 296237ce0feSMarek Vasut #if defined(CONFIG_BTUART) 297237ce0feSMarek Vasut pxa_uart_multi(btuart, BTUART) 298237ce0feSMarek Vasut #endif 299379be585SJean-Christophe PLAGNIOL-VILLARD 300379be585SJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SERIAL_MULTI 301237ce0feSMarek Vasut pxa_uart(serial, UART) 302407e6a28SMarek Vasut #else 303407e6a28SMarek Vasut __weak struct serial_device *default_serial_console(void) 304407e6a28SMarek Vasut { 305407e6a28SMarek Vasut #if CONFIG_CONS_INDEX == 1 306407e6a28SMarek Vasut return &serial_hwuart_device; 307407e6a28SMarek Vasut #elif CONFIG_CONS_INDEX == 2 308407e6a28SMarek Vasut return &serial_stuart_device; 309407e6a28SMarek Vasut #elif CONFIG_CONS_INDEX == 3 310407e6a28SMarek Vasut return &serial_ffuart_device; 311407e6a28SMarek Vasut #elif CONFIG_CONS_INDEX == 4 312407e6a28SMarek Vasut return &serial_btuart_device; 313407e6a28SMarek Vasut #else 314407e6a28SMarek Vasut #error "Bad CONFIG_CONS_INDEX." 315407e6a28SMarek Vasut #endif 316407e6a28SMarek Vasut } 317237ce0feSMarek Vasut #endif 318