From patchwork Wed Mar 6 11:30:35 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bastian Hecht X-Patchwork-Id: 2224781 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id EA7E5DF23A for ; Wed, 6 Mar 2013 11:34:58 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UDCYk-0005E6-TD; Wed, 06 Mar 2013 11:30:59 +0000 Received: from mail-ee0-f53.google.com ([74.125.83.53]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UDCYW-00058b-NQ for linux-arm-kernel@lists.infradead.org; Wed, 06 Mar 2013 11:30:46 +0000 Received: by mail-ee0-f53.google.com with SMTP id e53so5369515eek.26 for ; Wed, 06 Mar 2013 03:30:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer; bh=KlXGt6fhnwsSrSzdsBQ9VO8HDdNbnFDxi35rVnfZyC0=; b=dmx/bUYuw+MmEtplebNHDD0wAMr4eltA8wgTlww34VJCrzWB3+sVSiwiBMfI22/SsF bTaQj8T7rg9wUUpjurVSVBHQkptGdGXM490HlfG8Hi/GjZEsNzl0fCqRrAAIbG1q+6G2 4U+zlhJe9Xhkjkb58FArHx1tGqceA2fC/MMb2XwBh3bRc0v5tvg2Wm9IHUpArTE7ohjh LGt4aPgizyFWg/4E6MmAKf71qj1r+swq7YLQQ2HmgPFgQF/RMSrCnAmpqtPIPgHe24FZ MDAb6tdva71RmQclfAsLrfIq5b0nVWoaTz0sgdswhIAsMrx4uOY+n+ypmQzf+tTWa5aV aY2A== X-Received: by 10.14.211.65 with SMTP id v41mr80589773eeo.33.1362569442678; Wed, 06 Mar 2013 03:30:42 -0800 (PST) Received: from localhost.localdomain (p4FD2500B.dip.t-dialin.net. [79.210.80.11]) by mx.google.com with ESMTPS id u44sm41940111eel.7.2013.03.06.03.30.40 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 06 Mar 2013 03:30:42 -0800 (PST) From: Bastian Hecht To: linux-sh@vger.kernel.org Subject: [PATCH v6 1/3] serial: sh-sci: Add OF support Date: Wed, 6 Mar 2013 12:30:35 +0100 Message-Id: <1362569437-11133-1-git-send-email-hechtb+renesas@gmail.com> X-Mailer: git-send-email 1.7.9.5 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130306_063045_172659_14C5F20E X-CRM114-Status: GOOD ( 22.75 ) X-Spam-Score: -2.7 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [74.125.83.53 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (hechtb[at]gmail.com) -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature Cc: Simon Horman , Paul Mundt , Magnus Damm , linux-arm-kernel@lists.infradead.org, Arnd Bergmann X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org We add the capabilty to probe Renesas SCI devices using Device Tree setup. Signed-off-by: Bastian Hecht Reviewed-by: Paul Mundt Acked-by: Arnd Bergmann --- v6: putting it all together: I posted v5 as an incremental patch - here the full version based on Simon Horman's tree topic/intc-of. I will post another incremental version as well. - rename sci@xxxxxxxx to serial@xxxxxxxx - stick to scbrr-algorithm .../bindings/tty/serial/renesas,sci-serial.txt | 47 +++++++ drivers/tty/serial/sh-sci.c | 146 +++++++++++++++++++- include/linux/serial_sci.h | 4 + 3 files changed, 193 insertions(+), 4 deletions(-) create mode 100644 Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt diff --git a/Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt new file mode 100644 index 0000000..d80039e --- /dev/null +++ b/Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt @@ -0,0 +1,47 @@ +* Renesas SH-Mobile Serial Communication Interface + +Required properties: +- compatible : Should be "renesas,sci--uart", where is + "sci", "scif", "irda", "scifa", "scifb" + or for legacy devices + "sh2_scif_fifodata", "sh3_scif", "sh4_scif", "sh4_scif_no_scsptr", + "sh4_scif_fifodata", "sh7705_scif". +- reg : Address and length of the register set for the device +- interrupts : Should contain the following IRQs in this order: + ERI: receive-error interrupt + RXI: receive-FIFO-data-full interrupt + TXI: transmit-FIFO-data-empty interrupt + BRI: break reception interrupt +- interrupt-names: The IRQ names "eri", "rxi", "txi" and "bri". +- cell-index : The device id. +- renesas,scscr : Should contain a bitfield used by the Serial Control Register. + b7 = SCSCR_TIE + b6 = SCSCR_RIE + b5 = SCSCR_TE + b4 = SCSCR_RE + b3 = SCSCR_REIE + b2 = SCSCR_TOIE + b1 = SCSCR_CKE1 + b0 = SCSCR_CKE0 +- renesas,scbrr-algorithm : Choose an algorithm ID for the baud rate generator. + 1 = SCBRR_ALGO_1 ((clk + 16 * bps) / (16 * bps) - 1) + 2 = SCBRR_ALGO_2 ((clk + 16 * bps) / (32 * bps) - 1) + 3 = SCBRR_ALGO_3 (((clk * 2) + 16 * bps) / (16 * bps) - 1) + 4 = SCBRR_ALGO_4 (((clk * 2) + 16 * bps) / (32 * bps) - 1) + 5 = SCBRR_ALGO_5 (((clk * 1000 / 32) / bps) - 1) + +Optional properties: +- renesas,autoconf : Set if device is capable of auto configuration. + +Example: + serial@e6c50000 { + compatible = "renesas,sci-scifa-uart"; + interrupt-parent = <&intca>; + reg = <0xe6c50000 0x100>; + interrupts = <0x0c20>, <0x0c20>, <0x0c20>, <0x0c20>; + interrupt-names = "eri", "rxi", "txi", "bri"; + cell-index = <1>; + renesas,scscr = <0x30>; + renesas,scbrr-algorithm = <4>; + renesas,autoconf; + }; diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 6147756..03bb740 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -52,6 +52,7 @@ #include #include #include +#include #ifdef CONFIG_SUPERH #include @@ -2353,6 +2354,131 @@ static int sci_remove(struct platform_device *dev) return 0; } +static const struct of_device_id of_sci_match[] = { + { .compatible = "renesas,sci-sci-uart", + .data = (void *)SCIx_SCI_REGTYPE }, + { .compatible = "renesas,sci-scif-uart", + .data = (void *)SCIx_SH4_SCIF_REGTYPE, }, + { .compatible = "renesas,sci-irda-uart", + .data = (void *)SCIx_IRDA_REGTYPE }, + { .compatible = "renesas,sci-scifa-uart", + .data = (void *)SCIx_SCIFA_REGTYPE }, + { .compatible = "renesas,sci-scifb-uart", + .data = (void *)SCIx_SCIFB_REGTYPE }, + { .compatible = "renesas,sci-sh2_scif_fifodata-uart", + .data = (void *)SCIx_SH2_SCIF_FIFODATA_REGTYPE }, + { .compatible = "renesas,sci-sh3_scif-uart", + .data = (void *)SCIx_SH3_SCIF_REGTYPE }, + { .compatible = "renesas,sci-sh4_scif-uart", + .data = (void *)SCIx_SH4_SCIF_REGTYPE }, + { .compatible = "renesas,sci-sh4_scif_no_scsptr-uart", + .data = (void *)SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE }, + { .compatible = "renesas,sci-sh4_scif_fifodata-uart", + .data = (void *)SCIx_SH4_SCIF_FIFODATA_REGTYPE }, + { .compatible = "renesas,sci-sh7705_scif-uart", + .data = (void *)SCIx_SH7705_SCIF_REGTYPE }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_sci_match); + +static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev, + int *dev_id) +{ + struct plat_sci_port *p; + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + struct resource *res; + const __be32 *prop; + int i, irq, val; + + if (!IS_ENABLED(CONFIG_OF) || !np) + return NULL; + + match = of_match_node(of_sci_match, pdev->dev.of_node); + if (!match || !match->data) { + dev_err(&pdev->dev, "OF match error\n"); + return NULL; + } + + p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL); + if (!p) { + dev_err(&pdev->dev, "failed to allocate DT config data\n"); + return NULL; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "failed to get I/O memory\n"); + return NULL; + } + p->mapbase = res->start; + + for (i = 0; i < SCIx_NR_IRQS; i++) { + irq = platform_get_irq(pdev, i); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get irq data %d\n", i); + return NULL; + } + p->irqs[i] = irq; + } + + prop = of_get_property(np, "cell-index", NULL); + if (!prop) { + dev_err(&pdev->dev, "required DT prop cell-index missing\n"); + return NULL; + } + *dev_id = be32_to_cpup(prop); + + prop = of_get_property(np, "renesas,scscr", NULL); + if (!prop) { + dev_err(&pdev->dev, "required DT prop scscr missing\n"); + return NULL; + } + p->scscr = be32_to_cpup(prop); + + prop = of_get_property(np, "renesas,scbrr-algorithm", NULL); + if (!prop) { + dev_err(&pdev->dev, "required DT prop scbrr-algorithm missing\n"); + return NULL; + } + val = be32_to_cpup(prop); + if (val <= SCBRR_ALGO_INVALID || val >= SCBRR_NR_ALGOS) { + dev_err(&pdev->dev, "DT prop clock-algorithm out of range\n"); + return NULL; + } + p->scbrr_algo_id = val; + + p->flags = UPF_IOREMAP; + if (of_get_property(np, "renesas,autoconf", NULL)) + p->flags |= UPF_BOOT_AUTOCONF; + + p->regtype = (unsigned int)match->data; + + switch (p->regtype) { + case SCIx_SCI_REGTYPE: + p->type = PORT_SCI; + break; + case SCIx_SH4_SCIF_REGTYPE: + p->type = PORT_SCIF; + break; + case SCIx_IRDA_REGTYPE: + p->type = PORT_IRDA; + break; + case SCIx_SCIFA_REGTYPE: + p->type = PORT_SCIFA; + break; + case SCIx_SCIFB_REGTYPE: + p->type = PORT_SCIFB; + break; + default: + /* legacy register sets default to PORT_SCIF */ + p->type = PORT_SCIF; + break; + } + + return p; +} + static int sci_probe_single(struct platform_device *dev, unsigned int index, struct plat_sci_port *p, @@ -2385,9 +2511,9 @@ static int sci_probe_single(struct platform_device *dev, static int sci_probe(struct platform_device *dev) { - struct plat_sci_port *p = dev->dev.platform_data; - struct sci_port *sp = &sci_ports[dev->id]; - int ret; + struct plat_sci_port *p; + struct sci_port *sp; + int ret, dev_id = dev->id; /* * If we've come here via earlyprintk initialization, head off to @@ -2397,9 +2523,20 @@ static int sci_probe(struct platform_device *dev) if (is_early_platform_device(dev)) return sci_probe_earlyprintk(dev); + if (dev->dev.of_node) + p = sci_parse_dt(dev, &dev_id); + else + p = dev->dev.platform_data; + + if (!p) { + dev_err(&dev->dev, "no setup data supplied\n"); + return -EINVAL; + } + + sp = &sci_ports[dev_id]; platform_set_drvdata(dev, sp); - ret = sci_probe_single(dev, dev->id, p, sp); + ret = sci_probe_single(dev, dev_id, p, sp); if (ret) return ret; @@ -2451,6 +2588,7 @@ static struct platform_driver sci_driver = { .name = "sh-sci", .owner = THIS_MODULE, .pm = &sci_dev_pm_ops, + .of_match_table = of_match_ptr(of_sci_match), }, }; diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index eb763ad..857eec4 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -11,11 +11,15 @@ #define SCIx_NOT_SUPPORTED (-1) enum { + SCBRR_ALGO_INVALID, + SCBRR_ALGO_1, /* ((clk + 16 * bps) / (16 * bps) - 1) */ SCBRR_ALGO_2, /* ((clk + 16 * bps) / (32 * bps) - 1) */ SCBRR_ALGO_3, /* (((clk * 2) + 16 * bps) / (16 * bps) - 1) */ SCBRR_ALGO_4, /* (((clk * 2) + 16 * bps) / (32 * bps) - 1) */ SCBRR_ALGO_5, /* (((clk * 1000 / 32) / bps) - 1) */ + + SCBRR_NR_ALGOS, }; #define SCSCR_TIE (1 << 7)