123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- /*
- * (C) Copyright 2003
- *
- * Pantelis Antoniou <panto@intracom.gr>
- * Intracom S.A.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
- #include <common.h>
- #include <watchdog.h>
- #include <serial.h>
- #include <linux/compiler.h>
- DECLARE_GLOBAL_DATA_PTR;
- /**************************************************************/
- /* convienient macros */
- #define MAX3100_SPI_RXD() (MAX3100_SPI_RXD_PORT & MAX3100_SPI_RXD_BIT)
- #define MAX3100_SPI_TXD(x) \
- do { \
- if (x) \
- MAX3100_SPI_TXD_PORT |= MAX3100_SPI_TXD_BIT; \
- else \
- MAX3100_SPI_TXD_PORT &= ~MAX3100_SPI_TXD_BIT; \
- } while(0)
- #define MAX3100_SPI_CLK(x) \
- do { \
- if (x) \
- MAX3100_SPI_CLK_PORT |= MAX3100_SPI_CLK_BIT; \
- else \
- MAX3100_SPI_CLK_PORT &= ~MAX3100_SPI_CLK_BIT; \
- } while(0)
- #define MAX3100_SPI_CLK_TOGGLE() (MAX3100_SPI_CLK_PORT ^= MAX3100_SPI_CLK_BIT)
- #define MAX3100_CS(x) \
- do { \
- if (x) \
- MAX3100_CS_PORT |= MAX3100_CS_BIT; \
- else \
- MAX3100_CS_PORT &= ~MAX3100_CS_BIT; \
- } while(0)
- /**************************************************************/
- /* MAX3100 definitions */
- #define MAX3100_WC (3 << 14) /* write configuration */
- #define MAX3100_RC (1 << 14) /* read configuration */
- #define MAX3100_WD (2 << 14) /* write data */
- #define MAX3100_RD (0 << 14) /* read data */
- /* configuration register bits */
- #define MAX3100_FEN (1 << 13) /* FIFO enable */
- #define MAX3100_SHDN (1 << 12) /* shutdown bit */
- #define MAX3100_TM (1 << 11) /* T bit irq mask */
- #define MAX3100_RM (1 << 10) /* R bit irq mask */
- #define MAX3100_PM (1 << 9) /* P bit irq mask */
- #define MAX3100_RAM (1 << 8) /* mask for RA/FE bit */
- #define MAX3100_IR (1 << 7) /* IRDA timing mode */
- #define MAX3100_ST (1 << 6) /* transmit stop bit */
- #define MAX3100_PE (1 << 5) /* parity enable bit */
- #define MAX3100_L (1 << 4) /* Length bit */
- #define MAX3100_B_MASK (0x000F) /* baud rate bits mask */
- #define MAX3100_B(x) ((x) & 0x000F) /* baud rate select bits */
- /* data register bits (write) */
- #define MAX3100_TE (1 << 10) /* transmit enable bit (active low) */
- #define MAX3100_RTS (1 << 9) /* request-to-send bit (inverted ~RTS pin) */
- /* data register bits (read) */
- #define MAX3100_RA (1 << 10) /* receiver activity when in shutdown mode */
- #define MAX3100_FE (1 << 10) /* framing error when in normal mode */
- #define MAX3100_CTS (1 << 9) /* clear-to-send bit (inverted ~CTS pin) */
- /* data register bits (both directions) */
- #define MAX3100_R (1 << 15) /* receive bit */
- #define MAX3100_T (1 << 14) /* transmit bit */
- #define MAX3100_P (1 << 8) /* parity bit */
- #define MAX3100_D_MASK 0x00FF /* data bits mask */
- #define MAX3100_D(x) ((x) & 0x00FF) /* data bits */
- /* these definitions are valid only for fOSC = 3.6864MHz */
- #define MAX3100_B_230400 MAX3100_B(0)
- #define MAX3100_B_115200 MAX3100_B(1)
- #define MAX3100_B_57600 MAX3100_B(2)
- #define MAX3100_B_38400 MAX3100_B(9)
- #define MAX3100_B_19200 MAX3100_B(10)
- #define MAX3100_B_9600 MAX3100_B(11)
- #define MAX3100_B_4800 MAX3100_B(12)
- #define MAX3100_B_2400 MAX3100_B(13)
- #define MAX3100_B_1200 MAX3100_B(14)
- #define MAX3100_B_600 MAX3100_B(15)
- /**************************************************************/
- static inline unsigned int max3100_transfer(unsigned int val)
- {
- unsigned int rx;
- int b;
- MAX3100_SPI_CLK(0);
- MAX3100_CS(0);
- rx = 0; b = 16;
- while (--b >= 0) {
- MAX3100_SPI_TXD(val & 0x8000);
- val <<= 1;
- MAX3100_SPI_CLK_TOGGLE();
- udelay(1);
- rx <<= 1;
- if (MAX3100_SPI_RXD())
- rx |= 1;
- MAX3100_SPI_CLK_TOGGLE();
- udelay(1);
- }
- MAX3100_SPI_CLK(1);
- MAX3100_CS(1);
- return rx;
- }
- /**************************************************************/
- /* must be power of 2 */
- #define RXFIFO_SZ 16
- static int rxfifo_cnt;
- static int rxfifo_in;
- static int rxfifo_out;
- static unsigned char rxfifo_buf[16];
- static void max3100_serial_putc_raw(int c)
- {
- unsigned int rx;
- while (((rx = max3100_transfer(MAX3100_RC)) & MAX3100_T) == 0)
- WATCHDOG_RESET();
- rx = max3100_transfer(MAX3100_WD | (c & 0xff));
- if ((rx & MAX3100_RD) != 0 && rxfifo_cnt < RXFIFO_SZ) {
- rxfifo_cnt++;
- rxfifo_buf[rxfifo_in++] = rx & 0xff;
- rxfifo_in &= RXFIFO_SZ - 1;
- }
- }
- static int max3100_serial_getc(void)
- {
- int c;
- unsigned int rx;
- while (rxfifo_cnt == 0) {
- rx = max3100_transfer(MAX3100_RD);
- if ((rx & MAX3100_R) != 0) {
- do {
- rxfifo_cnt++;
- rxfifo_buf[rxfifo_in++] = rx & 0xff;
- rxfifo_in &= RXFIFO_SZ - 1;
- if (rxfifo_cnt >= RXFIFO_SZ)
- break;
- } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
- }
- WATCHDOG_RESET();
- }
- rxfifo_cnt--;
- c = rxfifo_buf[rxfifo_out++];
- rxfifo_out &= RXFIFO_SZ - 1;
- return c;
- }
- static int max3100_serial_tstc(void)
- {
- unsigned int rx;
- if (rxfifo_cnt > 0)
- return 1;
- rx = max3100_transfer(MAX3100_RD);
- if ((rx & MAX3100_R) == 0)
- return 0;
- do {
- rxfifo_cnt++;
- rxfifo_buf[rxfifo_in++] = rx & 0xff;
- rxfifo_in &= RXFIFO_SZ - 1;
- if (rxfifo_cnt >= RXFIFO_SZ)
- break;
- } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0);
- return 1;
- }
- static int max3100_serial_init(void)
- {
- unsigned int wconf, rconf;
- int i;
- wconf = 0;
- /* Set baud rate */
- switch (gd->baudrate) {
- case 1200:
- wconf = MAX3100_B_1200;
- break;
- case 2400:
- wconf = MAX3100_B_2400;
- break;
- case 4800:
- wconf = MAX3100_B_4800;
- break;
- case 9600:
- wconf = MAX3100_B_9600;
- break;
- case 19200:
- wconf = MAX3100_B_19200;
- break;
- case 38400:
- wconf = MAX3100_B_38400;
- break;
- case 57600:
- wconf = MAX3100_B_57600;
- break;
- default:
- case 115200:
- wconf = MAX3100_B_115200;
- break;
- case 230400:
- wconf = MAX3100_B_230400;
- break;
- }
- /* try for 10ms, with a 100us gap */
- for (i = 0; i < 10000; i += 100) {
- max3100_transfer(MAX3100_WC | wconf);
- rconf = max3100_transfer(MAX3100_RC) & 0x3fff;
- if (rconf == wconf)
- break;
- udelay(100);
- }
- rxfifo_in = rxfifo_out = rxfifo_cnt = 0;
- return (0);
- }
- static void max3100_serial_putc(const char c)
- {
- if (c == '\n')
- max3100_serial_putc_raw('\r');
- max3100_serial_putc_raw(c);
- }
- static void max3100_serial_puts(const char *s)
- {
- while (*s)
- max3100_serial_putc_raw(*s++);
- }
- static void max3100_serial_setbrg(void)
- {
- }
- static struct serial_device max3100_serial_drv = {
- .name = "max3100_serial",
- .start = max3100_serial_init,
- .stop = NULL,
- .setbrg = max3100_serial_setbrg,
- .putc = max3100_serial_putc,
- .puts = max3100_serial_puts,
- .getc = max3100_serial_getc,
- .tstc = max3100_serial_tstc,
- };
- void max3100_serial_initialize(void)
- {
- serial_register(&max3100_serial_drv);
- }
- __weak struct serial_device *default_serial_console(void)
- {
- return &max3100_serial_drv;
- }
|