From patchwork Tue Sep 11 08:54:24 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Ujfalusi X-Patchwork-Id: 1436051 Return-Path: X-Original-To: patchwork-linux-omap@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id D73FADFAF3 for ; Tue, 11 Sep 2012 08:53:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752861Ab2IKIx6 (ORCPT ); Tue, 11 Sep 2012 04:53:58 -0400 Received: from na3sys009aog122.obsmtp.com ([74.125.149.147]:42153 "EHLO na3sys009aog122.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751572Ab2IKIx4 (ORCPT ); Tue, 11 Sep 2012 04:53:56 -0400 Received: from mail-ob0-f174.google.com ([209.85.214.174]) (using TLSv1) by na3sys009aob122.postini.com ([74.125.148.12]) with SMTP ID DSNKUE78I+RTB7Xh4j92OF+BPEcl2vbME0DG@postini.com; Tue, 11 Sep 2012 01:53:56 PDT Received: by obbuo13 with SMTP id uo13so367164obb.19 for ; Tue, 11 Sep 2012 01:53:55 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:x-gm-message-state; bh=uFTFDLV700YbZHERAK91di0g3g6xupMjTFyfhM06B6w=; b=gvEw9unr4P1rPwpRESVfrKHknUuCnw4cvZ9BxoArZklqJgCBE9lQQm+L0JbOHgru0n dWISvWRASV52ahze0WgtE19APa8TNRT2ZlF//26Fg1d64oNFesCcchLJfpS7GmsRj+6x yAjzqdr012U3C2Uhd3Wf5uXQCFuVQDXWOW8BGhxmdunVorm02aQDtrSTBtgJyEmEeWVI 52ADFlh3wnQz1MlfwWMXDxuGgu9VT8+hCD7dBw4VbFUvwWvptxJHwPMJGw0scvuS/QcR C/Ln4ZSRytaTiLojWGdjAGu2JNFBHgJFwGil4TZDa/4HAwyhjgvRzQEYewPIyD0XnWnQ d6vw== Received: by 10.60.25.226 with SMTP id f2mr16742646oeg.53.1347353635158; Tue, 11 Sep 2012 01:53:55 -0700 (PDT) Received: from barack.emea.dhcp.ti.com (dragon.ti.com. [192.94.94.33]) by mx.google.com with ESMTPS id a20sm12366844oei.2.2012.09.11.01.53.53 (version=SSLv3 cipher=OTHER); Tue, 11 Sep 2012 01:53:54 -0700 (PDT) From: Peter Ujfalusi To: Linus Walleij , Tony Lindgren Cc: linux-omap@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2] pinctrl: pinctrl-single: Add pinctrl-single, bits type of mux Date: Tue, 11 Sep 2012 11:54:24 +0300 Message-Id: <1347353664-15906-1-git-send-email-peter.ujfalusi@ti.com> X-Mailer: git-send-email 1.7.12 X-Gm-Message-State: ALoCoQkljpqw2EDoEYBYTtIYQFAVw9OcPVA7ICFGecjtmw1H48MQExoGvTM1AVIzVGTVe3itf3Rn Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org With pinctrl-single,bits it is possible to update just part of the register within the pinctrl-single,function-mask area. This is useful when one register configures mmore than one pin's mux. pinctrl-single,bits takes three parameters: Signed-off-by: Peter Ujfalusi Acked-by: Tony Lindgren --- Hello Tony, Linus, Changes since v1: - Added boolean for the pinctrl-single: pinctrl-single,bit-per-mux When this is set the it indicates that the area contains registers which changes mux for multible pins. - Documentation updated reflecting this change (with example for this type) Regards, Peter .../devicetree/bindings/pinctrl/pinctrl-single.txt | 41 +++++++++++++++++-- drivers/pinctrl/pinctrl-single.c | 46 +++++++++++++++++----- 2 files changed, 74 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt index 5187f0d..2c81e45 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt @@ -14,10 +14,12 @@ Optional properties: - pinctrl-single,function-off : function off mode for disabled state if available and same for all registers; if not specified, disabling of pin functions is ignored +- pinctrl-single,bit-per-mux : boolean to indicate that one register controls + more than one pin -This driver assumes that there is only one register for each pin, -and uses the common pinctrl bindings as specified in the pinctrl-bindings.txt -document in this directory. +This driver assumes that there is only one register for each pin (unless the +pinctrl-single,bit-per-mux is set), and uses the common pinctrl bindings as +specified in the pinctrl-bindings.txt document in this directory. The pin configuration nodes for pinctrl-single are specified as pinctrl register offset and value pairs using pinctrl-single,pins. Only the bits @@ -31,6 +33,15 @@ device pinctrl register, and 0x118 contains the desired value of the pinctrl register. See the device example and static board pins example below for more information. +In case when one register changes more than one pin's mux the +pinctrl-single,bits need to be used which takes three parameters: + + pinctrl-single,bits = <0xdc 0x18, 0xff>; + +Where 0xdc is the offset from the pinctrl register base address for the +device pinctrl register, 0x18 is the desired value, and 0xff is the sub mask to +be used when applying this change to the register. + Example: /* SoC common file */ @@ -55,6 +66,15 @@ pmx_wkup: pinmux@4a31e040 { pinctrl-single,function-mask = <0xffff>; }; +control_devconf0: pinmux@48002274 { + compatible = "pinctrl-single"; + reg = <0x48002274 4>; /* Single register */ + #address-cells = <1>; + #size-cells = <0>; + pinctrl-single,bit-per-mux; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x5F>; +}; /* board specific .dts file */ @@ -87,6 +107,21 @@ pmx_wkup: pinmux@4a31e040 { }; }; +&control_devconf0 { + mcbsp1_pins: pinmux_mcbsp1_pins { + pinctrl-single,bits = < + 0x00 0x18 0x18 /* FSR/CLKR signal from FSX/CLKX pin */ + >; + }; + + mcbsp2_clks_pins: pinmux_mcbsp2_clks_pins { + pinctrl-single,bits = < + 0x00 0x40 0x40 /* McBSP2 CLKS from McBSP_CLKS pin */ + >; + }; + +}; + &uart2 { pinctrl-names = "default"; pinctrl-0 = <&uart2_pins>; diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 3508631..759b5a6 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -26,7 +26,8 @@ #include "core.h" #define DRIVER_NAME "pinctrl-single" -#define PCS_MUX_NAME "pinctrl-single,pins" +#define PCS_MUX_PINS_NAME "pinctrl-single,pins" +#define PCS_MUX_BITS_NAME "pinctrl-single,bits" #define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1) #define PCS_OFF_DISABLED ~0U @@ -54,6 +55,7 @@ struct pcs_pingroup { struct pcs_func_vals { void __iomem *reg; unsigned val; + unsigned mask; }; /** @@ -139,6 +141,7 @@ struct pcs_device { unsigned fshift; unsigned foff; unsigned fmax; + bool bits_per_mux; struct pcs_name *names; struct pcs_data pins; struct radix_tree_root pgtree; @@ -332,12 +335,17 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector, for (i = 0; i < func->nvals; i++) { struct pcs_func_vals *vals; - unsigned val; + unsigned val, mask; vals = &func->vals[i]; val = pcs->read(vals->reg); - val &= ~pcs->fmask; - val |= (vals->val & pcs->fmask); + if (!vals->mask) + mask = pcs->fmask; + else + mask = pcs->fmask & vals->mask; + + val &= ~mask; + val |= (vals->val & mask); pcs->write(val, vals->reg); } @@ -657,18 +665,29 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, { struct pcs_func_vals *vals; const __be32 *mux; - int size, rows, *pins, index = 0, found = 0, res = -ENOMEM; + int size, params, rows, *pins, index = 0, found = 0, res = -ENOMEM; struct pcs_function *function; - mux = of_get_property(np, PCS_MUX_NAME, &size); - if ((!mux) || (size < sizeof(*mux) * 2)) { - dev_err(pcs->dev, "bad data for mux %s\n", - np->name); + if (pcs->bits_per_mux) { + params = 3; + mux = of_get_property(np, PCS_MUX_BITS_NAME, &size); + } else { + params = 2; + mux = of_get_property(np, PCS_MUX_PINS_NAME, &size); + } + + if (!mux) { + dev_err(pcs->dev, "no valid property for %s\n", np->name); + return -EINVAL; + } + + if (size < (sizeof(*mux) * params)) { + dev_err(pcs->dev, "bad data for %s\n", np->name); return -EINVAL; } size /= sizeof(*mux); /* Number of elements in array */ - rows = size / 2; /* Each row is a key value pair */ + rows = size / params; /* Each row is a key value pair */ vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL); if (!vals) @@ -686,6 +705,10 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, val = be32_to_cpup(mux + index++); vals[found].reg = pcs->base + offset; vals[found].val = val; + if (params == 3) { + val = be32_to_cpup(mux + index++); + vals[found].mask = val; + } pin = pcs_get_pin_by_offset(pcs, offset); if (pin < 0) { @@ -883,6 +906,9 @@ static int __devinit pcs_probe(struct platform_device *pdev) if (ret) pcs->foff = PCS_OFF_DISABLED; + pcs->bits_per_mux = of_property_read_bool(np, + "pinctrl-single,bit-per-mux"); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(pcs->dev, "could not get resource\n");