From 19d8b4c46ee297fb385e836f9da7234646f005b6 Mon Sep 17 00:00:00 2001 From: "Anton D. Kachalov" Date: Mon, 3 Aug 2015 15:34:29 +0300 Subject: [PATCH] Add custom IOCTL for UART port Signed-off-by: Anton D. Kachalov --- arch/arm/src/moxart/Kconfig | 3 ++ arch/arm/src/moxart/moxart_16550.c | 71 ++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/arch/arm/src/moxart/Kconfig b/arch/arm/src/moxart/Kconfig index d520506785..3c8166499f 100644 --- a/arch/arm/src/moxart/Kconfig +++ b/arch/arm/src/moxart/Kconfig @@ -4,3 +4,6 @@ # comment "MoxART Configuration Options" + +config UART_MOXA_MODE_REG + hex "16550 UART mode register address" diff --git a/arch/arm/src/moxart/moxart_16550.c b/arch/arm/src/moxart/moxart_16550.c index 0152b6010f..a1dbed0bb3 100644 --- a/arch/arm/src/moxart/moxart_16550.c +++ b/arch/arm/src/moxart/moxart_16550.c @@ -40,11 +40,15 @@ #include +#include #include #include #include +#include +#include #include +#include #include "arm.h" #include "up_arch.h" @@ -62,3 +66,70 @@ void uart_putreg(uart_addrwidth_t base, unsigned int offset, uart_datawidth_t va { *((volatile uart_addrwidth_t *)base + offset) = value; } + +#ifdef CONFIG_SERIAL_UART_ARCH_IOCTL +int uart_ioctl(struct file *filep, int cmd, unsigned long arg) +{ + struct inode *inode = filep->f_inode; + struct uart_dev_s *dev = inode->i_private; + struct u16550_s *priv = (struct u16550_s*)dev->priv; + int ret = -ENOTTY; + uint32_t vmode; + unsigned int opmode; + int bitm_off; + + /* + * TODO: calculate bit offset from UART_BASE address. + * E.g.: + * 0x9820_0000 -> 0 + * 0x9820_0020 -> 1 + * 0x9820_0040 -> 2 + */ + + /* HARD: coded value for UART1 */ + bitm_off = 1; + + switch (cmd) + { + case MOXA_SET_OP_MODE: + { + irqstate_t flags; + opmode = *(unsigned long *)arg; + + /* Check for input data */ + + if (opmode & ~OP_MODE_MASK) + { + ret = -EINVAL; + break; + } + + flags = irqsave(); + + /* Update mode register with requested mode */ + + vmode = getreg32(CONFIG_UART_MOXA_MODE_REG); + putreg32(CONFIG_UART_MOXA_MODE_REG, (vmode & ~(OP_MODE_MASK << 2 * bitm_off)) | ((opmode << 2 * bitm_off) & 0xffff)); + + irqrestore(flags); + break; + } + + case MOXA_GET_OP_MODE: + { + irqstate_t flags; + flags = irqsave(); + + /* Read from mode register */ + + opmode = (getreg32(CONFIG_UART_MOXA_MODE_REG) >> 2 * bitm_off) & OP_MODE_MASK; + + irqrestore(flags); + *(unsigned long *)arg = opmode; + break; + } + } + + return ret; +} +#endif