diff options
author | Antony Pavlov <antonynpavlov@gmail.com> | 2014-07-29 01:15:23 +0400 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2014-07-29 15:08:29 +0200 |
commit | fd00d693cc6c0bfe61d638a820e4e9895560bcee (patch) | |
tree | 49eacbc2392f4c4562451094d4d98c764e320eca /drivers/serial | |
parent | bbd477644db1297debaffbfde61b9365a6b42e03 (diff) | |
download | barebox-fd00d693cc6c0bfe61d638a820e4e9895560bcee.tar.gz barebox-fd00d693cc6c0bfe61d638a820e4e9895560bcee.tar.xz |
serial: add driver for Canon DIGIC UART
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/Kconfig | 4 | ||||
-rw-r--r-- | drivers/serial/Makefile | 1 | ||||
-rw-r--r-- | drivers/serial/serial_digic.c | 132 |
3 files changed, 137 insertions, 0 deletions
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index f51c6e6b02..aa8833126c 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -129,4 +129,8 @@ config DRIVER_SERIAL_CADENCE help Say Y here if you have a Cadence serial IP core. +config DRIVER_SERIAL_DIGIC + bool "Canon DIGIC serial driver" + depends on ARCH_DIGIC + endmenu diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index e1865f725a..2d0e98eed3 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_DRIVER_SERIAL_PXA) += serial_pxa.o obj-$(CONFIG_DRIVER_SERIAL_OMAP4_USBBOOT) += serial_omap4_usbboot.o obj-$(CONFIG_DRIVER_SERIAL_AUART) += serial_auart.o obj-$(CONFIG_DRIVER_SERIAL_CADENCE) += serial_cadence.o +obj-$(CONFIG_DRIVER_SERIAL_DIGIC) += serial_digic.o diff --git a/drivers/serial/serial_digic.c b/drivers/serial/serial_digic.c new file mode 100644 index 0000000000..235ea0ff47 --- /dev/null +++ b/drivers/serial/serial_digic.c @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2013, 2014 Antony Pavlov <antonynpavlov@gmail.com> + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <init.h> +#include <malloc.h> +#include <io.h> + +#include <mach/uart.h> + +/* + * This driver is based on the "Serial terminal" docs here: + * http://magiclantern.wikia.com/wiki/Register_Map#Misc_Registers + * + * See also disassembler output for Canon A1100IS firmware + * (version a1100_100c): + * * a outc-like function can be found at address 0xffff18f0; + * * a getc-like function can be found at address 0xffff192c. + */ + +static inline uint32_t digic_serial_readl(struct console_device *cdev, + uint32_t offset) +{ + void __iomem *base = cdev->dev->priv; + + return readl(base + offset); +} + +static inline void digic_serial_writel(struct console_device *cdev, + uint32_t value, uint32_t offset) +{ + void __iomem *base = cdev->dev->priv; + + writel(value, base + offset); +} + +static int digic_serial_setbaudrate(struct console_device *cdev, int baudrate) +{ + /* I don't know how to setup baudrate :( */ + + return 0; +} + +static void digic_serial_putc(struct console_device *cdev, char c) +{ + uint32_t status; + + do { + status = digic_serial_readl(cdev, DIGIC_UART_ST); + } while (!(status & DIGIC_UART_ST_TX_RDY)); + + digic_serial_writel(cdev, 0x06, DIGIC_UART_ST); + digic_serial_writel(cdev, c, DIGIC_UART_TX); +} + +static int digic_serial_getc(struct console_device *cdev) +{ + uint32_t status; + + do { + status = digic_serial_readl(cdev, DIGIC_UART_ST); + } while (!(status & DIGIC_UART_ST_RX_RDY)); + + digic_serial_writel(cdev, 0x01, DIGIC_UART_ST); + + return digic_serial_readl(cdev, DIGIC_UART_RX); +} + +static int digic_serial_tstc(struct console_device *cdev) +{ + uint32_t status = digic_serial_readl(cdev, DIGIC_UART_ST); + + return ((status & DIGIC_UART_ST_RX_RDY) != 0); + + /* + * Canon folks use additional check, something like this: + * + * if (digic_serial_readl(cdev, DIGIC_UART_ST) & 0x38) { + * digic_serial_writel(cdev, 0x38, DIGIC_UART_ST); + * return 0; + * } + * + * But I know nothing about these magic bits in the status register... + * + */ +} + +static int digic_serial_probe(struct device_d *dev) +{ + struct console_device *cdev; + + cdev = xzalloc(sizeof(struct console_device)); + dev->priv = dev_request_mem_region(dev, 0); + cdev->dev = dev; + cdev->tstc = &digic_serial_tstc; + cdev->putc = &digic_serial_putc; + cdev->getc = &digic_serial_getc; + cdev->setbrg = &digic_serial_setbaudrate; + + console_register(cdev); + + return 0; +} + +static __maybe_unused struct of_device_id digic_serial_dt_ids[] = { + { + .compatible = "canon,digic-uart", + }, { + /* sentinel */ + } +}; + +static struct driver_d digic_serial_driver = { + .name = "digic-uart", + .probe = digic_serial_probe, + .of_compatible = DRV_OF_COMPAT(digic_serial_dt_ids), +}; +console_platform_driver(digic_serial_driver); |