From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
To: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Cc: barebox@lists.infradead.org
Subject: Re: [PATCH v2 1/5] serial: Add driver for Cadence UART
Date: Tue, 19 Mar 2013 16:22:53 +0100 [thread overview]
Message-ID: <20130319152253.GL1568@game.jcrosoft.org> (raw)
In-Reply-To: <1363684920-3034-2-git-send-email-s.trumtrar@pengutronix.de>
On 10:21 Tue 19 Mar , Steffen Trumtrar wrote:
> Support for Cadence UART core.
>
> Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
> ---
> drivers/serial/Kconfig | 4 +
> drivers/serial/Makefile | 1 +
> drivers/serial/serial_cadence.c | 307 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 312 insertions(+)
> create mode 100644 drivers/serial/serial_cadence.c
>
> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> index f61d670..a51510e 100644
> --- a/drivers/serial/Kconfig
> +++ b/drivers/serial/Kconfig
> @@ -113,4 +113,8 @@ config DRIVER_SERIAL_OMAP4_USBBOOT
> help
> Enable this to get console support over the usb bus used to boot an OMAP4
>
> +config DRIVER_SERIAL_CADENCE
> + default n
no need it's already n
> + bool "Cadence UART driver"
> +
> endmenu
> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> index 893e282..963a7df 100644
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -21,3 +21,4 @@ obj-$(CONFIG_DRIVER_SERIAL_ALTERA) += serial_altera.o
> obj-$(CONFIG_DRIVER_SERIAL_ALTERA_JTAG) += serial_altera_jtag.o
> obj-$(CONFIG_DRIVER_SERIAL_PXA) += serial_pxa.o
> obj-$(CONFIG_DRIVER_SERIAL_OMAP4_USBBOOT) += serial_omap4_usbboot.o
> +obj-$(CONFIG_DRIVER_SERIAL_CADENCE) += serial_cadence.o
> diff --git a/drivers/serial/serial_cadence.c b/drivers/serial/serial_cadence.c
> new file mode 100644
> index 0000000..c29c391
> --- /dev/null
> +++ b/drivers/serial/serial_cadence.c
> @@ -0,0 +1,307 @@
> +/*
> + * (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * 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 <driver.h>
> +#include <init.h>
> +#include <malloc.h>
> +#include <notifier.h>
> +#include <io.h>
> +#include <linux/err.h>
> +#include <linux/clk.h>
> +
> +#define CADENCE_UART_CONTROL 0x00
> +#define CADENCE_UART_MODE 0x04
> +#define CADENCE_UART_BAUD_GEN 0x18
> +#define CADENCE_UART_CHANNEL_STS 0x2C
> +#define CADENCE_UART_RXTXFIFO 0x30
> +#define CADENCE_UART_BAUD_DIV 0x34
> +
> +#define CADENCE_CTRL_RXRES (1 << 0)
> +#define CADENCE_CTRL_TXRES (1 << 1)
> +#define CADENCE_CTRL_RXEN (1 << 2)
> +#define CADENCE_CTRL_RXDIS (1 << 3)
> +#define CADENCE_CTRL_TXEN (1 << 4)
> +#define CADENCE_CTRL_TXDIS (1 << 5)
> +#define CADENCE_CTRL_RSTTO (1 << 6)
> +#define CADENCE_CTRL_STTBRK (1 << 7)
> +#define CADENCE_CTRL_STPBRK (1 << 8)
> +
> +#define CADENCE_MODE_CLK_REF (0 << 0)
> +#define CADENCE_MODE_CLK_REF_DIV (1 << 0)
> +#define CADENCE_MODE_CHRL_6 (3 << 1)
> +#define CADENCE_MODE_CHRL_7 (2 << 1)
> +#define CADENCE_MODE_CHRL_8 (0 << 1)
> +#define CADENCE_MODE_PAR_EVEN (0 << 3)
> +#define CADENCE_MODE_PAR_ODD (1 << 3)
> +#define CADENCE_MODE_PAR_SPACE (2 << 3)
> +#define CADENCE_MODE_PAR_MARK (3 << 3)
> +#define CADENCE_MODE_PAR_NONE (4 << 3)
> +
> +#define CADENCE_STS_REMPTY (1 << 1)
> +#define CADENCE_STS_RFUL (1 << 2)
> +#define CADENCE_STS_TEMPTY (1 << 3)
> +#define CADENCE_STS_TFUL (1 << 4)
move this to an include as we will use them for debug_ll
> +
> +/*
> + * create default values for different platforms
> + */
> +struct cadence_serial_devtype_data {
> + u32 ctrl;
> + u32 mode;
> +};
> +
> +static struct cadence_serial_devtype_data cadence_r1p08_data = {
> + .ctrl = CADENCE_CTRL_RXEN | CADENCE_CTRL_TXEN,
> + .mode = CADENCE_MODE_CLK_REF | CADENCE_MODE_CHRL_8 | CADENCE_MODE_PAR_NONE,
> +};
> +
> +struct cadence_serial_priv {
> + struct console_device cdev;
> + int baudrate;
> + struct notifier_block notify;
> + void __iomem *regs;
> + struct clk *clk;
> + struct cadence_serial_devtype_data *devtype;
> +};
> +
> +static int cadence_serial_reset(struct console_device *cdev)
> +{
> + struct cadence_serial_priv *priv = container_of(cdev,
> + struct cadence_serial_priv, cdev);
> +
> + /* Soft-Reset Tx/Rx paths */
> + writel(CADENCE_CTRL_RXRES | CADENCE_CTRL_TXRES, priv->regs +
> + CADENCE_UART_CONTROL);
> +
> + while (readl(priv->regs + CADENCE_UART_CONTROL) &
> + (CADENCE_CTRL_RXRES | CADENCE_CTRL_TXRES))
> + ;
> +
> + return 0;
> +}
> +
> +static int cadence_serial_setbaudrate(struct console_device *cdev, int baudrate)
> +{
> + struct cadence_serial_priv *priv = container_of(cdev,
> + struct cadence_serial_priv, cdev);
> + unsigned int gen, div;
> + int calc_rate;
> + unsigned long clk;
> + int error;
> + int val;
> +
> + clk = clk_get_rate(priv->clk);
> + priv->baudrate = baudrate;
> +
> + /* disable transmitter and receiver */
> + val = readl(priv->regs + CADENCE_UART_CONTROL);
> + val &= ~CADENCE_CTRL_TXEN & ~CADENCE_CTRL_RXEN;
> + writel(val, priv->regs + CADENCE_UART_CONTROL);
> +
> + /*
> + * clk
> + * rate = -----------
> + * gen*(div+1)
> + */
> +
> + for (div = 4; div < 256; div++) {
> + gen = clk / (baudrate * (div + 1));
> +
> + if (gen < 1 || gen > 65535)
> + continue;
> +
> + calc_rate = clk / (gen * (div + 1));
> + error = baudrate - calc_rate;
> + if (error < 0)
> + error *= -1;
> + if (((error * 100) / baudrate) < 3)
> + break;
> + }
> +
> + writel(gen, priv->regs + CADENCE_UART_BAUD_GEN);
> + writel(div, priv->regs + CADENCE_UART_BAUD_DIV);
> +
> + /* Soft-Reset Tx/Rx paths */
> + writel(CADENCE_CTRL_RXRES | CADENCE_CTRL_TXRES, priv->regs +
> + CADENCE_UART_CONTROL);
> +
> + while (readl(priv->regs + CADENCE_UART_CONTROL) &
> + (CADENCE_CTRL_RXRES | CADENCE_CTRL_TXRES))
> + ;
> +
> + /* Enable UART */
> + writel(priv->devtype->ctrl, priv->regs + CADENCE_UART_CONTROL);
> +
> + return 0;
> +}
> +
> +static int cadence_serial_init_port(struct console_device *cdev)
> +{
> + struct cadence_serial_priv *priv = container_of(cdev,
> + struct cadence_serial_priv, cdev);
> +
> + cadence_serial_reset(cdev);
> +
> + /* Enable UART */
> + writel(priv->devtype->ctrl, priv->regs + CADENCE_UART_CONTROL);
> + writel(priv->devtype->mode, priv->regs + CADENCE_UART_MODE);
> +
> + return 0;
> +}
> +
> +static void cadence_serial_putc(struct console_device *cdev, char c)
> +{
> + struct cadence_serial_priv *priv = container_of(cdev,
> + struct cadence_serial_priv, cdev);
> +
> + while ((readl(priv->regs + CADENCE_UART_CHANNEL_STS) &
> + CADENCE_STS_TFUL) != 0)
> + ;
> +
> + writel(c, priv->regs + CADENCE_UART_RXTXFIFO);
> +}
> +
> +static int cadence_serial_tstc(struct console_device *cdev)
> +{
> + struct cadence_serial_priv *priv = container_of(cdev,
> + struct cadence_serial_priv, cdev);
> +
> + return ((readl(priv->regs + CADENCE_UART_CHANNEL_STS) &
> + CADENCE_STS_REMPTY) == 0);
> +}
> +
> +static int cadence_serial_getc(struct console_device *cdev)
> +{
> + struct cadence_serial_priv *priv = container_of(cdev,
> + struct cadence_serial_priv, cdev);
> +
> + while (!cadence_serial_tstc(cdev))
> + ;
> +
> + return readl(priv->regs + CADENCE_UART_RXTXFIFO);
> +}
> +
> +static void cadence_serial_flush(struct console_device *cdev)
> +{
> + struct cadence_serial_priv *priv = container_of(cdev,
> + struct cadence_serial_priv, cdev);
> +
> + while ((readl(priv->regs + CADENCE_UART_CHANNEL_STS) &
> + CADENCE_STS_TEMPTY) != 0)
> + ;
> +}
> +
> +static int cadence_clocksource_clock_change(struct notifier_block *nb,
> + unsigned long event, void *data)
> +{
> + struct cadence_serial_priv *priv = container_of(nb,
> + struct cadence_serial_priv, notify);
> +
> + cadence_serial_setbaudrate(&priv->cdev, priv->baudrate);
> +
> + return 0;
> +}
> +
> +static int cadence_serial_probe(struct device_d *dev)
> +{
> + struct console_device *cdev;
> + struct cadence_serial_priv *priv;
> + struct cadence_serial_devtype_data *devtype;
> + int ret;
> +
> + ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
> + if (ret)
> + return ret;
> +
> + priv = xzalloc(sizeof(*priv));
> + priv->devtype = devtype;
> + cdev = &priv->cdev;
> + dev->priv = priv;
> +
> + priv->clk = clk_get(dev, NULL);
> + if (IS_ERR(priv->clk)) {
> + ret = -ENODEV;
> + goto err_free;
> + }
> +
> + if (devtype->mode & CADENCE_MODE_CLK_REF_DIV)
> + clk_set_rate(priv->clk, clk_get_rate(priv->clk) / 8);
> +
> + priv->regs = dev_request_mem_region(dev, 0);
> + if (!priv->regs) {
> + ret = -EBUSY;
> + goto err_free;
> + }
> +
> + cdev->dev = dev;
> + cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
> + cdev->tstc = cadence_serial_tstc;
> + cdev->putc = cadence_serial_putc;
> + cdev->getc = cadence_serial_getc;
> + cdev->flush = cadence_serial_flush;
> + cdev->setbrg = cadence_serial_setbaudrate;
> +
> + cadence_serial_init_port(cdev);
> +
> + console_register(cdev);
> + priv->notify.notifier_call = cadence_clocksource_clock_change;
> + clock_register_client(&priv->notify);
> +
> + return 0;
> +
> +err_free:
> + free(priv);
> + return ret;
> +}
> +
> +static void cadence_serial_remove(struct device_d *dev)
> +{
> + struct cadence_serial_priv *priv = dev->priv;
> +
> + console_unregister(&priv->cdev);
> + free(priv);
> +}
> +
> +static __maybe_unused struct of_device_id cadence_serial_dt_ids[] = {
> + {
> + .compatible = "xlnx,xuartps",
> + .data = (unsigned long)&cadence_r1p08_data,
> + }, {
> + /* sentinel */
> + }
> +};
> +
> +static struct platform_device_id cadence_serial_ids[] = {
> + {
> + .name = "cadence-uart",
> + .driver_data = (unsigned long)&cadence_r1p08_data,
> + }, {
> + /* sentinel */
> + },
> +};
> +
> +static struct driver_d cadence_serial_driver = {
> + .name = "cadence_serial",
> + .probe = cadence_serial_probe,
> + .remove = cadence_serial_remove,
don't do so
otherwise no uncompress in the kernel
> + .of_compatible = DRV_OF_COMPAT(cadence_serial_dt_ids),
> + .id_table = cadence_serial_ids,
> +};
> +
> +static int cadence_serial_init(void)
> +{
> + return platform_driver_register(&cadence_serial_driver);
> +}
> +console_initcall(cadence_serial_init);
> --
> 1.8.2.rc2
>
>
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2013-03-19 15:37 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-19 9:21 [PATCH v2 0/5] ARM: add support for Zynq Steffen Trumtrar
2013-03-19 9:21 ` [PATCH v2 1/5] serial: Add driver for Cadence UART Steffen Trumtrar
2013-03-19 15:22 ` Jean-Christophe PLAGNIOL-VILLARD [this message]
2013-03-19 9:21 ` [PATCH v2 2/5] ARM: zynq: Add new architecture zynq Steffen Trumtrar
2013-03-19 13:05 ` Josh Cartwright
2013-03-19 13:18 ` Josh Cartwright
2013-03-19 13:31 ` Steffen Trumtrar
2013-03-19 15:26 ` Jean-Christophe PLAGNIOL-VILLARD
2013-03-19 9:21 ` [PATCH v2 3/5] ARM: zynq: add clk support for zynq7000 Steffen Trumtrar
2013-03-19 13:29 ` Josh Cartwright
2013-03-19 13:35 ` Steffen Trumtrar
2013-03-19 13:48 ` Josh Cartwright
2013-03-19 9:21 ` [PATCH v2 4/5] ARM: zynq: add zynq fsbl checksum script Steffen Trumtrar
2013-03-19 9:22 ` [PATCH v2 5/5] ARM: zynq: Add support for the Avnet Zedboard Steffen Trumtrar
2013-03-19 13:40 ` Josh Cartwright
2013-03-19 13:47 ` Steffen Trumtrar
2013-03-19 15:28 ` Jean-Christophe PLAGNIOL-VILLARD
2013-03-19 12:59 ` [PATCH v2 0/5] ARM: add support for Zynq Josh Cartwright
2013-03-19 13:57 ` Steffen Trumtrar
2013-03-19 15:08 ` Josh Cartwright
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130319152253.GL1568@game.jcrosoft.org \
--to=plagnioj@jcrosoft.com \
--cc=barebox@lists.infradead.org \
--cc=s.trumtrar@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.