1 /* 2 * (c) 2015 Paul Thacker <paul.thacker@microchip.com> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 * 6 */ 7 #include <common.h> 8 #include <clk.h> 9 #include <dm.h> 10 #include <serial.h> 11 #include <wait_bit.h> 12 #include <mach/pic32.h> 13 #include <dt-bindings/clock/microchip,clock.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 /* UART Control Registers */ 18 #define U_MOD 0x00 19 #define U_MODCLR (U_MOD + _CLR_OFFSET) 20 #define U_MODSET (U_MOD + _SET_OFFSET) 21 #define U_STA 0x10 22 #define U_STACLR (U_STA + _CLR_OFFSET) 23 #define U_STASET (U_STA + _SET_OFFSET) 24 #define U_TXR 0x20 25 #define U_RXR 0x30 26 #define U_BRG 0x40 27 28 /* U_MOD bits */ 29 #define UART_ENABLE BIT(15) 30 31 /* U_STA bits */ 32 #define UART_RX_ENABLE BIT(12) 33 #define UART_TX_BRK BIT(11) 34 #define UART_TX_ENABLE BIT(10) 35 #define UART_TX_FULL BIT(9) 36 #define UART_TX_EMPTY BIT(8) 37 #define UART_RX_OVER BIT(1) 38 #define UART_RX_DATA_AVAIL BIT(0) 39 40 struct pic32_uart_priv { 41 void __iomem *base; 42 ulong uartclk; 43 }; 44 45 /* 46 * Initialize the serial port with the given baudrate. 47 * The settings are always 8 data bits, no parity, 1 stop bit, no start bits. 48 */ 49 static int pic32_serial_init(void __iomem *base, ulong clk, u32 baudrate) 50 { 51 u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16); 52 53 /* wait for TX FIFO to empty */ 54 wait_for_bit(__func__, base + U_STA, UART_TX_EMPTY, 55 true, CONFIG_SYS_HZ, false); 56 57 /* send break */ 58 writel(UART_TX_BRK, base + U_STASET); 59 60 /* disable and clear mode */ 61 writel(0, base + U_MOD); 62 writel(0, base + U_STA); 63 64 /* set baud rate generator */ 65 writel(div - 1, base + U_BRG); 66 67 /* enable the UART for TX and RX */ 68 writel(UART_TX_ENABLE | UART_RX_ENABLE, base + U_STASET); 69 70 /* enable the UART */ 71 writel(UART_ENABLE, base + U_MODSET); 72 return 0; 73 } 74 75 /* Check whether any char pending in RX fifo */ 76 static int pic32_uart_pending_input(void __iomem *base) 77 { 78 /* check if rx buffer overrun error has occurred */ 79 if (readl(base + U_STA) & UART_RX_OVER) { 80 readl(base + U_RXR); 81 82 /* clear overrun error to keep receiving */ 83 writel(UART_RX_OVER, base + U_STACLR); 84 } 85 86 /* In PIC32 there is no way to know number of outstanding 87 * chars in rx-fifo. Only it can be known whether there is any. 88 */ 89 return readl(base + U_STA) & UART_RX_DATA_AVAIL; 90 } 91 92 static int pic32_uart_pending(struct udevice *dev, bool input) 93 { 94 struct pic32_uart_priv *priv = dev_get_priv(dev); 95 96 if (input) 97 return pic32_uart_pending_input(priv->base); 98 99 return !(readl(priv->base + U_STA) & UART_TX_EMPTY); 100 } 101 102 static int pic32_uart_setbrg(struct udevice *dev, int baudrate) 103 { 104 struct pic32_uart_priv *priv = dev_get_priv(dev); 105 106 return pic32_serial_init(priv->base, priv->uartclk, baudrate); 107 } 108 109 static int pic32_uart_putc(struct udevice *dev, const char ch) 110 { 111 struct pic32_uart_priv *priv = dev_get_priv(dev); 112 113 /* Check if Tx FIFO is full */ 114 if (readl(priv->base + U_STA) & UART_TX_FULL) 115 return -EAGAIN; 116 117 /* pump the char to tx buffer */ 118 writel(ch, priv->base + U_TXR); 119 120 return 0; 121 } 122 123 static int pic32_uart_getc(struct udevice *dev) 124 { 125 struct pic32_uart_priv *priv = dev_get_priv(dev); 126 127 /* return error if RX fifo is empty */ 128 if (!pic32_uart_pending_input(priv->base)) 129 return -EAGAIN; 130 131 /* read the character from rx buffer */ 132 return readl(priv->base + U_RXR) & 0xff; 133 } 134 135 static int pic32_uart_probe(struct udevice *dev) 136 { 137 struct pic32_uart_priv *priv = dev_get_priv(dev); 138 struct clk clk; 139 fdt_addr_t addr; 140 fdt_size_t size; 141 int ret; 142 143 /* get address */ 144 addr = fdtdec_get_addr_size(gd->fdt_blob, dev_of_offset(dev), "reg", 145 &size); 146 if (addr == FDT_ADDR_T_NONE) 147 return -EINVAL; 148 149 priv->base = ioremap(addr, size); 150 151 /* get clock rate */ 152 ret = clk_get_by_index(dev, 0, &clk); 153 if (ret < 0) 154 return ret; 155 priv->uartclk = clk_get_rate(&clk); 156 clk_free(&clk); 157 158 /* initialize serial */ 159 return pic32_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE); 160 } 161 162 static const struct dm_serial_ops pic32_uart_ops = { 163 .putc = pic32_uart_putc, 164 .pending = pic32_uart_pending, 165 .getc = pic32_uart_getc, 166 .setbrg = pic32_uart_setbrg, 167 }; 168 169 static const struct udevice_id pic32_uart_ids[] = { 170 { .compatible = "microchip,pic32mzda-uart" }, 171 {} 172 }; 173 174 U_BOOT_DRIVER(pic32_serial) = { 175 .name = "pic32-uart", 176 .id = UCLASS_SERIAL, 177 .of_match = pic32_uart_ids, 178 .probe = pic32_uart_probe, 179 .ops = &pic32_uart_ops, 180 .flags = DM_FLAG_PRE_RELOC, 181 .priv_auto_alloc_size = sizeof(struct pic32_uart_priv), 182 }; 183 184 #ifdef CONFIG_DEBUG_UART_PIC32 185 #include <debug_uart.h> 186 187 static inline void _debug_uart_init(void) 188 { 189 void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE; 190 191 pic32_serial_init(base, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE); 192 } 193 194 static inline void _debug_uart_putc(int ch) 195 { 196 writel(ch, CONFIG_DEBUG_UART_BASE + U_TXR); 197 } 198 199 DEBUG_UART_FUNCS 200 #endif 201