* Re: [PATCH v2 1/5] pinctrl: Allow modules to use pinctrl_[un]register_mappings
From: Hans de Goede @ 2020-01-01 13:04 UTC (permalink / raw)
To: Linus Walleij
Cc: Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Ville Syrjälä, intel-gfx, Lee Jones, Andy Shevchenko,
open list:DRM PANEL DRIVERS, linux-kernel@vger.kernel.org,
open list:GPIO SUBSYSTEM
In-Reply-To: <CACRpkdaXFSJVkWJGzsVcvbUA9gpgP0Vbkwf1H-HWw8s35R9XYQ@mail.gmail.com>
Hi,
On 30-12-2019 14:31, Linus Walleij wrote:
> On Mon, Dec 16, 2019 at 9:51 PM Hans de Goede <hdegoede@redhat.com> wrote:
>
>> Currently only the drivers/pinctrl/devicetree.c code allows registering
>> pinctrl-mappings which may later be unregistered, all other mappings
>> are assumed to be permanent.
>>
>> Non-dt platforms may also want to register pinctrl mappings from code which
>> is build as a module, which requires being able to unregister the mapping
>> when the module is unloaded to avoid dangling pointers.
>>
>> To allow unregistering the mappings the devicetree code uses 2 internal
>> functions: pinctrl_register_map and pinctrl_unregister_map.
>>
>> pinctrl_register_map allows the devicetree code to tell the core to
>> not memdup the mappings as it retains ownership of them and
>> pinctrl_unregister_map does the unregistering, note this only works
>> when the mappings where not memdupped.
>>
>> The only code relying on the memdup/shallow-copy done by
>> pinctrl_register_mappings is arch/arm/mach-u300/core.c this commit
>> replaces the __initdata with const, so that the shallow-copy is no
>> longer necessary.
>>
>> After that we can get rid of the internal pinctrl_unregister_map function
>> and just use pinctrl_register_mappings directly everywhere.
>>
>> This commit also renames pinctrl_unregister_map to
>> pinctrl_unregister_mappings so that its naming matches its
>> pinctrl_register_mappings counter-part and exports it.
>>
>> Together these 2 changes will allow non-dt platform code to
>> register pinctrl-mappings from modules without breaking things on
>> module unload (as they can now unregister the mapping on unload).
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>
> This v2 works fine for me, I applied it to this immutable branch in the
> pinctrl tree:
> https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git/log/?h=ib-pinctrl-unreg-mappings
>
> And pulled that into the pinctrl "devel" branch for v5.6.
>
> Please pull this immutable branch into the Intel DRM tree and apply
> the rest of the stuff on top!
Great, thank you!
Regards,
Hans
p.s.
Happy New year everyone.
^ permalink raw reply
* [PATCH 00/16] constify copied structure
From: Julia Lawall @ 2020-01-01 7:43 UTC (permalink / raw)
To: Jernej Skrabec
Cc: kernel-janitors, Jonas Karlman, Laurent Pinchart, linuxppc-dev,
linux-fbdev, dri-devel, linux-media, linux-kernel, alsa-devel,
linux-arm-kernel, linux-usb, linux-arm-msm, linux-gpio, linux-nfs,
netdev
Make const static structures that are just copied into other structures.
The semantic patch that detects the opportunity for this change is as
follows: (http://coccinelle.lip6.fr/)
<smpl>
@r disable optional_qualifier@
identifier i,j;
position p;
@@
static struct i j@p = { ... };
@upd@
position p1;
identifier r.j;
expression e;
@@
e = j@p1
@ref@
position p2 != {r.p,upd.p1};
identifier r.j;
@@
j@p2
@script:ocaml depends on upd && !ref@
i << r.i;
j << r.j;
p << r.p;
@@
if j = (List.hd p).current_element
then Coccilib.print_main i p
</smpl>
---
arch/powerpc/sysdev/mpic.c | 4 ++--
drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c | 2 +-
drivers/media/i2c/mt9v111.c | 2 +-
drivers/media/platform/davinci/isif.c | 2 +-
drivers/media/usb/cx231xx/cx231xx-dvb.c | 2 +-
drivers/media/usb/dvb-usb-v2/anysee.c | 4 ++--
drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c | 2 +-
drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c | 2 +-
drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c | 2 +-
drivers/ptp/ptp_clockmatrix.c | 2 +-
drivers/usb/gadget/udc/atmel_usba_udc.c | 2 +-
drivers/video/fbdev/sa1100fb.c | 2 +-
net/sunrpc/xdr.c | 2 +-
sound/isa/ad1816a/ad1816a_lib.c | 2 +-
sound/pci/hda/hda_controller.c | 2 +-
sound/soc/qcom/qdsp6/q6asm-dai.c | 2 +-
16 files changed, 18 insertions(+), 18 deletions(-)
^ permalink raw reply
* [PATCH 08/16] pinctrl: ssbi-mpp: constify copied structure
From: Julia Lawall @ 2020-01-01 7:43 UTC (permalink / raw)
To: Andy Gross
Cc: kernel-janitors, Bjorn Andersson, Linus Walleij, linux-arm-msm,
linux-gpio, linux-kernel
In-Reply-To: <1577864614-5543-1-git-send-email-Julia.Lawall@inria.fr>
The pm8xxx_pinctrl_desc structure is only copied into another structure,
so make it const.
The opportunity for this change was found using Coccinelle.
Signed-off-by: Julia Lawall <Julia.Lawall@inria.fr>
---
drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c b/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
index 3d8b1d74fa2f..681d8dcf37e3 100644
--- a/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
+++ b/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
@@ -430,7 +430,7 @@ static const struct pinconf_ops pm8xxx_pinconf_ops = {
.pin_config_group_set = pm8xxx_pin_config_set,
};
-static struct pinctrl_desc pm8xxx_pinctrl_desc = {
+static const struct pinctrl_desc pm8xxx_pinctrl_desc = {
.name = "pm8xxx_mpp",
.pctlops = &pm8xxx_pinctrl_ops,
.pmxops = &pm8xxx_pinmux_ops,
^ permalink raw reply related
* [PATCH 14/16] pinctrl: qcom: ssbi-gpio: constify copied structure
From: Julia Lawall @ 2020-01-01 7:43 UTC (permalink / raw)
To: Bjorn Andersson
Cc: kernel-janitors, Andy Gross, Linus Walleij, linux-arm-msm,
linux-gpio, linux-kernel
In-Reply-To: <1577864614-5543-1-git-send-email-Julia.Lawall@inria.fr>
The pm8xxx_pinctrl_desc structure is only copied into another
structure, so make it const.
The opportunity for this change was found using Coccinelle.
Signed-off-by: Julia Lawall <Julia.Lawall@inria.fr>
---
drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
index dca86886b1f9..c7912135bbfb 100644
--- a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
+++ b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
@@ -439,7 +439,7 @@ static const struct pinconf_ops pm8xxx_pinconf_ops = {
.pin_config_group_set = pm8xxx_pin_config_set,
};
-static struct pinctrl_desc pm8xxx_pinctrl_desc = {
+static const struct pinctrl_desc pm8xxx_pinctrl_desc = {
.name = "pm8xxx_gpio",
.pctlops = &pm8xxx_pinctrl_ops,
.pmxops = &pm8xxx_pinmux_ops,
^ permalink raw reply related
* [PATCH 16/16] pinctrl: nuvoton: npcm7xx: constify copied structure
From: Julia Lawall @ 2020-01-01 7:43 UTC (permalink / raw)
To: Linus Walleij; +Cc: kernel-janitors, linux-gpio, linux-kernel
In-Reply-To: <1577864614-5543-1-git-send-email-Julia.Lawall@inria.fr>
The npcmgpio_irqchip structure is only copied into another
structure, so make it const.
The opportunity for this change was found using Coccinelle.
Signed-off-by: Julia Lawall <Julia.Lawall@inria.fr>
---
drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
index 22077cbe6880..a935065cdac4 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
@@ -331,7 +331,7 @@ static unsigned int npcmgpio_irq_startup(struct irq_data *d)
return 0;
}
-static struct irq_chip npcmgpio_irqchip = {
+static const struct irq_chip npcmgpio_irqchip = {
.name = "NPCM7XX-GPIO-IRQ",
.irq_ack = npcmgpio_irq_ack,
.irq_unmask = npcmgpio_irq_unmask,
^ permalink raw reply related
* Re: [PATCH] dt-bindings: pinctrl: Convert generic pin mux and config properties to schema
From: Linus Walleij @ 2019-12-31 18:44 UTC (permalink / raw)
To: Rob Herring
Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
linux-kernel@vger.kernel.org, Maxime Ripard,
open list:GPIO SUBSYSTEM
In-Reply-To: <20191107224254.15712-1-robh@kernel.org>
Hm it appears the following reply was stuck (no SMTP response or something):
On Thu, Nov 7, 2019 at 11:42 PM Rob Herring <robh@kernel.org> wrote:
> As pinctrl bindings have a flexible structure and no standard child node
> naming convention, creating a single pinctrl schema doesn't work. Instead,
> create schemas for the pin mux and config nodes which device pinctrl schema
> can reference.
>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: linux-gpio@vger.kernel.org
> Signed-off-by: Rob Herring <robh@kernel.org>
Patch applied. I am a big fan of schemas.
I still feel like swimming in deep waters sometimes when using it
and like I "fake it til I make it", I suppose one day I will grok the
inner transcendental meaning of this notation. Maybe.
> We're starting to see pinctrl schema doing their own definitions for
> generic properties, so we need to get something in place to reference.
ACK.
> Maybe this could be combined into a single schema? Spliting it was
> easier in order to just copy over the existing documentation.
We can surely do that later.
> Reading thru pinctrl-bindings.txt, I'm wondering if some of it is out
> of date. Do we let new bindings not use the generic muxing properties?
> Do we really need to be so flexible for child node structure?
The bindings are quite flexible because we simply could not agree
on a single semantic. Initially AT91, i.MX and pinctrl-single used the
strategy of just storing u32's in the tree to be poked into registers
to set up a certain muxing rather than strings to identify groups and
functions.
I tried to push and define the generic string-based muxing of functions
with groups and also using strings for pin configuration.
The downside of this approach is that pins need to be bundled into
groups based on use case. This is not perfect: sometimes we get
the wrong groups because all use cases can not be predicted when
writing a driver. A typical example would be that a UART group
would be four pins [RX TX CTS RTS]. Late the author realized
that systems actually want two groups [RX TX] [CTS RTS] so they
can punt out the [CTS RTS] group and reuse that for e.g. GPIO
when only RX and TX is in use.
At some point I was pretty heavily pushed by
some contributors who thought the idea to define groups
for all use cases was vain and wanted to use enumed numerals to define
all their settings on a per-pin basis and who felt the generic
muxing (and generic config) was inappropriate for their use cases.
This goes especially for STM32 and Rockchip IIRC but I could be
wrong. TI followed this pattern with the k3 and dra drivers.
This was something like 50% of the pin control community at the
time, not a vocal minority but a vocal 50%.
So I caved in and merged them. I could not really stand in the way
for this vital piece of infrastructure as it essentially stops the systems
from even booting a mainline kernel. I assumed it was the lesser
evil.
The fact of the day is that a significant portion of the pin control
authors like the magic numbers from defined in <dt-bindings/pinctrl/*.h>
files (sometimes corresponding to register values) and the case
is rather lost: these will be around and there will likely also be
more of them.
I personally prefer the string based configuration (functions muxed
to groups and abstract standard strings for configs) as the higher
abstraction gives a better fit with the ambitions of the device tree.
But it is not like the per-pin and magic numbers lack merit.
Yours,
Linus Walleij
^ permalink raw reply
* linusw/for-next boot: 56 boots: 1 failed, 55 passed (v5.5-rc4-9-g331d7ae3fa15)
From: kernelci.org bot @ 2019-12-31 17:17 UTC (permalink / raw)
To: linux-gpio, fellows
linusw/for-next boot: 56 boots: 1 failed, 55 passed (v5.5-rc4-9-g331d7ae3fa15)
Full Boot Summary: https://kernelci.org/boot/all/job/linusw/branch/for-next/kernel/v5.5-rc4-9-g331d7ae3fa15/
Full Build Summary: https://kernelci.org/build/linusw/branch/for-next/kernel/v5.5-rc4-9-g331d7ae3fa15/
Tree: linusw
Branch: for-next
Git Describe: v5.5-rc4-9-g331d7ae3fa15
Git Commit: 331d7ae3fa15f36a25fa83590d4bfcfc0e37a73c
Git URL: https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git/
Tested: 48 unique boards, 14 SoC families, 3 builds out of 5
Boot Regressions Detected:
arm:
multi_v7_defconfig:
gcc-8:
rk3288-rock2-square:
lab-collabora: new failure (last pass: v5.5-rc1-20-g06c4fc5eda6b)
Boot Failure Detected:
arm:
multi_v7_defconfig:
gcc-8:
rk3288-rock2-square: 1 failed lab
---
For more info write to <info@kernelci.org>
^ permalink raw reply
* linusw/fixes boot: 56 boots: 2 failed, 54 passed (v5.5-rc4)
From: kernelci.org bot @ 2019-12-31 17:16 UTC (permalink / raw)
To: linux-gpio, fellows
linusw/fixes boot: 56 boots: 2 failed, 54 passed (v5.5-rc4)
Full Boot Summary: https://kernelci.org/boot/all/job/linusw/branch/fixes/kernel/v5.5-rc4/
Full Build Summary: https://kernelci.org/build/linusw/branch/fixes/kernel/v5.5-rc4/
Tree: linusw
Branch: fixes
Git Describe: v5.5-rc4
Git Commit: fd6988496e79a6a4bdb514a4655d2920209eb85d
Git URL: https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git/
Tested: 48 unique boards, 14 SoC families, 3 builds out of 5
Boot Regressions Detected:
arm:
multi_v7_defconfig:
gcc-8:
rk3288-rock2-square:
lab-collabora: new failure (last pass: gpio-v5.5-1-2-gd196292990fc)
arm64:
defconfig:
gcc-8:
meson-gxm-q200:
lab-baylibre: new failure (last pass: v5.5-rc1-10-g279b1fed09ea)
Boot Failures Detected:
arm64:
defconfig:
gcc-8:
meson-gxm-q200: 1 failed lab
arm:
multi_v7_defconfig:
gcc-8:
rk3288-rock2-square: 1 failed lab
---
For more info write to <info@kernelci.org>
^ permalink raw reply
* linusw/for-next build: 5 builds: 0 failed, 5 passed, 1 warning (v5.5-rc4-9-g331d7ae3fa15)
From: kernelci.org bot @ 2019-12-31 16:32 UTC (permalink / raw)
To: linux-gpio, fellows
linusw/for-next build: 5 builds: 0 failed, 5 passed, 1 warning (v5.5-rc4-9-g331d7ae3fa15)
Full Build Summary: https://kernelci.org/build/linusw/branch/for-next/kernel/v5.5-rc4-9-g331d7ae3fa15/
Tree: linusw
Branch: for-next
Git Describe: v5.5-rc4-9-g331d7ae3fa15
Git Commit: 331d7ae3fa15f36a25fa83590d4bfcfc0e37a73c
Git URL: https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git/
Built: 5 unique architectures
Warnings Detected:
arm64:
arm:
mips:
riscv:
x86_64:
x86_64_defconfig (gcc-8): 1 warning
Warnings summary:
1 include/linux/of_mdio.h:58:13: warning: ‘of_mdiobus_child_is_phy’ defined but not used [-Wunused-function]
================================================================================
Detailed per-defconfig build reports:
--------------------------------------------------------------------------------
32r2el_defconfig (mips, gcc-8) — PASS, 0 errors, 0 warnings, 0 section mismatches
--------------------------------------------------------------------------------
defconfig (riscv, gcc-8) — PASS, 0 errors, 0 warnings, 0 section mismatches
--------------------------------------------------------------------------------
defconfig (arm64, gcc-8) — PASS, 0 errors, 0 warnings, 0 section mismatches
--------------------------------------------------------------------------------
multi_v7_defconfig (arm, gcc-8) — PASS, 0 errors, 0 warnings, 0 section mismatches
--------------------------------------------------------------------------------
x86_64_defconfig (x86_64, gcc-8) — PASS, 0 errors, 1 warning, 0 section mismatches
Warnings:
include/linux/of_mdio.h:58:13: warning: ‘of_mdiobus_child_is_phy’ defined but not used [-Wunused-function]
---
For more info write to <info@kernelci.org>
^ permalink raw reply
* linusw/fixes build: 5 builds: 0 failed, 5 passed, 1 warning (v5.5-rc4)
From: kernelci.org bot @ 2019-12-31 16:31 UTC (permalink / raw)
To: linux-gpio, fellows
linusw/fixes build: 5 builds: 0 failed, 5 passed, 1 warning (v5.5-rc4)
Full Build Summary: https://kernelci.org/build/linusw/branch/fixes/kernel/v5.5-rc4/
Tree: linusw
Branch: fixes
Git Describe: v5.5-rc4
Git Commit: fd6988496e79a6a4bdb514a4655d2920209eb85d
Git URL: https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git/
Built: 5 unique architectures
Warnings Detected:
arm64:
arm:
mips:
riscv:
x86_64:
x86_64_defconfig (gcc-8): 1 warning
Warnings summary:
1 include/linux/of_mdio.h:58:13: warning: ‘of_mdiobus_child_is_phy’ defined but not used [-Wunused-function]
================================================================================
Detailed per-defconfig build reports:
--------------------------------------------------------------------------------
32r2el_defconfig (mips, gcc-8) — PASS, 0 errors, 0 warnings, 0 section mismatches
--------------------------------------------------------------------------------
defconfig (riscv, gcc-8) — PASS, 0 errors, 0 warnings, 0 section mismatches
--------------------------------------------------------------------------------
defconfig (arm64, gcc-8) — PASS, 0 errors, 0 warnings, 0 section mismatches
--------------------------------------------------------------------------------
multi_v7_defconfig (arm, gcc-8) — PASS, 0 errors, 0 warnings, 0 section mismatches
--------------------------------------------------------------------------------
x86_64_defconfig (x86_64, gcc-8) — PASS, 0 errors, 1 warning, 0 section mismatches
Warnings:
include/linux/of_mdio.h:58:13: warning: ‘of_mdiobus_child_is_phy’ defined but not used [-Wunused-function]
---
For more info write to <info@kernelci.org>
^ permalink raw reply
* [PATCH v7 6/6] Add support for pin configuration dump via debugfs.
From: Light Hsieh @ 2019-12-31 13:41 UTC (permalink / raw)
To: linus.walleij
Cc: linux-mediatek, linux-gpio, linux-kernel, sean.wang, kuohong.wang,
Light Hsieh
In-Reply-To: <1577799707-11855-1-git-send-email-light.hsieh@mediatek.com>
Add support for pin configuration dump via catting
/sys/kernel/debug/pinctrl/$platform_dependent_path/pinconf-pins.
pinctrl framework had already support such dump. This patch implement the
operation function pointer to fullfill this dump.
Change-Id: I823642561adaedb847e77f9a8baea182913d6163
---
drivers/pinctrl/mediatek/pinctrl-paris.c | 109 +++++++++++++++++++++++++++++++
drivers/pinctrl/mediatek/pinctrl-paris.h | 3 +
2 files changed, 112 insertions(+)
diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c
index 115ebc1..83bf29c 100644
--- a/drivers/pinctrl/mediatek/pinctrl-paris.c
+++ b/drivers/pinctrl/mediatek/pinctrl-paris.c
@@ -539,12 +539,120 @@ static int mtk_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
return 0;
}
+static int mtk_hw_get_value_wrap(struct mtk_pinctrl *hw, unsigned int gpio, int field)
+{
+ const struct mtk_pin_desc *desc;
+ int value, err;
+
+ if (gpio > hw->soc->npins)
+ return -EINVAL;
+
+ desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
+
+ err = mtk_hw_get_value(hw, desc, field, &value);
+ if (err)
+ return err;
+
+ return value;
+}
+
+#define mtk_pctrl_get_pinmux(hw, gpio) \
+ mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_MODE)
+
+#define mtk_pctrl_get_direction(hw, gpio) \
+ mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DIR)
+
+#define mtk_pctrl_get_out(hw, gpio) \
+ mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DO)
+
+#define mtk_pctrl_get_in(hw, gpio) \
+ mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DI)
+
+#define mtk_pctrl_get_smt(hw, gpio) \
+ mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_SMT)
+
+#define mtk_pctrl_get_ies(hw, gpio) \
+ mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_IES)
+
+#define mtk_pctrl_get_driving(hw, gpio) \
+ mtk_hw_get_value_wrap(hw, gpio, PINCTRL_PIN_REG_DRV)
+
+ssize_t mtk_pctrl_show_one_pin(struct mtk_pinctrl *hw,
+ unsigned int gpio, char *buf, unsigned int bufLen)
+{
+ int pinmux, pullup, pullen, len = 0, r1 = -1, r0 = -1;
+ const struct mtk_pin_desc *desc;
+
+ if (gpio > hw->soc->npins)
+ return -EINVAL;
+
+ desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
+ pinmux = mtk_pctrl_get_pinmux(hw, gpio);
+ if (pinmux >= hw->soc->nfuncs)
+ pinmux -= hw->soc->nfuncs;
+
+ mtk_pinconf_bias_get_combo(hw, desc, &pullup, &pullen);
+ if (pullen == MTK_PUPD_SET_R1R0_00) {
+ pullen = 0;
+ r1 = 0;
+ r0 = 0;
+ } else if (pullen == MTK_PUPD_SET_R1R0_01) {
+ pullen = 1;
+ r1 = 0;
+ r0 = 1;
+ } else if (pullen == MTK_PUPD_SET_R1R0_10) {
+ pullen = 1;
+ r1 = 1;
+ r0 = 0;
+ } else if (pullen == MTK_PUPD_SET_R1R0_11) {
+ pullen = 1;
+ r1 = 1;
+ r0 = 1;
+ } else if (pullen != MTK_DISABLE && pullen != MTK_ENABLE) {
+ pullen = 0;
+ }
+ len += snprintf(buf + len, bufLen - len,
+ "%03d: %1d%1d%1d%1d%02d%1d%1d%1d%1d",
+ gpio,
+ pinmux,
+ mtk_pctrl_get_direction(hw, gpio),
+ mtk_pctrl_get_out(hw, gpio),
+ mtk_pctrl_get_in(hw, gpio),
+ mtk_pctrl_get_driving(hw, gpio),
+ mtk_pctrl_get_smt(hw, gpio),
+ mtk_pctrl_get_ies(hw, gpio),
+ pullen,
+ pullup);
+
+ if (r1 != -1) {
+ len += snprintf(buf + len, bufLen - len, " (%1d %1d)\n",
+ r1, r0);
+ } else {
+ len += snprintf(buf + len, bufLen - len, "\n");
+ }
+
+ return len;
+}
+
+#define PIN_DBG_BUF_SZ 96
+static void mtk_pctrl_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+ unsigned int gpio)
+{
+ struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+ char buf[PIN_DBG_BUF_SZ];
+
+ (void)mtk_pctrl_show_one_pin(hw, gpio, buf, PIN_DBG_BUF_SZ);
+
+ seq_printf(s, "%s", buf);
+}
+
static const struct pinctrl_ops mtk_pctlops = {
.dt_node_to_map = mtk_pctrl_dt_node_to_map,
.dt_free_map = pinctrl_utils_free_map,
.get_groups_count = mtk_pctrl_get_groups_count,
.get_group_name = mtk_pctrl_get_group_name,
.get_group_pins = mtk_pctrl_get_group_pins,
+ .pin_dbg_show = mtk_pctrl_dbg_show,
};
static int mtk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
@@ -641,6 +749,7 @@ static int mtk_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
.pin_config_get = mtk_pinconf_get,
.pin_config_group_get = mtk_pconf_group_get,
.pin_config_group_set = mtk_pconf_group_set,
+ .is_generic = true,
};
static struct pinctrl_desc mtk_desc = {
diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.h b/drivers/pinctrl/mediatek/pinctrl-paris.h
index 3d43771..afb7650 100644
--- a/drivers/pinctrl/mediatek/pinctrl-paris.h
+++ b/drivers/pinctrl/mediatek/pinctrl-paris.h
@@ -60,6 +60,9 @@
int mtk_paris_pinctrl_probe(struct platform_device *pdev,
const struct mtk_pin_soc *soc);
+ssize_t mtk_pctrl_show_one_pin(struct mtk_pinctrl *hw,
+ unsigned int gpio, char *buf, unsigned int bufLen);
+
extern const struct dev_pm_ops mtk_paris_pinctrl_pm_ops;
#endif /* __PINCTRL_PARIS_H */
--
1.8.1.1.dirty
^ permalink raw reply related
* [PATCH v7 1/6] Check gpio pin number and use binary search in mtk_hw_pin_field_lookup()
From: Light Hsieh @ 2019-12-31 13:41 UTC (permalink / raw)
To: linus.walleij
Cc: linux-mediatek, linux-gpio, linux-kernel, sean.wang, kuohong.wang,
Light Hsieh
1. Check if gpio pin number is in valid range to prevent from get invalid
pointer 'desc' in the following code:
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
2. Improve mtk_hw_pin_field_lookup()
2.1 Modify mtk_hw_pin_field_lookup() to use binary search for accelerating
search.
2.2 Correct message after the following check fail:
if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) {
rc = &hw->soc->reg_cal[field];
The original message is:
"Not support field %d for pin %d (%s)\n"
However, the check is on soc chip level, not on pin level yet.
So the message is corrected as:
"Not support field %d for this soc\n"
Change-Id: I498a18df73e6a693e0e35635d5b92b8dc9c063ac
---
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 27 ++++++++++++++++++------
drivers/pinctrl/mediatek/pinctrl-paris.c | 25 ++++++++++++++++++++++
2 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
index 20e1c89..d63e05e 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
@@ -68,32 +68,44 @@ static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw,
{
const struct mtk_pin_field_calc *c, *e;
const struct mtk_pin_reg_calc *rc;
+ int start = 0, end, check;
+ bool found = false;
u32 bits;
if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) {
rc = &hw->soc->reg_cal[field];
} else {
dev_dbg(hw->dev,
- "Not support field %d for pin %d (%s)\n",
- field, desc->number, desc->name);
+ "Not support field %d for this soc\n", field);
return -ENOTSUPP;
}
+ end = rc->nranges - 1;
c = rc->range;
e = c + rc->nranges;
- while (c < e) {
- if (desc->number >= c->s_pin && desc->number <= c->e_pin)
+ while (start <= end) {
+ check = (start + end) >> 1;
+ if (desc->number >= rc->range[check].s_pin
+ && desc->number <= rc->range[check].e_pin) {
+ found = true;
+ break;
+ } else if (start == end)
break;
- c++;
+ else if (desc->number < rc->range[check].s_pin)
+ end = check - 1;
+ else
+ start = check + 1;
}
- if (c >= e) {
+ if (!found) {
dev_dbg(hw->dev, "Not support field %d for pin = %d (%s)\n",
field, desc->number, desc->name);
return -ENOTSUPP;
}
+ c = rc->range + check;
+
if (c->i_base > hw->nbase - 1) {
dev_err(hw->dev,
"Invalid base for field %d for pin = %d (%s)\n",
@@ -182,6 +194,9 @@ int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
if (err)
return err;
+ if (value < 0 || value > pf.mask)
+ return -EINVAL;
+
if (!pf.next)
mtk_rmw(hw, pf.index, pf.offset, pf.mask << pf.bitpos,
(value & pf.mask) << pf.bitpos);
diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c
index 923264d..3e13ae7 100644
--- a/drivers/pinctrl/mediatek/pinctrl-paris.c
+++ b/drivers/pinctrl/mediatek/pinctrl-paris.c
@@ -81,6 +81,8 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
int val, val2, err, reg, ret = 1;
const struct mtk_pin_desc *desc;
+ if (pin >= hw->soc->npins)
+ return -EINVAL;
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
switch (param) {
@@ -206,6 +208,10 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
int err = 0;
u32 reg;
+ if (pin >= hw->soc->npins) {
+ err = -EINVAL;
+ goto err;
+ }
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
switch ((u32)param) {
@@ -693,6 +699,9 @@ static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio)
const struct mtk_pin_desc *desc;
int value, err;
+ if (gpio > hw->soc->npins)
+ return -EINVAL;
+
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &value);
@@ -708,6 +717,9 @@ static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio)
const struct mtk_pin_desc *desc;
int value, err;
+ if (gpio > hw->soc->npins)
+ return -EINVAL;
+
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value);
@@ -722,6 +734,9 @@ static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)
struct mtk_pinctrl *hw = gpiochip_get_data(chip);
const struct mtk_pin_desc *desc;
+ if (gpio > hw->soc->npins)
+ return;
+
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value);
@@ -729,12 +744,22 @@ static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)
static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
{
+ struct mtk_pinctrl *hw = gpiochip_get_data(chip);
+
+ if (gpio > hw->soc->npins)
+ return -EINVAL;
+
return pinctrl_gpio_direction_input(chip->base + gpio);
}
static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
int value)
{
+ struct mtk_pinctrl *hw = gpiochip_get_data(chip);
+
+ if (gpio > hw->soc->npins)
+ return -EINVAL;
+
mtk_gpio_set(chip, gpio, value);
return pinctrl_gpio_direction_output(chip->base + gpio);
--
1.8.1.1.dirty
^ permalink raw reply related
* [PATCH v7 5/6] Backward compatible to previous Mediatek's bias-pull usage
From: Light Hsieh @ 2019-12-31 13:41 UTC (permalink / raw)
To: linus.walleij
Cc: linux-mediatek, linux-gpio, linux-kernel, sean.wang, kuohong.wang,
Light Hsieh
In-Reply-To: <1577799707-11855-1-git-send-email-light.hsieh@mediatek.com>
Refine mtk_pinconf_set()/mtk_pinconf_get() for backward compatibility to
previous MediaTek's bias-pull usage.
In PINCTRL_MTK that use pinctrl-mtk-common.c, bias-pull setting for pins
with 2 pull resistors can be specified as value for bias-pull-up and
bias-pull-down. For example:
bias-pull-up = <MTK_PUPD_SET_R1R0_00>;
bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
bias-pull-up = <MTK_PUPD_SET_R1R0_11>;
bias-pull-down = <MTK_PUPD_SET_R1R0_00>;
bias-pull-down = <MTK_PUPD_SET_R1R0_01>;
bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
bias-pull-down = <MTK_PUPD_SET_R1R0_11>;
On the other hand, PINCTRL_MTK_PARIS use customized properties
"mediatek,pull-up-adv" and "mediatek,pull-down-adv" to specify bias-pull
setting for pins with 2 pull resistors.
This introduce in-compatibility in device tree and increase porting
effort to MediaTek's customer that had already used PINCTRL_MTK version.
Besides, if customers are not aware of this change and still write devicetree
for PINCTRL_MTK version, they may encounter runtime failure with pinctrl and
spent time to debug.
This patch adds backward compatible to previous MediaTek's bias-pull usage
so that Mediatek's customer need not use a new devicetree property name.
The rationale is that: changing driver implementation had better leave
interface unchanged.
Change-Id: I8f57c95e3baefcaabdcba4bbfb0dc69d2a825c34
---
drivers/pinctrl/mediatek/pinctrl-mt6765.c | 6 +-
drivers/pinctrl/mediatek/pinctrl-mt8183.c | 6 +-
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 241 +++++++++++++++++++++++
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h | 11 ++
drivers/pinctrl/mediatek/pinctrl-paris.c | 49 +++--
5 files changed, 285 insertions(+), 28 deletions(-)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6765.c b/drivers/pinctrl/mediatek/pinctrl-mt6765.c
index 7fae397..905dae8c 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt6765.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt6765.c
@@ -1072,10 +1072,8 @@
.gpio_m = 0,
.base_names = mt6765_pinctrl_register_base_names,
.nbase_names = ARRAY_SIZE(mt6765_pinctrl_register_base_names),
- .bias_disable_set = mtk_pinconf_bias_disable_set,
- .bias_disable_get = mtk_pinconf_bias_disable_get,
- .bias_set = mtk_pinconf_bias_set,
- .bias_get = mtk_pinconf_bias_get,
+ .bias_set_combo = mtk_pinconf_bias_set_combo,
+ .bias_get_combo = mtk_pinconf_bias_get_combo,
.drive_set = mtk_pinconf_drive_set_raw,
.drive_get = mtk_pinconf_drive_get_raw,
.adv_pull_get = mtk_pinconf_adv_pull_get,
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8183.c b/drivers/pinctrl/mediatek/pinctrl-mt8183.c
index 4eca818..6031833 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8183.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8183.c
@@ -556,10 +556,8 @@
.gpio_m = 0,
.base_names = mt8183_pinctrl_register_base_names,
.nbase_names = ARRAY_SIZE(mt8183_pinctrl_register_base_names),
- .bias_disable_set = mtk_pinconf_bias_disable_set_rev1,
- .bias_disable_get = mtk_pinconf_bias_disable_get_rev1,
- .bias_set = mtk_pinconf_bias_set_rev1,
- .bias_get = mtk_pinconf_bias_get_rev1,
+ .bias_set_combo = mtk_pinconf_bias_set_combo,
+ .bias_get_combo = mtk_pinconf_bias_get_combo,
.drive_set = mtk_pinconf_drive_set_rev1,
.drive_get = mtk_pinconf_drive_get_rev1,
.adv_pull_get = mtk_pinconf_adv_pull_get,
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
index 2247eae..191b1c4 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
@@ -6,6 +6,7 @@
*
*/
+#include <dt-bindings/pinctrl/mt65xx.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
@@ -206,6 +207,20 @@ int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
return 0;
}
+void mtk_hw_set_value_no_lookup(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc,
+ int value, struct mtk_pin_field *pf)
+{
+ if (value < 0 || value > pf->mask)
+ return;
+
+ if (!pf->next)
+ mtk_rmw(hw, pf->index, pf->offset, pf->mask << pf->bitpos,
+ (value & pf->mask) << pf->bitpos);
+ else
+ mtk_hw_write_cross_field(hw, pf, value);
+}
+
int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
int field, int *value)
{
@@ -225,6 +240,17 @@ int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
return 0;
}
+void mtk_hw_get_value_no_lookup(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc,
+ int *value, struct mtk_pin_field *pf)
+{
+ if (!pf->next)
+ *value = (mtk_r32(hw, pf->index, pf->offset)
+ >> pf->bitpos) & pf->mask;
+ else
+ mtk_hw_read_cross_field(hw, pf, value);
+}
+
static int mtk_xt_find_eint_num(struct mtk_pinctrl *hw, unsigned long eint_n)
{
const struct mtk_pin_desc *desc;
@@ -517,6 +543,221 @@ int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw,
return 0;
}
+/* Combo for the following pull register type:
+ * 1. PU + PD
+ * 2. PULLSEL + PULLEN
+ * 3. PUPD + R0 + R1
+ */
+static int mtk_pinconf_bias_set_pu_pd(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc,
+ u32 pullup, u32 arg)
+{
+ int err, pu, pd;
+
+ if (arg == MTK_DISABLE) {
+ pu = 0;
+ pd = 0;
+ } else if ((arg == MTK_ENABLE) && pullup) {
+ pu = 1;
+ pd = 0;
+ } else if ((arg == MTK_ENABLE) && !pullup) {
+ pu = 0;
+ pd = 1;
+ } else {
+ goto out;
+ }
+
+ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU, pu);
+ if (err)
+ goto out;
+
+ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD, pd);
+
+out:
+ return err;
+}
+
+static int mtk_pinconf_bias_set_pullsel_pullen(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc,
+ u32 pullup, u32 arg)
+{
+ int err, enable;
+
+ if (arg == MTK_DISABLE)
+ enable = 0;
+ else if (arg == MTK_ENABLE)
+ enable = 1;
+ else
+ goto out;
+
+ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable);
+ if (err)
+ goto out;
+
+ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup);
+
+out:
+ return err;
+}
+
+static int mtk_pinconf_bias_set_pupd_r1_r0(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc,
+ u32 pullup, u32 arg)
+{
+ int err, r0, r1;
+
+ if ((arg == MTK_DISABLE) || (arg == MTK_PUPD_SET_R1R0_00)) {
+ pullup = 0;
+ r0 = 0;
+ r1 = 0;
+ } else if (arg == MTK_PUPD_SET_R1R0_01) {
+ r0 = 1;
+ r1 = 0;
+ } else if (arg == MTK_PUPD_SET_R1R0_10) {
+ r0 = 0;
+ r1 = 1;
+ } else if (arg == MTK_PUPD_SET_R1R0_11) {
+ r0 = 1;
+ r1 = 1;
+ } else
+ goto out;
+
+ /* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */
+ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PUPD, !pullup);
+ if (err)
+ goto out;
+
+ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R0, r0);
+ if (err)
+ goto out;
+
+ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R1, r1);
+
+out:
+ return err;
+}
+
+static int mtk_pinconf_bias_get_pu_pd(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc,
+ u32 *pullup, u32 *enable)
+{
+ int err, pu, pd;
+
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &pu);
+ if (err)
+ goto out;
+
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &pd);
+ if (err)
+ goto out;
+
+ if (pu == 0 && pd == 0) {
+ *pullup = 0;
+ *enable = MTK_DISABLE;
+ } else if (pu == 1 && pd == 0) {
+ *pullup = 1;
+ *enable = MTK_ENABLE;
+ } else if (pu == 0 && pd == 1) {
+ *pullup = 0;
+ *enable = MTK_ENABLE;
+ } else
+ err = -EINVAL;
+
+out:
+ return err;
+}
+
+static int mtk_pinconf_bias_get_pullsel_pullen(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc,
+ u32 *pullup, u32 *enable)
+{
+ int err;
+
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup);
+ if (err)
+ goto out;
+
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable);
+
+out:
+ return err;
+}
+
+static int mtk_pinconf_bias_get_pupd_r1_r0(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc,
+ u32 *pullup, u32 *enable)
+{
+ int err, r0, r1;
+
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PUPD, pullup);
+ if (err)
+ goto out;
+ /* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */
+ *pullup = !(*pullup);
+
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R0, &r0);
+ if (err)
+ goto out;
+
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R1, &r1);
+ if (err)
+ goto out;
+
+ if ((r1 == 0) && (r0 == 0))
+ *enable = MTK_PUPD_SET_R1R0_00;
+ else if ((r1 == 0) && (r0 == 1))
+ *enable = MTK_PUPD_SET_R1R0_01;
+ else if ((r1 == 1) && (r0 == 0))
+ *enable = MTK_PUPD_SET_R1R0_10;
+ else if ((r1 == 1) && (r0 == 1))
+ *enable = MTK_PUPD_SET_R1R0_11;
+ else
+ err = -EINVAL;
+
+out:
+ return err;
+}
+
+int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc,
+ u32 pullup, u32 arg)
+{
+ int err;
+
+ err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, arg);
+ if (!err)
+ goto out;
+
+ err = mtk_pinconf_bias_set_pullsel_pullen(hw, desc, pullup, arg);
+ if (!err)
+ goto out;
+
+ err = mtk_pinconf_bias_set_pupd_r1_r0(hw, desc, pullup, arg);
+
+out:
+ return err;
+}
+
+int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc,
+ u32 *pullup, u32 *enable)
+{
+ int err;
+
+ err = mtk_pinconf_bias_get_pu_pd(hw, desc, pullup, enable);
+ if (!err)
+ goto out;
+
+ err = mtk_pinconf_bias_get_pullsel_pullen(hw, desc, pullup, enable);
+ if (!err)
+ goto out;
+
+ err = mtk_pinconf_bias_get_pupd_r1_r0(hw, desc, pullup, enable);
+
+out:
+ return err;
+}
+
/* Revision 0 */
int mtk_pinconf_drive_set(struct mtk_pinctrl *hw,
const struct mtk_pin_desc *desc, u32 arg)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
index 75d0e07..27df087 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
@@ -216,6 +216,11 @@ struct mtk_pin_soc {
int (*bias_get)(struct mtk_pinctrl *hw,
const struct mtk_pin_desc *desc, bool pullup, int *res);
+ int (*bias_set_combo)(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc, u32 pullup, u32 arg);
+ int (*bias_get_combo)(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc, u32 *pullup, u32 *arg);
+
int (*drive_set)(struct mtk_pinctrl *hw,
const struct mtk_pin_desc *desc, u32 arg);
int (*drive_get)(struct mtk_pinctrl *hw,
@@ -277,6 +282,12 @@ int mtk_pinconf_bias_set_rev1(struct mtk_pinctrl *hw,
int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw,
const struct mtk_pin_desc *desc, bool pullup,
int *res);
+int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc,
+ u32 pullup, u32 enable);
+int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc,
+ u32 *pullup, u32 *enable);
int mtk_pinconf_drive_set(struct mtk_pinctrl *hw,
const struct mtk_pin_desc *desc, u32 arg);
diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c
index d09a726..115ebc1 100644
--- a/drivers/pinctrl/mediatek/pinctrl-paris.c
+++ b/drivers/pinctrl/mediatek/pinctrl-paris.c
@@ -78,7 +78,7 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
{
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
u32 param = pinconf_to_config_param(*config);
- int err, reg, ret = 1;
+ int pullup, err, reg, ret = 1;
const struct mtk_pin_desc *desc;
if (pin >= hw->soc->npins) {
@@ -89,22 +89,31 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
- if (hw->soc->bias_disable_get)
- err = hw->soc->bias_disable_get(hw, desc, &ret);
- else
- err = -ENOTSUPP;
- break;
case PIN_CONFIG_BIAS_PULL_UP:
- if (hw->soc->bias_get)
- err = hw->soc->bias_get(hw, desc, 1, &ret);
- else
- err = -ENOTSUPP;
- break;
case PIN_CONFIG_BIAS_PULL_DOWN:
- if (hw->soc->bias_get)
- err = hw->soc->bias_get(hw, desc, 0, &ret);
- else
+ if (hw->soc->bias_get_combo) {
+ err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret);
+ if (err)
+ goto out;
+ if (param == PIN_CONFIG_BIAS_DISABLE) {
+ if (ret == MTK_PUPD_SET_R1R0_00)
+ ret = MTK_DISABLE;
+ } else if (param == PIN_CONFIG_BIAS_PULL_UP) {
+ /* When desire to get pull-up value, return
+ * error if current setting is pull-down
+ */
+ if (!pullup)
+ err = -EINVAL;
+ } else if (param == PIN_CONFIG_BIAS_PULL_DOWN) {
+ /* When desire to get pull-down value, return
+ * error if current setting is pull-up
+ */
+ if (pullup)
+ err = -EINVAL;
+ }
+ } else {
err = -ENOTSUPP;
+ }
break;
case PIN_CONFIG_SLEW_RATE:
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &ret);
@@ -196,20 +205,20 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
switch ((u32)param) {
case PIN_CONFIG_BIAS_DISABLE:
- if (hw->soc->bias_disable_set)
- err = hw->soc->bias_disable_set(hw, desc);
+ if (hw->soc->bias_set_combo)
+ err = hw->soc->bias_set_combo(hw, desc, 0, MTK_DISABLE);
else
err = -ENOTSUPP;
break;
case PIN_CONFIG_BIAS_PULL_UP:
- if (hw->soc->bias_set)
- err = hw->soc->bias_set(hw, desc, 1);
+ if (hw->soc->bias_set_combo)
+ err = hw->soc->bias_set_combo(hw, desc, 1, arg);
else
err = -ENOTSUPP;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
- if (hw->soc->bias_set)
- err = hw->soc->bias_set(hw, desc, 0);
+ if (hw->soc->bias_set_combo)
+ err = hw->soc->bias_set_combo(hw, desc, 0, arg);
else
err = -ENOTSUPP;
break;
--
1.8.1.1.dirty
^ permalink raw reply related
* [PATCH v7 3/6] Refine mtk_pinconf_get() and mtk_pinconf_set()
From: Light Hsieh @ 2019-12-31 13:41 UTC (permalink / raw)
To: linus.walleij
Cc: linux-mediatek, linux-gpio, linux-kernel, sean.wang, kuohong.wang,
Light Hsieh
In-Reply-To: <1577799707-11855-1-git-send-email-light.hsieh@mediatek.com>
1.Refine mtk_pinconf_get():
Use only one occurrence of return at end of this function.
2.Refine mtk_pinconf_set():
2.1 Use only one occurrence of return at end of this function.
2.2 Modify case of PIN_CONFIG_INPUT_ENABLE -
2.2.1
Regard all non-zero setting value as enable, instead of always enable.
2.2.2
Remove check of ies_present flag and always invoke mtk_hw_set_value()
since mtk_hw_pin_field_lookup() invoked inside mtk_hw_set_value() has
the same effect of checking if ies control is supported.
[The rationale is that: available of a control is always checked
in mtk_hw_pin_field_lookup() and no need to add ies_present flag
specially for ies control.]
2.3 Simply code logic for case of PIN_CONFIG_INPUT_SCHMITT.
2.4 Add case for PIN_CONFIG_INPUT_SCHMITT_ENABLE and process it with the
same code for case of PIN_CONFIG_INPUT_SCHMITT.
Change-Id: I7adef3550ccbb11aee3ddaf014bbd9f54a9ad089
---
drivers/pinctrl/mediatek/pinctrl-mt6765.c | 1 -
drivers/pinctrl/mediatek/pinctrl-mt8183.c | 1 -
drivers/pinctrl/mediatek/pinctrl-paris.c | 171 ++++++++++++------------------
3 files changed, 65 insertions(+), 108 deletions(-)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6765.c b/drivers/pinctrl/mediatek/pinctrl-mt6765.c
index 1212264..7fae397 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt6765.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt6765.c
@@ -1070,7 +1070,6 @@
.ngrps = ARRAY_SIZE(mtk_pins_mt6765),
.eint_hw = &mt6765_eint_hw,
.gpio_m = 0,
- .ies_present = true,
.base_names = mt6765_pinctrl_register_base_names,
.nbase_names = ARRAY_SIZE(mt6765_pinctrl_register_base_names),
.bias_disable_set = mtk_pinconf_bias_disable_set,
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8183.c b/drivers/pinctrl/mediatek/pinctrl-mt8183.c
index 9a74d50..4eca818 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8183.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8183.c
@@ -554,7 +554,6 @@
.ngrps = ARRAY_SIZE(mtk_pins_mt8183),
.eint_hw = &mt8183_eint_hw,
.gpio_m = 0,
- .ies_present = true,
.base_names = mt8183_pinctrl_register_base_names,
.nbase_names = ARRAY_SIZE(mt8183_pinctrl_register_base_names),
.bias_disable_set = mtk_pinconf_bias_disable_set_rev1,
diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c
index 3e13ae7..2f07500 100644
--- a/drivers/pinctrl/mediatek/pinctrl-paris.c
+++ b/drivers/pinctrl/mediatek/pinctrl-paris.c
@@ -81,37 +81,30 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
int val, val2, err, reg, ret = 1;
const struct mtk_pin_desc *desc;
- if (pin >= hw->soc->npins)
- return -EINVAL;
+ if (pin >= hw->soc->npins) {
+ err = -EINVAL;
+ goto out;
+ }
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
- if (hw->soc->bias_disable_get) {
+ if (hw->soc->bias_disable_get)
err = hw->soc->bias_disable_get(hw, desc, &ret);
- if (err)
- return err;
- } else {
- return -ENOTSUPP;
- }
+ else
+ err = -ENOTSUPP;
break;
case PIN_CONFIG_BIAS_PULL_UP:
- if (hw->soc->bias_get) {
+ if (hw->soc->bias_get)
err = hw->soc->bias_get(hw, desc, 1, &ret);
- if (err)
- return err;
- } else {
- return -ENOTSUPP;
- }
+ else
+ err = -ENOTSUPP;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
- if (hw->soc->bias_get) {
+ if (hw->soc->bias_get)
err = hw->soc->bias_get(hw, desc, 0, &ret);
- if (err)
- return err;
- } else {
- return -ENOTSUPP;
- }
+ else
+ err = -ENOTSUPP;
break;
case PIN_CONFIG_SLEW_RATE:
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val);
@@ -126,12 +119,16 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
case PIN_CONFIG_OUTPUT_ENABLE:
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
if (err)
- return err;
-
- /* HW takes input mode as zero; output mode as non-zero */
- if ((val && param == PIN_CONFIG_INPUT_ENABLE) ||
- (!val && param == PIN_CONFIG_OUTPUT_ENABLE))
- return -EINVAL;
+ goto out;
+ /* CONFIG Current direction return value
+ * ------------- ----------------- ----------------------
+ * OUTPUT_ENABLE output 1 (= HW value)
+ * input 0 (= HW value)
+ * INPUT_ENABLE output 0 (= reverse HW value)
+ * input 1 (= reverse HW value)
+ */
+ if (param == PIN_CONFIG_INPUT_ENABLE)
+ val = !val;
break;
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
@@ -148,13 +145,10 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
break;
case PIN_CONFIG_DRIVE_STRENGTH:
- if (hw->soc->drive_get) {
+ if (hw->soc->drive_get)
err = hw->soc->drive_get(hw, desc, &ret);
- if (err)
- return err;
- } else {
+ else
err = -ENOTSUPP;
- }
break;
case MTK_PIN_CONFIG_TDSEL:
case MTK_PIN_CONFIG_RDSEL:
@@ -175,28 +169,24 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
pullup = param == MTK_PIN_CONFIG_PU_ADV;
err = hw->soc->adv_pull_get(hw, desc, pullup, &ret);
- if (err)
- return err;
- } else {
- return -ENOTSUPP;
- }
+ } else
+ err = -ENOTSUPP;
break;
case MTK_PIN_CONFIG_DRV_ADV:
- if (hw->soc->adv_drive_get) {
+ if (hw->soc->adv_drive_get)
err = hw->soc->adv_drive_get(hw, desc, &ret);
- if (err)
- return err;
- } else {
- return -ENOTSUPP;
- }
+ else
+ err = -ENOTSUPP;
break;
default:
- return -ENOTSUPP;
+ err = -ENOTSUPP;
}
- *config = pinconf_to_config_packed(param, ret);
+out:
+ if (!err)
+ *config = pinconf_to_config_packed(param, ret);
- return 0;
+ return err;
}
static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
@@ -216,60 +206,47 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
switch ((u32)param) {
case PIN_CONFIG_BIAS_DISABLE:
- if (hw->soc->bias_disable_set) {
+ if (hw->soc->bias_disable_set)
err = hw->soc->bias_disable_set(hw, desc);
- if (err)
- return err;
- } else {
- return -ENOTSUPP;
- }
+ else
+ err = -ENOTSUPP;
break;
case PIN_CONFIG_BIAS_PULL_UP:
- if (hw->soc->bias_set) {
+ if (hw->soc->bias_set)
err = hw->soc->bias_set(hw, desc, 1);
- if (err)
- return err;
- } else {
- return -ENOTSUPP;
- }
+ else
+ err = -ENOTSUPP;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
- if (hw->soc->bias_set) {
+ if (hw->soc->bias_set)
err = hw->soc->bias_set(hw, desc, 0);
- if (err)
- return err;
- } else {
- return -ENOTSUPP;
- }
+ else
+ err = -ENOTSUPP;
break;
case PIN_CONFIG_OUTPUT_ENABLE:
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
MTK_DISABLE);
- if (err)
+ /* Keep set direction to consider the case that a GPIO pin
+ * does not have SMT control
+ */
+ if (err != -ENOTSUPP)
goto err;
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
MTK_OUTPUT);
- if (err)
- goto err;
break;
case PIN_CONFIG_INPUT_ENABLE:
- if (hw->soc->ies_present) {
- mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES,
- MTK_ENABLE);
- }
+ /* regard all non-zero value as enable */
+ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, !!arg);
+ if (err)
+ goto err;
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
MTK_INPUT);
- if (err)
- goto err;
break;
case PIN_CONFIG_SLEW_RATE:
- err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR,
- arg);
- if (err)
- goto err;
-
+ /* regard all non-zero value as enable */
+ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR, !!arg);
break;
case PIN_CONFIG_OUTPUT:
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
@@ -279,41 +256,29 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO,
arg);
- if (err)
- goto err;
break;
+ case PIN_CONFIG_INPUT_SCHMITT:
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
/* arg = 1: Input mode & SMT enable ;
* arg = 0: Output mode & SMT disable
*/
- arg = arg ? 2 : 1;
- err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
- arg & 1);
+ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !arg);
if (err)
goto err;
- err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
- !!(arg & 2));
- if (err)
- goto err;
+ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, !!arg);
break;
case PIN_CONFIG_DRIVE_STRENGTH:
- if (hw->soc->drive_set) {
+ if (hw->soc->drive_set)
err = hw->soc->drive_set(hw, desc, arg);
- if (err)
- return err;
- } else {
- return -ENOTSUPP;
- }
+ else
+ err = -ENOTSUPP;
break;
case MTK_PIN_CONFIG_TDSEL:
case MTK_PIN_CONFIG_RDSEL:
reg = (param == MTK_PIN_CONFIG_TDSEL) ?
PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
-
err = mtk_hw_set_value(hw, desc, reg, arg);
- if (err)
- goto err;
break;
case MTK_PIN_CONFIG_PU_ADV:
case MTK_PIN_CONFIG_PD_ADV:
@@ -323,20 +288,14 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
pullup = param == MTK_PIN_CONFIG_PU_ADV;
err = hw->soc->adv_pull_set(hw, desc, pullup,
arg);
- if (err)
- return err;
- } else {
- return -ENOTSUPP;
- }
+ } else
+ err = -ENOTSUPP;
break;
case MTK_PIN_CONFIG_DRV_ADV:
- if (hw->soc->adv_drive_set) {
+ if (hw->soc->adv_drive_set)
err = hw->soc->adv_drive_set(hw, desc, arg);
- if (err)
- return err;
- } else {
- return -ENOTSUPP;
- }
+ else
+ err = -ENOTSUPP;
break;
default:
err = -ENOTSUPP;
--
1.8.1.1.dirty
^ permalink raw reply related
* [PATCH v7 2/6] Supporting driving setting without mapping current to register value
From: Light Hsieh @ 2019-12-31 13:41 UTC (permalink / raw)
To: linus.walleij
Cc: linux-mediatek, linux-gpio, linux-kernel, sean.wang, kuohong.wang,
Light Hsieh
In-Reply-To: <1577799707-11855-1-git-send-email-light.hsieh@mediatek.com>
MediaTek's smarphone project actual usage does need to know current value
(in mA) in procedure of finding the best driving setting.
The steps in the procedure is like as follow:
1. set driving setting field in setting register as 0, measure waveform,
perform test, and etc.
2. set driving setting field in setting register as 1, measure waveform,
perform test, and etc.
...
n. set driving setting field in setting register as n-1, measure
waveform, perform test, and etc.
Check the results of steps 1~n and adopt the setting that get best result.
This procedure does need to know the mapping between current to register
value.
Therefore, setting driving without mapping current is more practical for
MediaTek's smartphone usage.
Change-Id: I8bd6a2cecc0af650923704589b5b90097b0ff77e
---
drivers/pinctrl/mediatek/pinctrl-mt6765.c | 4 ++--
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c | 12 ++++++++++++
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h | 5 +++++
3 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6765.c b/drivers/pinctrl/mediatek/pinctrl-mt6765.c
index 32451e8..1212264 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt6765.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt6765.c
@@ -1077,8 +1077,8 @@
.bias_disable_get = mtk_pinconf_bias_disable_get,
.bias_set = mtk_pinconf_bias_set,
.bias_get = mtk_pinconf_bias_get,
- .drive_set = mtk_pinconf_drive_set_rev1,
- .drive_get = mtk_pinconf_drive_get_rev1,
+ .drive_set = mtk_pinconf_drive_set_raw,
+ .drive_get = mtk_pinconf_drive_get_raw,
.adv_pull_get = mtk_pinconf_adv_pull_get,
.adv_pull_set = mtk_pinconf_adv_pull_set,
};
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
index d63e05e..2247eae 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
@@ -608,6 +608,18 @@ int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw,
return 0;
}
+int mtk_pinconf_drive_set_raw(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc, u32 arg)
+{
+ return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV, arg);
+}
+
+int mtk_pinconf_drive_get_raw(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc, int *val)
+{
+ return mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV, val);
+}
+
int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw,
const struct mtk_pin_desc *desc, bool pullup,
u32 arg)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
index 1b7da42..75d0e07 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
@@ -288,6 +288,11 @@ int mtk_pinconf_drive_set_rev1(struct mtk_pinctrl *hw,
int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw,
const struct mtk_pin_desc *desc, int *val);
+int mtk_pinconf_drive_set_raw(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc, u32 arg);
+int mtk_pinconf_drive_get_raw(struct mtk_pinctrl *hw,
+ const struct mtk_pin_desc *desc, int *val);
+
int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw,
const struct mtk_pin_desc *desc, bool pullup,
u32 arg);
--
1.8.1.1.dirty
^ permalink raw reply related
* [PATCH v7 4/6] Refine mtk_pinconf_get()
From: Light Hsieh @ 2019-12-31 13:41 UTC (permalink / raw)
To: linus.walleij
Cc: linux-mediatek, linux-gpio, linux-kernel, sean.wang, kuohong.wang,
Light Hsieh
In-Reply-To: <1577799707-11855-1-git-send-email-light.hsieh@mediatek.com>
Correct cases for PIN_CONFIG_SLEW_RATE, PIN_CONFIG_INPUT_SCHMITT_ENABLE,
and PIN_CONFIG_OUTPUT_ENABLE -
Use variable ret to receive value in mtk_hw_get_value() (instead of
variable val) since pinconf_to_config_packed() at end of this function
use variable ret to pack config value.
Change-Id: Icdeecee8f614346a9b53764d20122b2b4940b381
---
drivers/pinctrl/mediatek/pinctrl-paris.c | 40 ++++++++++++--------------------
1 file changed, 15 insertions(+), 25 deletions(-)
diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c
index 2f07500..d09a726 100644
--- a/drivers/pinctrl/mediatek/pinctrl-paris.c
+++ b/drivers/pinctrl/mediatek/pinctrl-paris.c
@@ -78,7 +78,7 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
{
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
u32 param = pinconf_to_config_param(*config);
- int val, val2, err, reg, ret = 1;
+ int err, reg, ret = 1;
const struct mtk_pin_desc *desc;
if (pin >= hw->soc->npins) {
@@ -107,17 +107,11 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
err = -ENOTSUPP;
break;
case PIN_CONFIG_SLEW_RATE:
- err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val);
- if (err)
- return err;
-
- if (!val)
- return -EINVAL;
-
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &ret);
break;
case PIN_CONFIG_INPUT_ENABLE:
case PIN_CONFIG_OUTPUT_ENABLE:
- err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
if (err)
goto out;
/* CONFIG Current direction return value
@@ -128,20 +122,22 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
* input 1 (= reverse HW value)
*/
if (param == PIN_CONFIG_INPUT_ENABLE)
- val = !val;
+ ret = !ret;
break;
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
- err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
if (err)
- return err;
-
- err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &val2);
- if (err)
- return err;
+ goto out;
+ /* return error when in output mode
+ * because schmitt trigger only work in input mode
+ */
+ if (ret) {
+ err = -EINVAL;
+ goto out;
+ }
- if (val || !val2)
- return -EINVAL;
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &ret);
break;
case PIN_CONFIG_DRIVE_STRENGTH:
@@ -154,13 +150,7 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
case MTK_PIN_CONFIG_RDSEL:
reg = (param == MTK_PIN_CONFIG_TDSEL) ?
PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
-
- err = mtk_hw_get_value(hw, desc, reg, &val);
- if (err)
- return err;
-
- ret = val;
-
+ err = mtk_hw_get_value(hw, desc, reg, &ret);
break;
case MTK_PIN_CONFIG_PU_ADV:
case MTK_PIN_CONFIG_PD_ADV:
--
1.8.1.1.dirty
^ permalink raw reply related
* Re: [PATCH] dt-bindings: pinctrl: Convert generic pin mux and config properties to schema
From: Rob Herring @ 2019-12-30 23:19 UTC (permalink / raw)
To: Linus Walleij
Cc: devicetree, linux-kernel@vger.kernel.org, Maxime Ripard,
open list:GPIO SUBSYSTEM
In-Reply-To: <20191107224254.15712-1-robh@kernel.org>
On Thu, Nov 7, 2019 at 3:42 PM Rob Herring <robh@kernel.org> wrote:
>
> As pinctrl bindings have a flexible structure and no standard child node
> naming convention, creating a single pinctrl schema doesn't work. Instead,
> create schemas for the pin mux and config nodes which device pinctrl schema
> can reference.
>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: linux-gpio@vger.kernel.org
> Signed-off-by: Rob Herring <robh@kernel.org>
> ---
>
> We're starting to see pinctrl schema doing their own definitions for
> generic properties, so we need to get something in place to reference.
>
> Maybe this could be combined into a single schema? Spliting it was
> easier in order to just copy over the existing documentation.
>
> Reading thru pinctrl-bindings.txt, I'm wondering if some of it is out
> of date. Do we let new bindings not use the generic muxing properties?
> Do we really need to be so flexible for child node structure?
Ping!
>
> Rob
>
> .../bindings/pinctrl/pincfg-node.yaml | 140 +++++++++++++
> .../bindings/pinctrl/pinctrl-bindings.txt | 192 +-----------------
> .../bindings/pinctrl/pinmux-node.yaml | 132 ++++++++++++
> 3 files changed, 274 insertions(+), 190 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml
> create mode 100644 Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml
>
> diff --git a/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml b/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml
> new file mode 100644
> index 000000000000..13b7ab9dd6d5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml
> @@ -0,0 +1,140 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pinctrl/pincfg-node.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Generic pin configuration node schema
> +
> +maintainers:
> + - Linus Walleij <linus.walleij@linaro.org>
> +
> +description:
> + Many data items that are represented in a pin configuration node are common
> + and generic. Pin control bindings should use the properties defined below
> + where they are applicable; not all of these properties are relevant or useful
> + for all hardware or binding structures. Each individual binding document
> + should state which of these generic properties, if any, are used, and the
> + structure of the DT nodes that contain these properties.
> +
> +properties:
> + bias-disable:
> + type: boolean
> + description: disable any pin bias
> +
> + bias-high-impedance:
> + type: boolean
> + description: high impedance mode ("third-state", "floating")
> +
> + bias-bus-hold:
> + type: boolean
> + description: latch weakly
> +
> + bias-pull-up:
> + oneOf:
> + - type: boolean
> + - $ref: /schemas/types.yaml#/definitions/uint32
> + description: pull up the pin. Takes as optional argument on hardware
> + supporting it the pull strength in Ohm.
> +
> + bias-pull-down:
> + oneOf:
> + - type: boolean
> + - $ref: /schemas/types.yaml#/definitions/uint32
> + description: pull down the pin. Takes as optional argument on hardware
> + supporting it the pull strength in Ohm.
> +
> + bias-pull-pin-default:
> + oneOf:
> + - type: boolean
> + - $ref: /schemas/types.yaml#/definitions/uint32
> + description: use pin-default pull state. Takes as optional argument on
> + hardware supporting it the pull strength in Ohm.
> +
> + drive-push-pull:
> + type: boolean
> + description: drive actively high and low
> +
> + drive-open-drain:
> + type: boolean
> + description: drive with open drain
> +
> + drive-open-source:
> + type: boolean
> + description: drive with open source
> +
> + drive-strength:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + description: sink or source at most X mA
> +
> + drive-strength-microamp:
> + description: sink or source at most X uA
> +
> + input-enable:
> + type: boolean
> + description: enable input on pin (no effect on output, such as
> + enabling an input buffer)
> +
> + input-disable:
> + type: boolean
> + description: disable input on pin (no effect on output, such as
> + disabling an input buffer)
> +
> + input-schmitt-enable:
> + type: boolean
> + description: enable schmitt-trigger mode
> +
> + input-schmitt-disable:
> + type: boolean
> + description: disable schmitt-trigger mode
> +
> + input-debounce:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + description: Takes the debounce time in usec as argument or 0 to disable
> + debouncing
> +
> + power-source:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + description: select between different power supplies
> +
> + low-power-enable:
> + type: boolean
> + description: enable low power mode
> +
> + low-power-disable:
> + type: boolean
> + description: disable low power mode
> +
> + output-disable:
> + type: boolean
> + description: disable output on a pin (such as disable an output buffer)
> +
> + output-enable:
> + type: boolean
> + description: enable output on a pin without actively driving it
> + (such as enabling an output buffer)
> +
> + output-low:
> + type: boolean
> + description: set the pin to output mode with low level
> +
> + output-high:
> + type: boolean
> + description: set the pin to output mode with high level
> +
> + sleep-hardware-state:
> + type: boolean
> + description: indicate this is sleep related state which will be
> + programmed into the registers for the sleep state.
> +
> + slew-rate:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + description: set the slew rate
> +
> + skew-delay:
> + $ref: /schemas/types.yaml#/definitions/uint32
> + description:
> + this affects the expected clock skew on input pins
> + and the delay before latching a value to an output
> + pin. Typically indicates how many double-inverters are
> + used to delay the signal.
> diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
> index fcd37e93ed4d..4613bb17ace3 100644
> --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
> +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
> @@ -141,196 +141,8 @@ controller device.
>
> == Generic pin multiplexing node content ==
>
> -pin multiplexing nodes:
> -
> -function - the mux function to select
> -groups - the list of groups to select with this function
> - (either this or "pins" must be specified)
> -pins - the list of pins to select with this function (either
> - this or "groups" must be specified)
> -
> -Example:
> -
> -state_0_node_a {
> - uart0 {
> - function = "uart0";
> - groups = "u0rxtx", "u0rtscts";
> - };
> -};
> -state_1_node_a {
> - spi0 {
> - function = "spi0";
> - groups = "spi0pins";
> - };
> -};
> -state_2_node_a {
> - function = "i2c0";
> - pins = "mfio29", "mfio30";
> -};
> -
> -Optionally an alternative binding can be used if more suitable depending on the
> -pin controller hardware. For hardware where there is a large number of identical
> -pin controller instances, naming each pin and function can easily become
> -unmaintainable. This is especially the case if the same controller is used for
> -different pins and functions depending on the SoC revision and packaging.
> -
> -For cases like this, the pin controller driver may use pinctrl-pin-array helper
> -binding with a hardware based index and a number of pin configuration values:
> -
> -pincontroller {
> - ... /* Standard DT properties for the device itself elided */
> - #pinctrl-cells = <2>;
> -
> - state_0_node_a {
> - pinctrl-pin-array = <
> - 0 A_DELAY_PS(0) G_DELAY_PS(120)
> - 4 A_DELAY_PS(0) G_DELAY_PS(360)
> - ...
> - >;
> - };
> - ...
> -};
> -
> -Above #pinctrl-cells specifies the number of value cells in addition to the
> -index of the registers. This is similar to the interrupts-extended binding with
> -one exception. There is no need to specify the phandle for each entry as that
> -is already known as the defined pins are always children of the pin controller
> -node. Further having the phandle pointing to another pin controller would not
> -currently work as the pinctrl framework uses named modes to group pins for each
> -pin control device.
> -
> -The index for pinctrl-pin-array must relate to the hardware for the pinctrl
> -registers, and must not be a virtual index of pin instances. The reason for
> -this is to avoid mapping of the index in the dts files and the pin controller
> -driver as it can change.
> -
> -For hardware where pin multiplexing configurations have to be specified for
> -each single pin the number of required sub-nodes containing "pin" and
> -"function" properties can quickly escalate and become hard to write and
> -maintain.
> -
> -For cases like this, the pin controller driver may use the pinmux helper
> -property, where the pin identifier is provided with mux configuration settings
> -in a pinmux group. A pinmux group consists of the pin identifier and mux
> -settings represented as a single integer or an array of integers.
> -
> -The pinmux property accepts an array of pinmux groups, each of them describing
> -a single pin multiplexing configuration.
> -
> -pincontroller {
> - state_0_node_a {
> - pinmux = <PINMUX_GROUP>, <PINMUX_GROUP>, ...;
> - };
> -};
> -
> -Each individual pin controller driver bindings documentation shall specify
> -how pin IDs and pin multiplexing configuration are defined and assembled
> -together in a pinmux group.
> +See pinmux-node.yaml
>
> == Generic pin configuration node content ==
>
> -Many data items that are represented in a pin configuration node are common
> -and generic. Pin control bindings should use the properties defined below
> -where they are applicable; not all of these properties are relevant or useful
> -for all hardware or binding structures. Each individual binding document
> -should state which of these generic properties, if any, are used, and the
> -structure of the DT nodes that contain these properties.
> -
> -Supported generic properties are:
> -
> -pins - the list of pins that properties in the node
> - apply to (either this, "group" or "pinmux" has to be
> - specified)
> -group - the group to apply the properties to, if the driver
> - supports configuration of whole groups rather than
> - individual pins (either this, "pins" or "pinmux" has
> - to be specified)
> -pinmux - the list of numeric pin ids and their mux settings
> - that properties in the node apply to (either this,
> - "pins" or "groups" have to be specified)
> -bias-disable - disable any pin bias
> -bias-high-impedance - high impedance mode ("third-state", "floating")
> -bias-bus-hold - latch weakly
> -bias-pull-up - pull up the pin
> -bias-pull-down - pull down the pin
> -bias-pull-pin-default - use pin-default pull state
> -drive-push-pull - drive actively high and low
> -drive-open-drain - drive with open drain
> -drive-open-source - drive with open source
> -drive-strength - sink or source at most X mA
> -drive-strength-microamp - sink or source at most X uA
> -input-enable - enable input on pin (no effect on output, such as
> - enabling an input buffer)
> -input-disable - disable input on pin (no effect on output, such as
> - disabling an input buffer)
> -input-schmitt-enable - enable schmitt-trigger mode
> -input-schmitt-disable - disable schmitt-trigger mode
> -input-debounce - debounce mode with debound time X
> -power-source - select between different power supplies
> -low-power-enable - enable low power mode
> -low-power-disable - disable low power mode
> -output-disable - disable output on a pin (such as disable an output
> - buffer)
> -output-enable - enable output on a pin without actively driving it
> - (such as enabling an output buffer)
> -output-low - set the pin to output mode with low level
> -output-high - set the pin to output mode with high level
> -sleep-hardware-state - indicate this is sleep related state which will be programmed
> - into the registers for the sleep state.
> -slew-rate - set the slew rate
> -skew-delay - this affects the expected clock skew on input pins
> - and the delay before latching a value to an output
> - pin. Typically indicates how many double-inverters are
> - used to delay the signal.
> -
> -For example:
> -
> -state_0_node_a {
> - cts_rxd {
> - pins = "GPIO0_AJ5", "GPIO2_AH4"; /* CTS+RXD */
> - bias-pull-up;
> - };
> -};
> -state_1_node_a {
> - rts_txd {
> - pins = "GPIO1_AJ3", "GPIO3_AH3"; /* RTS+TXD */
> - output-high;
> - };
> -};
> -state_2_node_a {
> - foo {
> - group = "foo-group";
> - bias-pull-up;
> - };
> -};
> -state_3_node_a {
> - mux {
> - pinmux = <GPIOx_PINm_MUXn>, <GPIOx_PINj_MUXk)>;
> - input-enable;
> - };
> -};
> -
> -Some of the generic properties take arguments. For those that do, the
> -arguments are described below.
> -
> -- pins takes a list of pin names or IDs as a required argument. The specific
> - binding for the hardware defines:
> - - Whether the entries are integers or strings, and their meaning.
> -
> -- pinmux takes a list of pin IDs and mux settings as required argument. The
> - specific bindings for the hardware defines:
> - - How pin IDs and mux settings are defined and assembled together in a single
> - integer or an array of integers.
> -
> -- bias-pull-up, -down and -pin-default take as optional argument on hardware
> - supporting it the pull strength in Ohm. bias-disable will disable the pull.
> -
> -- drive-strength takes as argument the target strength in mA.
> -
> -- drive-strength-microamp takes as argument the target strength in uA.
> -
> -- input-debounce takes the debounce time in usec as argument
> - or 0 to disable debouncing
> -
> -More in-depth documentation on these parameters can be found in
> -<include/linux/pinctrl/pinconf-generic.h>
> +See pincfg-node.yaml
> diff --git a/Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml b/Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml
> new file mode 100644
> index 000000000000..777623a57fd5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml
> @@ -0,0 +1,132 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pinctrl/pinmux-node.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Generic pin multiplexing node schema
> +
> +maintainers:
> + - Linus Walleij <linus.walleij@linaro.org>
> +
> +description: |
> + The contents of the pin configuration child nodes are defined by the binding
> + for the individual pin controller device. The pin configuration nodes need not
> + be direct children of the pin controller device; they may be grandchildren,
> + for example. Whether this is legal, and whether there is any interaction
> + between the child and intermediate parent nodes, is again defined entirely by
> + the binding for the individual pin controller device.
> +
> + While not required to be used, there are 3 generic forms of pin muxing nodes
> + which pin controller devices can use.
> +
> + pin multiplexing nodes:
> +
> + Example:
> +
> + state_0_node_a {
> + uart0 {
> + function = "uart0";
> + groups = "u0rxtx", "u0rtscts";
> + };
> + };
> + state_1_node_a {
> + spi0 {
> + function = "spi0";
> + groups = "spi0pins";
> + };
> + };
> + state_2_node_a {
> + function = "i2c0";
> + pins = "mfio29", "mfio30";
> + };
> +
> + Optionally an alternative binding can be used if more suitable depending on the
> + pin controller hardware. For hardware where there is a large number of identical
> + pin controller instances, naming each pin and function can easily become
> + unmaintainable. This is especially the case if the same controller is used for
> + different pins and functions depending on the SoC revision and packaging.
> +
> + For cases like this, the pin controller driver may use pinctrl-pin-array helper
> + binding with a hardware based index and a number of pin configuration values:
> +
> + pincontroller {
> + ... /* Standard DT properties for the device itself elided */
> + #pinctrl-cells = <2>;
> +
> + state_0_node_a {
> + pinctrl-pin-array = <
> + 0 A_DELAY_PS(0) G_DELAY_PS(120)
> + 4 A_DELAY_PS(0) G_DELAY_PS(360)
> + ...
> + >;
> + };
> + ...
> + };
> +
> + Above #pinctrl-cells specifies the number of value cells in addition to the
> + index of the registers. This is similar to the interrupts-extended binding with
> + one exception. There is no need to specify the phandle for each entry as that
> + is already known as the defined pins are always children of the pin controller
> + node. Further having the phandle pointing to another pin controller would not
> + currently work as the pinctrl framework uses named modes to group pins for each
> + pin control device.
> +
> + The index for pinctrl-pin-array must relate to the hardware for the pinctrl
> + registers, and must not be a virtual index of pin instances. The reason for
> + this is to avoid mapping of the index in the dts files and the pin controller
> + driver as it can change.
> +
> + For hardware where pin multiplexing configurations have to be specified for
> + each single pin the number of required sub-nodes containing "pin" and
> + "function" properties can quickly escalate and become hard to write and
> + maintain.
> +
> + For cases like this, the pin controller driver may use the pinmux helper
> + property, where the pin identifier is provided with mux configuration settings
> + in a pinmux group. A pinmux group consists of the pin identifier and mux
> + settings represented as a single integer or an array of integers.
> +
> + The pinmux property accepts an array of pinmux groups, each of them describing
> + a single pin multiplexing configuration.
> +
> + pincontroller {
> + state_0_node_a {
> + pinmux = <PINMUX_GROUP>, <PINMUX_GROUP>, ...;
> + };
> + };
> +
> + Each individual pin controller driver bindings documentation shall specify
> + how pin IDs and pin multiplexing configuration are defined and assembled
> + together in a pinmux group.
> +
> +properties:
> + function:
> + $ref: /schemas/types.yaml#/definitions/string
> + description: The mux function to select
> +
> + pins:
> + oneOf:
> + - $ref: /schemas/types.yaml#/definitions/uint32-array
> + - $ref: /schemas/types.yaml#/definitions/string-array
> + description:
> + The list of pin identifiers that properties in the node apply to. The
> + specific binding for the hardware defines whether the entries are integers
> + or strings, and their meaning.
> +
> + group:
> + $ref: /schemas/types.yaml#/definitions/string-array
> + description:
> + the group to apply the properties to, if the driver supports
> + configuration of whole groups rather than individual pins (either
> + this, "pins" or "pinmux" has to be specified)
> +
> + pinmux:
> + allOf:
> + - $ref: /schemas/types.yaml#/definitions/uint32-array
> + description:
> + The list of numeric pin ids and their mux settings that properties in the
> + node apply to (either this, "pins" or "groups" have to be specified)
> +
> + pinctrl-pin-array:
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> --
> 2.20.1
>
^ permalink raw reply
* [PATCH/RFC 0/2] gpio: of: Add DT overlay support for GPIO hogs
From: Geert Uytterhoeven @ 2019-12-30 13:38 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Pantelis Antoniou,
Frank Rowand, Rob Herring
Cc: Peter Ujfalusi, Chris Brandt, linux-gpio, devicetree,
linux-renesas-soc, linux-kernel, Geert Uytterhoeven
Hi all,
As GPIO hogs are configured at GPIO controller initialization time,
adding/removing GPIO hogs in Device Tree overlays currently does not
work. Hence this patch series adds support for that, by registering an
of_reconfig notifier, as is already done for platform, i2c, and SPI
devices.
Perhaps this would be better served through a pinctrl-gpio driver?
Pinctrl is already working fine with DT overlays, as the pinctrl-*
properties are part of the slave device node, and thus looked up at
slave device node attachment time, not at pin controller initialization
time.
In my particular use case (talking to SPI devices connected to a PMOD
connector on the RSK+RZA1 development board), the GPIO performs board
level muxing of a.o. the SPI MOSI/MISO/SCK signals. Hence the hog
really needs to be active only while talking to the SPI device, so the
muxing could (in theory) be done upon demand.
But how to describe that in DT, and implement it (using Runtime PM?)?
Thanks for your comments!
Geert Uytterhoeven (2):
gpio: of: Extract of_gpiochip_add_hog()
gpio: of: Add DT overlay support for GPIO hogs
drivers/gpio/gpiolib-of.c | 133 +++++++++++++++++++++++++++++++++-----
drivers/gpio/gpiolib-of.h | 2 +
drivers/gpio/gpiolib.c | 14 +++-
drivers/gpio/gpiolib.h | 3 +
4 files changed, 133 insertions(+), 19 deletions(-)
--
2.17.1
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH/RFC 1/2] gpio: of: Extract of_gpiochip_add_hog()
From: Geert Uytterhoeven @ 2019-12-30 13:38 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Pantelis Antoniou,
Frank Rowand, Rob Herring
Cc: Peter Ujfalusi, Chris Brandt, linux-gpio, devicetree,
linux-renesas-soc, linux-kernel, Geert Uytterhoeven
In-Reply-To: <20191230133852.5890-1-geert+renesas@glider.be>
Extract the code to add all GPIO hogs of a gpio-hog node into its own
function, so it can be reused.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/gpio/gpiolib-of.c | 49 ++++++++++++++++++++++++++-------------
1 file changed, 33 insertions(+), 16 deletions(-)
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index b696e4598a240ea4..dfae797846bb746b 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -625,6 +625,35 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np,
return desc;
}
+/**
+ * of_gpiochip_add_hog - Add all hogs in a hog device node
+ * @chip: gpio chip to act on
+ * @hog: device node describing the hogs
+ *
+ * Returns error if it fails otherwise 0 on success.
+ */
+static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog)
+{
+ enum gpiod_flags dflags;
+ struct gpio_desc *desc;
+ unsigned long lflags;
+ const char *name;
+ unsigned int i;
+ int ret;
+
+ for (i = 0;; i++) {
+ desc = of_parse_own_gpio(hog, chip, i, &name, &lflags, &dflags);
+ if (IS_ERR(desc))
+ break;
+
+ ret = gpiod_hog(desc, name, lflags, dflags);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
/**
* of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions
* @chip: gpio chip to act on
@@ -635,29 +664,17 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np,
*/
static int of_gpiochip_scan_gpios(struct gpio_chip *chip)
{
- struct gpio_desc *desc = NULL;
struct device_node *np;
- const char *name;
- unsigned long lflags;
- enum gpiod_flags dflags;
- unsigned int i;
int ret;
for_each_available_child_of_node(chip->of_node, np) {
if (!of_property_read_bool(np, "gpio-hog"))
continue;
- for (i = 0;; i++) {
- desc = of_parse_own_gpio(np, chip, i, &name, &lflags,
- &dflags);
- if (IS_ERR(desc))
- break;
-
- ret = gpiod_hog(desc, name, lflags, dflags);
- if (ret < 0) {
- of_node_put(np);
- return ret;
- }
+ ret = of_gpiochip_add_hog(chip, np);
+ if (ret < 0) {
+ of_node_put(np);
+ return ret;
}
}
--
2.17.1
^ permalink raw reply related
* [PATCH/RFC 2/2] gpio: of: Add DT overlay support for GPIO hogs
From: Geert Uytterhoeven @ 2019-12-30 13:38 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Pantelis Antoniou,
Frank Rowand, Rob Herring
Cc: Peter Ujfalusi, Chris Brandt, linux-gpio, devicetree,
linux-renesas-soc, linux-kernel, Geert Uytterhoeven
In-Reply-To: <20191230133852.5890-1-geert+renesas@glider.be>
As GPIO hogs are configured at GPIO controller initialization time,
adding/removing GPIO hogs in DT overlays does not work.
Add support for GPIO hogs described in DT overlays by registering an OF
reconfiguration notifier, to handle the addition and removal of GPIO hog
subnodes to/from a GPIO controller device node.
Note that when a GPIO hog device node is being removed, its "gpios"
properties is no longer available, so we have to keep track of which
node a hog belongs to, which is done by adding a pointer to the hog's
device node to struct gpio_desc.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/gpio/gpiolib-of.c | 84 +++++++++++++++++++++++++++++++++++++++
drivers/gpio/gpiolib-of.h | 2 +
drivers/gpio/gpiolib.c | 14 +++++--
drivers/gpio/gpiolib.h | 3 ++
4 files changed, 100 insertions(+), 3 deletions(-)
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index dfae797846bb746b..89a6138ac0a4b506 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -649,6 +649,10 @@ static int of_gpiochip_add_hog(struct gpio_chip *chip, struct device_node *hog)
ret = gpiod_hog(desc, name, lflags, dflags);
if (ret < 0)
return ret;
+
+#ifdef CONFIG_OF_DYNAMIC
+ desc->hog = hog;
+#endif
}
return 0;
@@ -676,11 +680,91 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip)
of_node_put(np);
return ret;
}
+
+ of_node_set_flag(np, OF_POPULATED);
}
return 0;
}
+#ifdef CONFIG_OF_DYNAMIC
+/**
+ * of_gpiochip_remove_hog - Remove all hogs in a hog device node
+ * @chip: gpio chip to act on
+ * @hog: device node describing the hogs
+ */
+static void of_gpiochip_remove_hog(struct gpio_chip *chip,
+ struct device_node *hog)
+{
+ struct gpio_desc *descs = chip->gpiodev->descs;
+ unsigned int i;
+
+ for (i = 0; i < chip->ngpio; i++) {
+ if (test_bit(FLAG_IS_HOGGED, &descs[i].flags) &&
+ descs[i].hog == hog)
+ gpiochip_free_own_desc(&descs[i]);
+ }
+}
+
+static int of_gpiochip_match_node(struct gpio_chip *chip, void *data)
+{
+ return chip->gpiodev->dev.of_node == data;
+}
+
+static struct gpio_chip *of_find_gpiochip_by_node(struct device_node *np)
+{
+ return gpiochip_find(np, of_gpiochip_match_node);
+}
+
+static int of_gpio_notify(struct notifier_block *nb, unsigned long action,
+ void *arg)
+{
+ struct of_reconfig_data *rd = arg;
+ struct gpio_chip *chip;
+ int ret;
+
+ switch (of_reconfig_get_state_change(action, arg)) {
+ case OF_RECONFIG_CHANGE_ADD:
+ if (!of_property_read_bool(rd->dn, "gpio-hog"))
+ return NOTIFY_OK; /* not for us */
+
+ if (of_node_test_and_set_flag(rd->dn, OF_POPULATED))
+ return NOTIFY_OK;
+
+ chip = of_find_gpiochip_by_node(rd->dn->parent);
+ if (chip == NULL)
+ return NOTIFY_OK; /* not for us */
+
+ ret = of_gpiochip_add_hog(chip, rd->dn);
+ if (ret < 0) {
+ pr_err("%s: failed to add hogs for %pOF\n", __func__,
+ rd->dn);
+ of_node_clear_flag(rd->dn, OF_POPULATED);
+ return notifier_from_errno(ret);
+ }
+ break;
+
+ case OF_RECONFIG_CHANGE_REMOVE:
+ if (!of_node_check_flag(rd->dn, OF_POPULATED))
+ return NOTIFY_OK; /* already depopulated */
+
+ chip = of_find_gpiochip_by_node(rd->dn->parent);
+ if (chip == NULL)
+ return NOTIFY_OK; /* not for us */
+
+ of_gpiochip_remove_hog(chip, rd->dn);
+ of_node_clear_flag(rd->dn, OF_POPULATED);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+struct notifier_block gpio_of_notifier = {
+ .notifier_call = of_gpio_notify,
+};
+#endif /* CONFIG_OF_DYNAMIC */
+
/**
* of_gpio_simple_xlate - translate gpiospec to the GPIO number and flags
* @gc: pointer to the gpio_chip structure
diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h
index 9768831b1fe2f25b..ed26664f153782fc 100644
--- a/drivers/gpio/gpiolib-of.h
+++ b/drivers/gpio/gpiolib-of.h
@@ -35,4 +35,6 @@ static inline bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
}
#endif /* CONFIG_OF_GPIO */
+extern struct notifier_block gpio_of_notifier;
+
#endif /* GPIOLIB_OF_H */
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index bff5ac774d870b67..ef12cfcaf0962c1c 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2952,6 +2952,9 @@ static bool gpiod_free_commit(struct gpio_desc *desc)
clear_bit(FLAG_PULL_DOWN, &desc->flags);
clear_bit(FLAG_BIAS_DISABLE, &desc->flags);
clear_bit(FLAG_IS_HOGGED, &desc->flags);
+#ifdef CONFIG_OF_DYNAMIC
+ desc->hog = NULL;
+#endif
ret = true;
}
@@ -5145,10 +5148,15 @@ static int __init gpiolib_dev_init(void)
if (ret < 0) {
pr_err("gpiolib: failed to allocate char dev region\n");
bus_unregister(&gpio_bus_type);
- } else {
- gpiolib_initialized = true;
- gpiochip_setup_devs();
+ return ret;
}
+
+ gpiolib_initialized = true;
+ gpiochip_setup_devs();
+
+ if (IS_ENABLED(CONFIG_OF_DYNAMIC))
+ WARN_ON(of_reconfig_notifier_register(&gpio_of_notifier));
+
return ret;
}
core_initcall(gpiolib_dev_init);
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index a4a759920faa48ab..7af9931e8572304a 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -118,6 +118,9 @@ struct gpio_desc {
const char *label;
/* Name of the GPIO */
const char *name;
+#ifdef CONFIG_OF_DYNAMIC
+ struct device_node *hog;
+#endif
};
int gpiod_request(struct gpio_desc *desc, const char *label);
--
2.17.1
^ permalink raw reply related
* Re: [PATCH v2 1/5] pinctrl: Allow modules to use pinctrl_[un]register_mappings
From: Linus Walleij @ 2019-12-30 13:31 UTC (permalink / raw)
To: Hans de Goede
Cc: Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Ville Syrjälä, intel-gfx, Lee Jones, Andy Shevchenko,
open list:DRM PANEL DRIVERS, linux-kernel@vger.kernel.org,
open list:GPIO SUBSYSTEM
In-Reply-To: <20191216205122.1850923-2-hdegoede@redhat.com>
On Mon, Dec 16, 2019 at 9:51 PM Hans de Goede <hdegoede@redhat.com> wrote:
> Currently only the drivers/pinctrl/devicetree.c code allows registering
> pinctrl-mappings which may later be unregistered, all other mappings
> are assumed to be permanent.
>
> Non-dt platforms may also want to register pinctrl mappings from code which
> is build as a module, which requires being able to unregister the mapping
> when the module is unloaded to avoid dangling pointers.
>
> To allow unregistering the mappings the devicetree code uses 2 internal
> functions: pinctrl_register_map and pinctrl_unregister_map.
>
> pinctrl_register_map allows the devicetree code to tell the core to
> not memdup the mappings as it retains ownership of them and
> pinctrl_unregister_map does the unregistering, note this only works
> when the mappings where not memdupped.
>
> The only code relying on the memdup/shallow-copy done by
> pinctrl_register_mappings is arch/arm/mach-u300/core.c this commit
> replaces the __initdata with const, so that the shallow-copy is no
> longer necessary.
>
> After that we can get rid of the internal pinctrl_unregister_map function
> and just use pinctrl_register_mappings directly everywhere.
>
> This commit also renames pinctrl_unregister_map to
> pinctrl_unregister_mappings so that its naming matches its
> pinctrl_register_mappings counter-part and exports it.
>
> Together these 2 changes will allow non-dt platform code to
> register pinctrl-mappings from modules without breaking things on
> module unload (as they can now unregister the mapping on unload).
>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
This v2 works fine for me, I applied it to this immutable branch in the
pinctrl tree:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git/log/?h=ib-pinctrl-unreg-mappings
And pulled that into the pinctrl "devel" branch for v5.6.
Please pull this immutable branch into the Intel DRM tree and apply
the rest of the stuff on top!
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH] pinctrl: intel: Pass irqchip when adding gpiochip
From: Mika Westerberg @ 2019-12-30 10:20 UTC (permalink / raw)
To: Linus Walleij; +Cc: linux-kernel, linux-gpio, Andy Shevchenko, Mathias Nyman
In-Reply-To: <20191229013059.495767-1-linus.walleij@linaro.org>
On Sun, Dec 29, 2019 at 02:30:59AM +0100, Linus Walleij wrote:
> We need to convert all old gpio irqchips to pass the irqchip
> setup along when adding the gpio_chip. For more info see
> drivers/gpio/TODO.
>
> Set up the pin ranges using the new callback.
Maybe have this one split as a separate patch? Same what we do for
Baytrail and Cherryview.
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> drivers/pinctrl/intel/pinctrl-intel.c | 61 +++++++++++++++------------
> 1 file changed, 35 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
> index 4860bc9a4e48..ffacd77861f7 100644
> --- a/drivers/pinctrl/intel/pinctrl-intel.c
> +++ b/drivers/pinctrl/intel/pinctrl-intel.c
> @@ -1160,8 +1160,8 @@ static irqreturn_t intel_gpio_irq(int irq, void *data)
> return ret;
> }
>
> -static int intel_gpio_add_pin_ranges(struct intel_pinctrl *pctrl,
> - const struct intel_community *community)
> +static int intel_gpio_add_community_ranges(struct intel_pinctrl *pctrl,
> + const struct intel_community *community)
> {
> int ret = 0, i;
>
> @@ -1181,6 +1181,24 @@ static int intel_gpio_add_pin_ranges(struct intel_pinctrl *pctrl,
> return ret;
> }
>
> +static int intel_gpio_add_pin_ranges(struct gpio_chip *gc)
> +{
> + struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
> + int ret, i;
> +
> + for (i = 0; i < pctrl->ncommunities; i++) {
> + struct intel_community *community = &pctrl->communities[i];
> +
> + ret = intel_gpio_add_community_ranges(pctrl, community);
> + if (ret) {
> + dev_err(pctrl->dev, "failed to add GPIO pin range\n");
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
> +
> static unsigned int intel_gpio_ngpio(const struct intel_pinctrl *pctrl)
> {
> const struct intel_community *community;
> @@ -1205,7 +1223,8 @@ static unsigned int intel_gpio_ngpio(const struct intel_pinctrl *pctrl)
>
> static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
> {
> - int ret, i;
> + int ret;
> + struct gpio_irq_chip *girq;
Nit:
Can you order these in "reverse christmas tree" like,
struct gpio_irq_chip *girq;
int ret;
Otherwise looks good to me, thanks!
^ permalink raw reply
* Re: [PATCH] pinctrl: baytrail: Do not clear IRQ flags on direct-irq enabled pins
From: Mika Westerberg @ 2019-12-30 10:10 UTC (permalink / raw)
To: Hans de Goede
Cc: Andy Shevchenko, Linus Walleij, Bastien Nocera, Dmitry Mastykin,
linux-gpio, linux-acpi
In-Reply-To: <20191227230447.32458-1-hdegoede@redhat.com>
On Sat, Dec 28, 2019 at 12:04:47AM +0100, Hans de Goede wrote:
> Suspending Goodix touchscreens requires changing the interrupt pin to
> output before sending them a power-down command. Followed by wiggling
> the interrupt pin to wake the device up, after which it is put back
> in input mode.
>
> On Bay Trail devices with a Goodix touchscreen direct-irq mode is used
> in combination with listing the pin as a normal GpioIo resource.
>
> This works fine, until the goodix driver gets rmmod-ed and then insmod-ed
> again. In this case byt_gpio_disable_free() calls
> byt_gpio_clear_triggering() which clears the IRQ flags and after that the
> (direct) IRQ no longer triggers.
>
> This commit fixes this by adding a check for the BYT_DIRECT_IRQ_EN flag
> to byt_gpio_clear_triggering().
>
> Note that byt_gpio_clear_triggering() only gets called from
> byt_gpio_disable_free() for direct-irq enabled pins, as these are excluded
> from the irq_valid mask by byt_init_irq_valid_mask().
>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
^ permalink raw reply
* Re: [PATCH v2] pinctrl: baytrail: Remove WARN when setting direct-irq pin to output
From: Mika Westerberg @ 2019-12-30 10:08 UTC (permalink / raw)
To: Hans de Goede
Cc: Andy Shevchenko, Linus Walleij, Bastien Nocera, Dmitry Mastykin,
linux-gpio, linux-acpi
In-Reply-To: <acafef49-bd32-6900-01d2-f6adccabe201@redhat.com>
On Fri, Dec 27, 2019 at 11:47:38PM +0100, Hans de Goede wrote:
> The problem is that we hit this path everytime we output a value on the
> pin. I guess we can change the WARN to dev_info_once() if you prefer that.
Yes, I think dev_info_once() would be fine.
^ permalink raw reply
* [PATCH v8 12/12] led: bd71828: Support LED outputs on ROHM BD71828 PMIC
From: Matti Vaittinen @ 2019-12-30 9:45 UTC (permalink / raw)
To: matti.vaittinen, mazziesaccount
Cc: Jacek Anaszewski, Pavel Machek, Dan Murphy, Rob Herring,
Mark Rutland, Lee Jones, Michael Turquette, Stephen Boyd,
Linus Walleij, Bartosz Golaszewski, Liam Girdwood, Mark Brown,
Alessandro Zummo, Alexandre Belloni, linux-leds, devicetree,
linux-kernel, linux-clk, linux-gpio, linux-rtc
In-Reply-To: <cover.1577694311.git.matti.vaittinen@fi.rohmeurope.com>
ROHM BD71828 power management IC has two LED outputs for charge status
and button pressing indications. The LED outputs can also be forced
by SW so add driver allowing to use these LEDs for other indications
as well.
Leds are controlled by SW using 'Force ON' bits. Please note the
constrains mentioned in data-sheet:
1. If one LED is forced ON - then also the other LED is forced.
=> You can't use SW control to force ON one LED and allow HW
to control the other.
2. You can't force both LEDs OFF. If the FORCE bit for both LED's is
zero, then LEDs are controlled by HW and indicate button/charger
states as explained in data-sheet.
Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
---
Changes from v7 - no changes
drivers/leds/Kconfig | 10 +++
drivers/leds/Makefile | 1 +
drivers/leds/leds-bd71828.c | 118 ++++++++++++++++++++++++++++++++++++
3 files changed, 129 insertions(+)
create mode 100644 drivers/leds/leds-bd71828.c
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 4b68520ac251..db408e03e296 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -545,6 +545,16 @@ config LEDS_BD2802
This option enables support for BD2802GU RGB LED driver chips
accessed via the I2C bus.
+config LEDS_BD71828
+ tristate "LED driver for LEDS on ROHM BD71828 PMIC"
+ depends on LEDS_CLASS
+ depends on MFD_ROHM_BD71828
+ help
+ This option enables support for LED outputs located on ROHM
+ BD71828 power management IC. ROHM BD71828 has two led output pins
+ which can be left to indicate HW states or controlled by SW. Say
+ yes here if you want to enable SW control for these LEDs.
+
config LEDS_INTEL_SS4200
tristate "LED driver for Intel NAS SS4200 series"
depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 2da39e896ce8..a5164acfaf51 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_LEDS_AN30259A) += leds-an30259a.o
obj-$(CONFIG_LEDS_BCM6328) += leds-bcm6328.o
obj-$(CONFIG_LEDS_BCM6358) += leds-bcm6358.o
obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o
+obj-$(CONFIG_LEDS_BD71828) += leds-bd71828.o
obj-$(CONFIG_LEDS_CPCAP) += leds-cpcap.o
obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o
diff --git a/drivers/leds/leds-bd71828.c b/drivers/leds/leds-bd71828.c
new file mode 100644
index 000000000000..a02c2ac4a70b
--- /dev/null
+++ b/drivers/leds/leds-bd71828.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Copyright (C) 2019 ROHM Semiconductors
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/mfd/rohm-bd71828.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define BD71828_LED_TO_DATA(l) ((l)->id == ID_GREEN_LED ? \
+ container_of((l), struct bd71828_leds, green) : \
+ container_of((l), struct bd71828_leds, amber))
+
+/* Names for led identification - these match the data sheet names */
+enum {
+ ID_GREEN_LED,
+ ID_AMBER_LED,
+ ID_NMBR_OF,
+};
+
+struct bd71828_led {
+ struct led_init_data init_data;
+ int id;
+ struct led_classdev l;
+ u8 force_mask;
+};
+
+struct bd71828_leds {
+ struct rohm_regmap_dev *bd71828;
+ struct bd71828_led green;
+ struct bd71828_led amber;
+};
+
+static int bd71828_led_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct bd71828_led *l = container_of(led_cdev, struct bd71828_led, l);
+ struct bd71828_leds *data;
+ unsigned int val = BD71828_LED_OFF;
+
+ data = BD71828_LED_TO_DATA(l);
+ if (value != LED_OFF)
+ val = BD71828_LED_ON;
+
+ return regmap_update_bits(data->bd71828->regmap, BD71828_REG_LED_CTRL,
+ l->force_mask, val);
+}
+
+static int bd71828_led_probe(struct platform_device *pdev)
+{
+ struct rohm_regmap_dev *bd71828;
+ struct bd71828_leds *l;
+ struct bd71828_led *g, *a;
+ int ret;
+
+ bd71828 = dev_get_drvdata(pdev->dev.parent);
+ l = devm_kzalloc(&pdev->dev, sizeof(*l), GFP_KERNEL);
+ if (!l)
+ return -ENOMEM;
+ l->bd71828 = bd71828;
+ a = &l->amber;
+ g = &l->green;
+
+ /* Fill in details for 'AMBLED' */
+ a->init_data.match_property.name = "rohm,led-compatible";
+ a->init_data.match_property.raw_val = "bd71828-ambled";
+ a->init_data.match_property.size = strlen("bd71828-ambled");
+ a->id = ID_AMBER_LED;
+ a->force_mask = BD71828_MASK_LED_AMBER;
+
+ /* Fill in details for 'GRNLED' */
+ g->init_data.match_property.name = "rohm,led-compatible";
+ g->init_data.match_property.raw_val = "bd71828-grnled";
+ g->init_data.match_property.size = strlen("bd71828-grnled");
+ g->id = ID_GREEN_LED;
+ g->force_mask = BD71828_MASK_LED_GREEN;
+
+ a->l.brightness_set_blocking = bd71828_led_brightness_set;
+ g->l.brightness_set_blocking = bd71828_led_brightness_set;
+
+ ret = devm_led_classdev_register_ext(&pdev->dev, &g->l, &g->init_data);
+ if (ret)
+ return ret;
+
+ return devm_led_classdev_register_ext(&pdev->dev, &a->l, &a->init_data);
+}
+
+/*
+ * Device is instantiated through parent MFD device and device matching is done
+ * through platform_device_id.
+ *
+ * However, the *module* matching will be done trough DT aliases. This requires
+ * of_device_id table - but no .of_match_table as *device* matching is still
+ * done through platform_device_id.
+ */
+static const struct of_device_id bd71828_dt_match[] __used = {
+ { .compatible = "rohm,bd71828-leds" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, bd71828_dt_match);
+
+static struct platform_driver bd71828_led_driver = {
+ .driver = {
+ .name = "bd71828-led",
+ },
+ .probe = bd71828_led_probe,
+};
+
+module_platform_driver(bd71828_led_driver);
+
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_DESCRIPTION("ROHM BD71828 LED driver");
+MODULE_LICENSE("GPL");
--
2.21.0
--
Matti Vaittinen, Linux device drivers
ROHM Semiconductors, Finland SWDC
Kiviharjunlenkki 1E
90220 OULU
FINLAND
~~~ "I don't think so," said Rene Descartes. Just then he vanished ~~~
Simon says - in Latin please.
~~~ "non cogito me" dixit Rene Descarte, deinde evanescavit ~~~
Thanks to Simon Glass for the translation =]
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox