drivers: serial: add driver for Microchip PIC32 UART controller.
PATCH 5/18 drivers: serial: add driver for Microchip PIC32 UART controller.
From: Paul Thacker <[email protected]>
---
drivers/serial/Kconfig | 13 +++ drivers/serial/Makefile | 1 + drivers/serial/serial_pic32.c | 220 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 234 insertions(+) create mode 100644 drivers/serial/serial_pic32.c
drivers/serial/Kconfig +13 -0
@@ -107,6 +107,14 @@ config DEBUG_UART_APBUART will need to provide parameters to make this work. The driver will be available until the real driver model serial is running. +config DEBUG_UART_PIC32 + bool "Microchip PIC32" + help + Select this to enable a debug UART using the serial_pic32 driver. You + will need to provide parameters to make this work. The driver will + be available until the real driver model serial is running. + + endchoice config DEBUG_UART_BASE
@@ -223,4 +231,9 @@ config UNIPHIER_SERIAL If you have a UniPhier based board and want to use the on-chip serial ports, say Y to this option. If unsure, say N. +config PIC32_SERIAL + bool "Support for Microchip PIC32 on-chip UART" + help + Support for the UART found on Microchip PIC32 SoC's. + endmenu
drivers/serial/Makefile +1 -0
@@ -41,6 +41,7 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o obj-$(CONFIG_ARC_SERIAL) += serial_arc.o obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o +obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_USB_TTY) += usbtty.o
drivers/serial/serial_pic32.c new file +220 -0
220 lines not on this page · raw message
Signature · 1 line
1.8.3.1
PATCH 5/18 drivers: serial: add driver for Microchip PIC32 UART controller.
On Thursday, December 17, 2015 at 06:29:32 PM, Purna Chandra Mandal wrote:
Hi!
Minor nits below.
btw do we expect MIPS to become maintained in U-Boot? That's nice :)
[...]
Quoted 46 lines
drivers/serial/Makefile +1
-0@@ -41,6 +41,7 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o obj-$(CONFIG_ARC_SERIAL) += serial_arc.o obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o +obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_USB_TTY) += usbtty.odrivers/serial/serial_pic32.c new file +28
-0@@ -0,0 +1,220 @@ +/* +* (c) 2015 Paul Thacker <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +* +*/ +#include <common.h> +#include <dm.h> +#include <clk.h> +#include <errno.h> +#include <config.h> +#include <serial.h> +#include <linux/bitops.h> +#include <common.h> +#include <asm/io.h> +#include <asm/arch-pic32/pic32.h> +#include <asm/arch-pic32/clock.h> + +DECLARE_GLOBAL_DATA_PTR ; + +#define UART_ENABLE BIT(15) +#define UART_ENABLE_RX BIT(12) +#define UART_ENABLE_TX BIT(10) +#define UART_RX_DATA_AVAIL BIT(0) +#define UART_RX_OERR BIT(1) +#define UART_TX_FULL BIT(9) + +/* UART Control */
drivers/serial/serial_pic32.c line 38
Quoted 10 lines
drivers/serial/serial_pic32.c new file +10
-0+#define U_BASE (x) (x) +#define U_MODE (x) U_BASE(x) +#define U_MODECLR (x) (U_MODE(x) + _CLR_OFFSET) +#define U_MODESET (x) (U_MODE(x) + _SET_OFFSET) +#define U_STA (x) (U_BASE(x) + 0x10) +#define U_STACLR (x) (U_STA(x) + _CLR_OFFSET) +#define U_STASET (x) (U_STA(x) + _SET_OFFSET) +#define U_TXREG (x) (U_BASE(x) + 0x20) +#define U_RXREG (x) (U_BASE(x) + 0x30) +#define U_BRG (x) (U_BASE(x) + 0x40)
Why don't you just use uart_priv->regs + PIC32_REGISTER_OFFSET in the code? The U_BASE is redundant and so is UMODE.
Quoted 53 lines
drivers/serial/serial_pic32.c new file +6
-0+struct pic32_uart_priv { +void __iomem *regs; +ulong uartclk; +}; + +static void pic32_serial_setbrg(void __iomem *regs, ulong uart_clk, u32baud) +{
drivers/serial/serial_pic32.c new file +8
-0+writel (0 ,U_BRG (regs)); +writel ((uart_clk / baud /16 ) -1 ,U_BRG (regs)); +udelay (100 ); +} + +/* +* Initialize the serial port with the given baudrate. +* The settings are always 8 data bits, no parity, 1 stop bit, no start bits. + */
drivers/serial/serial_pic32.c new file +37
-0+static int pic32_serial_init (void __iomem *regs,ulong clk,u32 baudrate) +{ +/* disable and clear mode */ +writel (0 ,U_MODE (regs)); +writel (0 ,U_STA (regs)); + +/* set baud rate generator */ +pic32_serial_setbrg (regs, clk, baudrate); + +/* enable the UART for TX and RX */ +writel (UART_ENABLE_TX |UART_ENABLE_RX ,U_STASET (regs)); + +/* enable the UART */ +writel (UART_ENABLE ,U_MODESET (regs)); +return 0 ; +} + +/* Output a single byte to the serial port */ +static void pic32_serial_putc (void __iomem *regs,const char c) +{ +/* if \n, then add a \r */ +if (c =='\n' ) +pic32_serial_putc (regs,'\r' ); + +/* Wait for Tx FIFO not full */ +while (readl (U_STA (regs)) &UART_TX_FULL ) + ; + +/* stuff the tx buffer with the character */ +writel (c,U_TXREG (regs)); +} + +/* Test whether a character is in the RX buffer */ +static int pic32_serial_tstc (void __iomem *regs) +{ +/* check if rcv buf overrun error has occurred */ +if (readl (U_STA (regs)) &UART_RX_OERR ) {
drivers/serial/serial_pic32.c line 102
Quoted 10 lines
drivers/serial/serial_pic32.c new file +10
-0+readl (U_RXREG (regs)); + +/* clear OERR to keep receiving */ +writel (UART_RX_OERR ,U_STACLR (regs)); + } + +if (readl (U_STA (regs)) &UART_RX_DATA_AVAIL ) +return 1 ;/* yes, there is data in rcv buffer */ +else +return 0 ;/* no data in rcv buffer */
return readl() & UART_RX_DATA_AVAIL; is sufficient here.
Quoted 6 lines
drivers/serial/serial_pic32.c new file +6
-0+} + +/* +* Read a single byte from the rx buffer. +* Blocking: waits until a character is received, then returns. +* Return the character read directly from the UART's receive register.
drivers/serial/serial_pic32.c line 118
Quoted 10 lines
drivers/serial/serial_pic32.c new file +10
-0+* +*/ +static int pic32_serial_getc (void __iomem *regs) +{ +/* wait here until data is available */ +while (!pic32_serial_tstc (regs)) + ; + +/* read the character from the rcv buffer */ +return readl (U_RXREG (regs));
return readl() & 0xff, since the return value is a signed integer.
Quoted 1 line
+}
[...]
drivers/serial/serial_pic32.c line 200
Quoted 9 lines
drivers/serial/serial_pic32.c new file +9
-0+U_BOOT_DRIVER (pic32_serial) = { + .name ="pic32-uart" , + .id =UCLASS_SERIAL , + .of_match = pic32_uart_ids, + .probe = pic32_uart_probe, + .ops = &pic32_uart_ops, + .flags =DM_FLAG_PRE_RELOC , + .ofdata_to_platdata = pic32_uart_ofdata_to_platdata, + .platdata_auto_alloc_size =sizeof (struct pic32_uart_priv ),
Is there some problem with tab/space conversion going on in here?
Quoted 2 lines
drivers/serial/serial_pic32.c new file +2
-0+}; +
[...]
PATCH 5/18 drivers: serial: add driver for Microchip PIC32 UART controller.
Quoted 60 lines · Marek Vasut
On Thursday, December 17, 2015 at 06:29:32 PM, Purna Chandra Mandal wrote:
Hi!
Minor nits below.
btw do we expect MIPS to become maintained in U-Boot? That's nice :)
[...]
Quoted 50 lines
drivers/serial/Makefile +1
-0@@ -41,6 +41,7 @@ obj-$(CONFIG_MXS_AUART) += mxs_auart.o obj-$(CONFIG_ARC_SERIAL) += serial_arc.o obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o +obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_USB_TTY) += usbtty.odrivers/serial/serial_pic32.c new file +32
-0@@ -0,0 +1,220 @@ +/* +* (c) 2015 Paul Thacker <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +* +*/ +#include <common.h> +#include <dm.h> +#include <clk.h> +#include <errno.h> +#include <config.h> +#include <serial.h> +#include <linux/bitops.h> +#include <common.h> +#include <asm/io.h> +#include <asm/arch-pic32/pic32.h> +#include <asm/arch-pic32/clock.h> + +DECLARE_GLOBAL_DATA_PTR ; + +#define UART_ENABLE BIT(15) +#define UART_ENABLE_RX BIT(12) +#define UART_ENABLE_TX BIT(10) +#define UART_RX_DATA_AVAIL BIT(0) +#define UART_RX_OERR BIT(1) +#define UART_TX_FULL BIT(9) + +/* UART Control */ +#define U_BASE (x) (x) +#define U_MODE (x) U_BASE(x) +#define U_MODECLR (x) (U_MODE(x) + _CLR_OFFSET) +#define U_MODESET (x) (U_MODE(x) + _SET_OFFSET)
Quoted 8 lines
drivers/serial/serial_pic32.c line 38
Quoted 6 lines
drivers/serial/serial_pic32.c new file +6
-0+#define U_STA (x) (U_BASE(x) + 0x10) +#define U_STACLR (x) (U_STA(x) + _CLR_OFFSET) +#define U_STASET (x) (U_STA(x) + _SET_OFFSET) +#define U_TXREG (x) (U_BASE(x) + 0x20) +#define U_RXREG (x) (U_BASE(x) + 0x30) +#define U_BRG (x) (U_BASE(x) + 0x40)Why don't you just use
uart_priv->regs+PIC32_REGISTER_OFFSETin the code? TheU_BASEis redundant and so is UMODE.
ack. Will update.
Quoted 56 lines
Quoted 56 lines
drivers/serial/serial_pic32.c new file +6
-0+struct pic32_uart_priv { +void __iomem *regs; +ulong uartclk; +}; + +static void pic32_serial_setbrg(void __iomem *regs, ulong uart_clk, u32baud) +{
drivers/serial/serial_pic32.c new file +8
-0+writel (0 ,U_BRG (regs)); +writel ((uart_clk / baud /16 ) -1 ,U_BRG (regs)); +udelay (100 ); +} + +/* +* Initialize the serial port with the given baudrate. +* The settings are always 8 data bits, no parity, 1 stop bit, no start bits. + */
drivers/serial/serial_pic32.c new file +40
-0+static int pic32_serial_init (void __iomem *regs,ulong clk,u32 baudrate) +{ +/* disable and clear mode */ +writel (0 ,U_MODE (regs)); +writel (0 ,U_STA (regs)); + +/* set baud rate generator */ +pic32_serial_setbrg (regs, clk, baudrate); + +/* enable the UART for TX and RX */ +writel (UART_ENABLE_TX |UART_ENABLE_RX ,U_STASET (regs)); + +/* enable the UART */ +writel (UART_ENABLE ,U_MODESET (regs)); +return 0 ; +} + +/* Output a single byte to the serial port */ +static void pic32_serial_putc (void __iomem *regs,const char c) +{ +/* if \n, then add a \r */ +if (c =='\n' ) +pic32_serial_putc (regs,'\r' ); + +/* Wait for Tx FIFO not full */ +while (readl (U_STA (regs)) &UART_TX_FULL ) + ; + +/* stuff the tx buffer with the character */ +writel (c,U_TXREG (regs)); +} + +/* Test whether a character is in the RX buffer */ +static int pic32_serial_tstc (void __iomem *regs) +{ +/* check if rcv buf overrun error has occurred */ +if (readl (U_STA (regs)) &UART_RX_OERR ) { +readl (U_RXREG (regs)); + +/* clear OERR to keep receiving */
Quoted 8 lines
drivers/serial/serial_pic32.c line 102
Quoted 7 lines
drivers/serial/serial_pic32.c new file +7
-0+writel (UART_RX_OERR ,U_STACLR (regs)); + } + +if (readl (U_STA (regs)) &UART_RX_DATA_AVAIL ) +return 1 ;/* yes, there is data in rcv buffer */ +else +return 0 ;/* no data in rcv buffer */ return
readl()&UART_RX_DATA_AVAIL; is sufficient here.
ack.
Quoted 9 lines
Quoted 9 lines
drivers/serial/serial_pic32.c new file +9
-0+} + +/* +* Read a single byte from the rx buffer. +* Blocking: waits until a character is received, then returns. +* Return the character read directly from the UART's receive register. +* +*/ +static int pic32_serial_getc (void __iomem *regs)
Quoted 8 lines
drivers/serial/serial_pic32.c line 118
Quoted 7 lines
drivers/serial/serial_pic32.c new file +7
-0+{ +/* wait here until data is available */ +while (!pic32_serial_tstc (regs)) + ; + +/* read the character from the rcv buffer */ +return readl (U_RXREG (regs));return
readl()&0xff, since the return value is a signed integer.
ack.
Quoted 12 lines
Quoted 1 line
+}
[...]
drivers/serial/serial_pic32.c line 200
Quoted 9 lines
drivers/serial/serial_pic32.c new file +9
-0+U_BOOT_DRIVER (pic32_serial) = { + .name ="pic32-uart" , + .id =UCLASS_SERIAL , + .of_match = pic32_uart_ids, + .probe = pic32_uart_probe, + .ops = &pic32_uart_ops, + .flags =DM_FLAG_PRE_RELOC , + .ofdata_to_platdata = pic32_uart_ofdata_to_platdata, + .platdata_auto_alloc_size =sizeof (struct pic32_uart_priv ),
Quoted 1 line
Is there some problem with tab/space conversion going on in here?
ack. will fix.
Quoted 3 lines
Quoted 2 lines
drivers/serial/serial_pic32.c new file +2
-0+}; +[...]