From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from mail-la0-x22c.google.com ([2a00:1450:4010:c03::22c]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VDouH-0004dl-Vn for barebox@lists.infradead.org; Mon, 26 Aug 2013 05:00:04 +0000 Received: by mail-la0-f44.google.com with SMTP id eo20so1975870lab.17 for ; Sun, 25 Aug 2013 21:59:39 -0700 (PDT) From: Antony Pavlov Date: Mon, 26 Aug 2013 08:57:11 +0400 Message-Id: <1377493037-2229-3-git-send-email-antonynpavlov@gmail.com> In-Reply-To: <1377493037-2229-1-git-send-email-antonynpavlov@gmail.com> References: <1377493037-2229-1-git-send-email-antonynpavlov@gmail.com> List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "barebox" Errors-To: barebox-bounces+u.kleine-koenig=pengutronix.de@lists.infradead.org Subject: [RFC 2/8] serial: add driver for Canon DIGIC UART To: barebox@lists.infradead.org Signed-off-by: Antony Pavlov --- drivers/serial/Kconfig | 4 ++ drivers/serial/Makefile | 1 + drivers/serial/serial_digic.c | 131 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 drivers/serial/serial_digic.c diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 11fc155..541350d 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -122,4 +122,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 93790b5..485a3ef 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -17,3 +17,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 0000000..938172f --- /dev/null +++ b/drivers/serial/serial_digic.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2013 Antony Pavlov + * + * 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 +#include +#include +#include + +/* Serial interface registers offsets */ +#define UART_TX 0x0 +#define UART_RX 0x4 +#define UART_ST 0x14 + #define UART_ST_RX_RDY 1 + #define UART_ST_TX_RDY 2 + +/* + * 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 off) +{ + void *digic = cdev->dev->priv; + + return readl(digic + off); +} + +static inline void digic_serial_writel(struct console_device *cdev, uint32_t val, + uint32_t off) +{ + void *digic = cdev->dev->priv; + + writel(val, digic + off); +} + +static int digic_serial_setbaudrate(struct console_device *cdev, int baudrate) +{ + /* FIXME: empty */ + + return 0; +} + +static void digic_serial_putc(struct console_device *cdev, char c) +{ + while (!(digic_serial_readl(cdev, UART_ST) & UART_ST_TX_RDY)) + ; /* noop */ + + digic_serial_writel(cdev, 0x06, UART_ST); + digic_serial_writel(cdev, c, UART_TX); +} + +static int digic_serial_getc(struct console_device *cdev) +{ + while (!(digic_serial_readl(cdev, UART_ST) & UART_ST_RX_RDY)) + ; /* noop */ + + digic_serial_writel(cdev, 0x01, UART_ST); + + return digic_serial_readl(cdev, UART_RX); +} + +static int digic_serial_tstc(struct console_device *cdev) +{ + return ((digic_serial_readl(cdev, UART_ST) & UART_ST_RX_RDY) != 0); + + /* + * Canon folks use additional check, something like this: + * + * if (digic_serial_readl(cdev, UART_ST) & 0x38) { + * digic_serial_writel(cdev, 0x38, UART_ST); + * return 0; + * } + * + * But I know nothing about these magic bits in the status regster... + * + */ +} + +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->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR; + cdev->tstc = &digic_serial_tstc; + cdev->putc = &digic_serial_putc; + cdev->getc = &digic_serial_getc; + cdev->setbrg = &digic_serial_setbaudrate; + + /* FIXME: need digic_init_port(cdev); */ + + console_register(cdev); + + return 0; +} + +static __maybe_unused struct of_device_id digic_serial_dt_ids[] = { + { + .compatible = "canon,digic-serial", + }, { + /* sentinel */ + } +}; + +static struct driver_d digic_serial_driver = { + .name = "digic-serial", + .probe = digic_serial_probe, + .of_compatible = DRV_OF_COMPAT(digic_serial_dt_ids), +}; +console_platform_driver(digic_serial_driver); -- 1.8.4.rc3 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox