uboot/drivers/serial/serial_max3100.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2003
   3 *
   4 * Pantelis Antoniou <panto@intracom.gr>
   5 * Intracom S.A.
   6 *
   7 * See file CREDITS for list of people who contributed to this
   8 * project.
   9 *
  10 * This program is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU General Public License as
  12 * published by the Free Software Foundation; either version 2 of
  13 * the License, or (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, write to the Free Software
  22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23 * MA 02111-1307 USA
  24 */
  25
  26#include <common.h>
  27#include <watchdog.h>
  28
  29DECLARE_GLOBAL_DATA_PTR;
  30
  31/**************************************************************/
  32
  33/* convienient macros */
  34#define MAX3100_SPI_RXD() (MAX3100_SPI_RXD_PORT & MAX3100_SPI_RXD_BIT)
  35
  36#define MAX3100_SPI_TXD(x) \
  37        do { \
  38                if (x) \
  39                        MAX3100_SPI_TXD_PORT |=  MAX3100_SPI_TXD_BIT; \
  40                else \
  41                        MAX3100_SPI_TXD_PORT &= ~MAX3100_SPI_TXD_BIT; \
  42        } while(0)
  43
  44#define MAX3100_SPI_CLK(x) \
  45        do { \
  46                if (x) \
  47                        MAX3100_SPI_CLK_PORT |=  MAX3100_SPI_CLK_BIT; \
  48                else \
  49                        MAX3100_SPI_CLK_PORT &= ~MAX3100_SPI_CLK_BIT; \
  50        } while(0)
  51
  52#define MAX3100_SPI_CLK_TOGGLE() (MAX3100_SPI_CLK_PORT ^= MAX3100_SPI_CLK_BIT)
  53
  54#define MAX3100_CS(x) \
  55        do { \
  56                if (x) \
  57                        MAX3100_CS_PORT |=  MAX3100_CS_BIT; \
  58                else \
  59                        MAX3100_CS_PORT &= ~MAX3100_CS_BIT; \
  60        } while(0)
  61
  62/**************************************************************/
  63
  64/* MAX3100 definitions */
  65
  66#define MAX3100_WC      (3 << 14)               /* write configuration */
  67#define MAX3100_RC      (1 << 14)               /* read  configuration */
  68#define MAX3100_WD      (2 << 14)               /* write data          */
  69#define MAX3100_RD      (0 << 14)               /* read  data          */
  70
  71/* configuration register bits */
  72#define MAX3100_FEN     (1 << 13)               /* FIFO enable           */
  73#define MAX3100_SHDN    (1 << 12)               /* shutdown bit          */
  74#define MAX3100_TM      (1 << 11)               /* T bit irq mask        */
  75#define MAX3100_RM      (1 << 10)               /* R bit irq mask        */
  76#define MAX3100_PM      (1 <<  9)               /* P bit irq mask        */
  77#define MAX3100_RAM     (1 <<  8)               /* mask for RA/FE bit    */
  78#define MAX3100_IR      (1 <<  7)               /* IRDA timing mode      */
  79#define MAX3100_ST      (1 <<  6)               /* transmit stop bit     */
  80#define MAX3100_PE      (1 <<  5)               /* parity enable bit     */
  81#define MAX3100_L       (1 <<  4)               /* Length bit            */
  82#define MAX3100_B_MASK  (0x000F)                /* baud rate bits mask   */
  83#define MAX3100_B(x)    ((x) & 0x000F)  /* baud rate select bits */
  84
  85/* data register bits (write) */
  86#define MAX3100_TE      (1 << 10)               /* transmit enable bit (active low)        */
  87#define MAX3100_RTS     (1 <<  9)               /* request-to-send bit (inverted ~RTS pin) */
  88
  89/* data register bits (read) */
  90#define MAX3100_RA      (1 << 10)               /* receiver activity when in shutdown mode */
  91#define MAX3100_FE      (1 << 10)               /* framing error when in normal mode       */
  92#define MAX3100_CTS     (1 <<  9)               /* clear-to-send bit (inverted ~CTS pin)   */
  93
  94/* data register bits (both directions) */
  95#define MAX3100_R       (1 << 15)               /* receive bit    */
  96#define MAX3100_T       (1 << 14)               /* transmit bit   */
  97#define MAX3100_P       (1 <<  8)               /* parity bit     */
  98#define MAX3100_D_MASK  0x00FF                  /* data bits mask */
  99#define MAX3100_D(x)    ((x) & 0x00FF)          /* data bits      */
 100
 101/* these definitions are valid only for fOSC = 3.6864MHz */
 102#define MAX3100_B_230400        MAX3100_B(0)
 103#define MAX3100_B_115200        MAX3100_B(1)
 104#define MAX3100_B_57600         MAX3100_B(2)
 105#define MAX3100_B_38400         MAX3100_B(9)
 106#define MAX3100_B_19200         MAX3100_B(10)
 107#define MAX3100_B_9600          MAX3100_B(11)
 108#define MAX3100_B_4800          MAX3100_B(12)
 109#define MAX3100_B_2400          MAX3100_B(13)
 110#define MAX3100_B_1200          MAX3100_B(14)
 111#define MAX3100_B_600           MAX3100_B(15)
 112
 113/**************************************************************/
 114
 115static inline unsigned int max3100_transfer(unsigned int val)
 116{
 117        unsigned int rx;
 118        int b;
 119
 120        MAX3100_SPI_CLK(0);
 121        MAX3100_CS(0);
 122
 123        rx = 0; b = 16;
 124        while (--b >= 0) {
 125                MAX3100_SPI_TXD(val & 0x8000);
 126                val <<= 1;
 127                MAX3100_SPI_CLK_TOGGLE();
 128                udelay(1);
 129                rx <<= 1;
 130                if (MAX3100_SPI_RXD())
 131                        rx |= 1;
 132                MAX3100_SPI_CLK_TOGGLE();
 133                udelay(1);
 134        }
 135
 136        MAX3100_SPI_CLK(1);
 137        MAX3100_CS(1);
 138
 139        return rx;
 140}
 141
 142/**************************************************************/
 143
 144/* must be power of 2 */
 145#define RXFIFO_SZ       16
 146
 147static int rxfifo_cnt;
 148static int rxfifo_in;
 149static int rxfifo_out;
 150static unsigned char rxfifo_buf[16];
 151
 152static void max3100_putc(int c)
 153{
 154        unsigned int rx;
 155
 156        while (((rx = max3100_transfer(MAX3100_RC)) & MAX3100_T) == 0)
 157                WATCHDOG_RESET();
 158
 159        rx = max3100_transfer(MAX3100_WD | (c & 0xff));
 160        if ((rx & MAX3100_RD) != 0 && rxfifo_cnt < RXFIFO_SZ) {
 161                rxfifo_cnt++;
 162                rxfifo_buf[rxfifo_in++] = rx & 0xff;
 163                rxfifo_in &= RXFIFO_SZ - 1;
 164        }
 165}
 166
 167static int max3100_getc(void)
 168{
 169        int c;
 170        unsigned int rx;
 171
 172        while (rxfifo_cnt == 0) {
 173                rx = max3100_transfer(MAX3100_RD);
 174                if ((rx & MAX3100_R) != 0) {
 175                        do {
 176                                rxfifo_cnt++;
 177                                rxfifo_buf[rxfifo_in++] = rx & 0xff;
 178                                rxfifo_in &= RXFIFO_SZ - 1;
 179
 180                                if (rxfifo_cnt >= RXFIFO_SZ)
 181                                        break;
 182                        } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
 183                }
 184                WATCHDOG_RESET();
 185        }
 186
 187        rxfifo_cnt--;
 188        c = rxfifo_buf[rxfifo_out++];
 189        rxfifo_out &= RXFIFO_SZ - 1;
 190        return c;
 191}
 192
 193static int max3100_tstc(void)
 194{
 195        unsigned int rx;
 196
 197        if (rxfifo_cnt > 0)
 198                return 1;
 199
 200        rx = max3100_transfer(MAX3100_RD);
 201        if ((rx & MAX3100_R) == 0)
 202                return 0;
 203
 204        do {
 205                rxfifo_cnt++;
 206                rxfifo_buf[rxfifo_in++] = rx & 0xff;
 207                rxfifo_in &= RXFIFO_SZ - 1;
 208
 209                if (rxfifo_cnt >= RXFIFO_SZ)
 210                        break;
 211        } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
 212
 213        return 1;
 214}
 215
 216int serial_init(void)
 217{
 218        unsigned int wconf, rconf;
 219        int i;
 220
 221        wconf = 0;
 222
 223        /* Set baud rate */
 224        switch (gd->baudrate) {
 225                case 1200:
 226                        wconf = MAX3100_B_1200;
 227                        break;
 228                case 2400:
 229                        wconf = MAX3100_B_2400;
 230                        break;
 231                case 4800:
 232                        wconf = MAX3100_B_4800;
 233                        break;
 234                case 9600:
 235                        wconf = MAX3100_B_9600;
 236                        break;
 237                case 19200:
 238                        wconf = MAX3100_B_19200;
 239                        break;
 240                case 38400:
 241                        wconf = MAX3100_B_38400;
 242                        break;
 243                case 57600:
 244                        wconf = MAX3100_B_57600;
 245                        break;
 246                default:
 247                case 115200:
 248                        wconf = MAX3100_B_115200;
 249                        break;
 250                case 230400:
 251                        wconf = MAX3100_B_230400;
 252                        break;
 253        }
 254
 255        /* try for 10ms, with a 100us gap */
 256        for (i = 0; i < 10000; i += 100) {
 257
 258                max3100_transfer(MAX3100_WC | wconf);
 259                rconf = max3100_transfer(MAX3100_RC) & 0x3fff;
 260
 261                if (rconf == wconf)
 262                        break;
 263                udelay(100);
 264        }
 265
 266        rxfifo_in = rxfifo_out = rxfifo_cnt = 0;
 267
 268        return (0);
 269}
 270
 271void serial_putc(const char c)
 272{
 273        if (c == '\n')
 274                max3100_putc('\r');
 275
 276        max3100_putc(c);
 277}
 278
 279void serial_puts(const char *s)
 280{
 281        while (*s)
 282                serial_putc (*s++);
 283}
 284
 285int serial_getc(void)
 286{
 287        return max3100_getc();
 288}
 289
 290int serial_tstc(void)
 291{
 292        return max3100_tstc();
 293}
 294
 295/* XXX WTF? */
 296void serial_setbrg(void)
 297{
 298}
 299