1 /* 2 * (C) Copyright 2004, Psyent Corporation <www.psyent.com> 3 * Scott McNutt <smcnutt@psyent.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <errno.h> 11 #include <serial.h> 12 #include <asm/io.h> 13 14 DECLARE_GLOBAL_DATA_PTR; 15 16 /* data register */ 17 #define ALTERA_JTAG_RVALID BIT(15) /* Read valid */ 18 19 /* control register */ 20 #define ALTERA_JTAG_AC BIT(10) /* activity indicator */ 21 #define ALTERA_JTAG_RRDY BIT(12) /* read available */ 22 #define ALTERA_JTAG_WSPACE(d) ((d) >> 16) /* Write space avail */ 23 /* Write fifo size. FIXME: this should be extracted with sopc2dts */ 24 #define ALTERA_JTAG_WRITE_DEPTH 64 25 26 struct altera_jtaguart_regs { 27 u32 data; /* Data register */ 28 u32 control; /* Control register */ 29 }; 30 31 struct altera_jtaguart_platdata { 32 struct altera_jtaguart_regs *regs; 33 }; 34 35 static int altera_jtaguart_setbrg(struct udevice *dev, int baudrate) 36 { 37 return 0; 38 } 39 40 static int altera_jtaguart_putc(struct udevice *dev, const char ch) 41 { 42 struct altera_jtaguart_platdata *plat = dev->platdata; 43 struct altera_jtaguart_regs *const regs = plat->regs; 44 u32 st = readl(®s->control); 45 46 #ifdef CONFIG_ALTERA_JTAG_UART_BYPASS 47 if (!(st & ALTERA_JTAG_AC)) /* no connection yet */ 48 return -ENETUNREACH; 49 #endif 50 51 if (ALTERA_JTAG_WSPACE(st) == 0) 52 return -EAGAIN; 53 54 writel(ch, ®s->data); 55 56 return 0; 57 } 58 59 static int altera_jtaguart_pending(struct udevice *dev, bool input) 60 { 61 struct altera_jtaguart_platdata *plat = dev->platdata; 62 struct altera_jtaguart_regs *const regs = plat->regs; 63 u32 st = readl(®s->control); 64 65 if (input) 66 return st & ALTERA_JTAG_RRDY ? 1 : 0; 67 else 68 return !(ALTERA_JTAG_WSPACE(st) == ALTERA_JTAG_WRITE_DEPTH); 69 } 70 71 static int altera_jtaguart_getc(struct udevice *dev) 72 { 73 struct altera_jtaguart_platdata *plat = dev->platdata; 74 struct altera_jtaguart_regs *const regs = plat->regs; 75 u32 val; 76 77 val = readl(®s->data); 78 79 if (!(val & ALTERA_JTAG_RVALID)) 80 return -EAGAIN; 81 82 return val & 0xff; 83 } 84 85 static int altera_jtaguart_probe(struct udevice *dev) 86 { 87 #ifdef CONFIG_ALTERA_JTAG_UART_BYPASS 88 struct altera_jtaguart_platdata *plat = dev->platdata; 89 struct altera_jtaguart_regs *const regs = plat->regs; 90 91 writel(ALTERA_JTAG_AC, ®s->control); /* clear AC flag */ 92 #endif 93 return 0; 94 } 95 96 static int altera_jtaguart_ofdata_to_platdata(struct udevice *dev) 97 { 98 struct altera_jtaguart_platdata *plat = dev_get_platdata(dev); 99 100 plat->regs = map_physmem(dev_get_addr(dev), 101 sizeof(struct altera_jtaguart_regs), 102 MAP_NOCACHE); 103 104 return 0; 105 } 106 107 static const struct dm_serial_ops altera_jtaguart_ops = { 108 .putc = altera_jtaguart_putc, 109 .pending = altera_jtaguart_pending, 110 .getc = altera_jtaguart_getc, 111 .setbrg = altera_jtaguart_setbrg, 112 }; 113 114 static const struct udevice_id altera_jtaguart_ids[] = { 115 { .compatible = "altr,juart-1.0" }, 116 {} 117 }; 118 119 U_BOOT_DRIVER(altera_jtaguart) = { 120 .name = "altera_jtaguart", 121 .id = UCLASS_SERIAL, 122 .of_match = altera_jtaguart_ids, 123 .ofdata_to_platdata = altera_jtaguart_ofdata_to_platdata, 124 .platdata_auto_alloc_size = sizeof(struct altera_jtaguart_platdata), 125 .probe = altera_jtaguart_probe, 126 .ops = &altera_jtaguart_ops, 127 .flags = DM_FLAG_PRE_RELOC, 128 }; 129 130 #ifdef CONFIG_DEBUG_UART_ALTERA_JTAGUART 131 132 #include <debug_uart.h> 133 134 static inline void _debug_uart_init(void) 135 { 136 } 137 138 static inline void _debug_uart_putc(int ch) 139 { 140 struct altera_jtaguart_regs *regs = (void *)CONFIG_DEBUG_UART_BASE; 141 142 while (1) { 143 u32 st = readl(®s->control); 144 145 if (ALTERA_JTAG_WSPACE(st)) 146 break; 147 } 148 149 writel(ch, ®s->data); 150 } 151 152 DEBUG_UART_FUNCS 153 154 #endif 155