Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1604741 > unrolled thread
| Started by | Jacopo Mondi <jacopo+renesas@jmondi.org> |
|---|---|
| First post | 2017-03-20 17:30 +0100 |
| Last post | 2017-03-22 19:20 +0100 |
| Articles | 20 on this page of 22 — 4 participants |
Back to article view | Back to linux.kernel
[PATCH v2 0/7] Renesas RZ/A1 pin and gpio controller Jacopo Mondi <jacopo+renesas@jmondi.org> - 2017-03-20 17:30 +0100
[PATCH v2 6/7] arm: dts: genmai: Add RIIC2 pin group Jacopo Mondi <jacopo+renesas@jmondi.org> - 2017-03-20 17:30 +0100
Re: [PATCH v2 6/7] arm: dts: genmai: Add RIIC2 pin group Geert Uytterhoeven <geert@linux-m68k.org> - 2017-03-22 14:20 +0100
[PATCH v2 7/7] arm: dts: genmai: Add user led device nodes Jacopo Mondi <jacopo+renesas@jmondi.org> - 2017-03-20 17:30 +0100
Re: [PATCH v2 7/7] arm: dts: genmai: Add user led device nodes Geert Uytterhoeven <geert@linux-m68k.org> - 2017-03-22 14:30 +0100
[PATCH v2 1/7] pinctrl: Renesas RZ/A1 pin and gpio controller Jacopo Mondi <jacopo+renesas@jmondi.org> - 2017-03-20 17:50 +0100
Re: [PATCH v2 1/7] pinctrl: Renesas RZ/A1 pin and gpio controller Geert Uytterhoeven <geert@linux-m68k.org> - 2017-03-22 11:30 +0100
Re: [PATCH v2 1/7] pinctrl: Renesas RZ/A1 pin and gpio controller jacopo <jacopo@jmondi.org> - 2017-03-23 15:30 +0100
[PATCH v2 4/7] arm: dts: r7s72100: Add pin controller node Jacopo Mondi <jacopo+renesas@jmondi.org> - 2017-03-20 17:50 +0100
Re: [PATCH v2 4/7] arm: dts: r7s72100: Add pin controller node Geert Uytterhoeven <geert@linux-m68k.org> - 2017-03-22 14:20 +0100
Re: [PATCH v2 4/7] arm: dts: r7s72100: Add pin controller node jacopo <jacopo@jmondi.org> - 2017-03-23 17:20 +0100
[PATCH v2 3/7] arm: dts: dt-bindings: Add Renesas RZ pinctrl header Jacopo Mondi <jacopo+renesas@jmondi.org> - 2017-03-20 18:00 +0100
Re: [PATCH v2 3/7] arm: dts: dt-bindings: Add Renesas RZ pinctrl header Geert Uytterhoeven <geert@linux-m68k.org> - 2017-03-22 11:40 +0100
[PATCH v2 5/7] arm: dts: genmai: Add SCIF2 pin group Jacopo Mondi <jacopo+renesas@jmondi.org> - 2017-03-20 18:00 +0100
Re: [PATCH v2 5/7] arm: dts: genmai: Add SCIF2 pin group Geert Uytterhoeven <geert@linux-m68k.org> - 2017-03-22 14:20 +0100
[PATCH v2 2/7] dt-bindings: pinctrl: Add RZ/A1 bindings doc Jacopo Mondi <jacopo+renesas@jmondi.org> - 2017-03-20 18:30 +0100
Re: [PATCH v2 2/7] dt-bindings: pinctrl: Add RZ/A1 bindings doc Geert Uytterhoeven <geert@linux-m68k.org> - 2017-03-22 11:40 +0100
Re: [PATCH v2 2/7] dt-bindings: pinctrl: Add RZ/A1 bindings doc Geert Uytterhoeven <geert@linux-m68k.org> - 2017-03-22 14:30 +0100
Re: [PATCH v2 2/7] dt-bindings: pinctrl: Add RZ/A1 bindings doc jacopo <jacopo@jmondi.org> - 2017-03-22 16:40 +0100
Re: [PATCH v2 2/7] dt-bindings: pinctrl: Add RZ/A1 bindings doc Geert Uytterhoeven <geert@linux-m68k.org> - 2017-03-22 17:00 +0100
Re: [PATCH v2 2/7] dt-bindings: pinctrl: Add RZ/A1 bindings doc jacopo <jacopo@jmondi.org> - 2017-03-23 17:10 +0100
RE: [PATCH v2 0/7] Renesas RZ/A1 pin and gpio controller Chris Brandt <Chris.Brandt@renesas.com> - 2017-03-22 19:20 +0100
Page 1 of 2 [1] 2 Next page →
| From | Jacopo Mondi <jacopo+renesas@jmondi.org> |
|---|---|
| Date | 2017-03-20 17:30 +0100 |
| Subject | [PATCH v2 0/7] Renesas RZ/A1 pin and gpio controller |
| Message-ID | <tn8lY-7kZ-19@gated-at.bofh.it> |
Hello, second round of combined GPIO and pin controller driver for Renesas RZ/A1 SoC. Few adjustments compared to v1. The most visible one is the update of pin configuration flag to what Chris suggested, and consequent simplification of pin multiplexing routine. Some other fixes in DTS suggested by Geert have been applied. Testing done verifying functionalities of hardware modules enabled in device tree (SCIF2 for serial output, RIIC for accessing an internal eeprom chip and user visible leds). Gpio have been also verified using a i2c-gpio device in place of the native RIIC one to access the same eeprom device. Chris: it would be great if you could give this another spin on RSK board. In v4.11 generic pinmux and pinctrl function have been merged in mainline, so no need for an ad-hoc branch if you're willing to test this again. Thanks j v1 -> v2: - change pin configuration flags as suggested by Chris - gpio set direction function fixed as suggested by Chris - add some more example on pin configuration flag usage to dt-binding doc - fix gpio-controller names to remove unit address as suggested by Geert - some comments chopped here and there to make the driver less verbose Jacopo Mondi (7): pinctrl: Renesas RZ/A1 pin and gpio controller dt-bindings: pinctrl: Add RZ/A1 bindings doc arm: dts: dt-bindings: Add Renesas RZ pinctrl header arm: dts: r7s72100: Add pin controller node arm: dts: genmai: Add SCIF2 pin group arm: dts: genmai: Add RIIC2 pin group arm: dts: genmai: Add user led device nodes .../bindings/pinctrl/renesas,rza1-pinctrl.txt | 144 +++ arch/arm/boot/dts/r7s72100-genmai.dts | 36 + arch/arm/boot/dts/r7s72100.dtsi | 80 ++ drivers/pinctrl/Kconfig | 10 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-rza1.c | 963 +++++++++++++++++++++ include/dt-bindings/pinctrl/r7s72100-pinctrl.h | 36 + 7 files changed, 1270 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt create mode 100644 drivers/pinctrl/pinctrl-rza1.c create mode 100644 include/dt-bindings/pinctrl/r7s72100-pinctrl.h -- 2.7.4
[toc] | [next] | [standalone]
| From | Jacopo Mondi <jacopo+renesas@jmondi.org> |
|---|---|
| Date | 2017-03-20 17:30 +0100 |
| Subject | [PATCH v2 6/7] arm: dts: genmai: Add RIIC2 pin group |
| Message-ID | <tn8lX-7kZ-17@gated-at.bofh.it> |
| In reply to | #1604741 |
Add pin configuration subnode for RIIC2 interface.
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
arch/arm/boot/dts/r7s72100-genmai.dts | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm/boot/dts/r7s72100-genmai.dts b/arch/arm/boot/dts/r7s72100-genmai.dts
index 569c86a..30992b1 100644
--- a/arch/arm/boot/dts/r7s72100-genmai.dts
+++ b/arch/arm/boot/dts/r7s72100-genmai.dts
@@ -44,6 +44,12 @@
renesas,pins = <PIN(3, 0) 6>,
<PIN(3, 2) 4>;
};
+
+ i2c2_pins: i2c2 {
+ /* RIIC2: P1_4 as SCL, P1_5 as SDA */
+ renesas,pins = <PIN(1, 4) (1 | BI_DIR)>,
+ <PIN(1, 5) (1 | BI_DIR)>;
+ };
};
&extal_clk {
@@ -62,6 +68,9 @@
status = "okay";
clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins>;
+
eeprom@50 {
compatible = "renesas,24c128";
reg = <0x50>;
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-03-22 14:20 +0100 |
| Subject | Re: [PATCH v2 6/7] arm: dts: genmai: Add RIIC2 pin group |
| Message-ID | <tnOlc-2UB-13@gated-at.bofh.it> |
| In reply to | #1604742 |
On Mon, Mar 20, 2017 at 5:14 PM, Jacopo Mondi <jacopo+renesas@jmondi.org> wrote:
> Add pin configuration subnode for RIIC2 interface.
>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
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
[toc] | [prev] | [next] | [standalone]
| From | Jacopo Mondi <jacopo+renesas@jmondi.org> |
|---|---|
| Date | 2017-03-20 17:30 +0100 |
| Subject | [PATCH v2 7/7] arm: dts: genmai: Add user led device nodes |
| Message-ID | <tn8lY-7kZ-33@gated-at.bofh.it> |
| In reply to | #1604741 |
Add device nodes for user leds on Genmai board.
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
arch/arm/boot/dts/r7s72100-genmai.dts | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm/boot/dts/r7s72100-genmai.dts b/arch/arm/boot/dts/r7s72100-genmai.dts
index 30992b1..94b9ab7 100644
--- a/arch/arm/boot/dts/r7s72100-genmai.dts
+++ b/arch/arm/boot/dts/r7s72100-genmai.dts
@@ -11,6 +11,7 @@
/dts-v1/;
#include "r7s72100.dtsi"
+#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/r7s72100-pinctrl.h>
/ {
@@ -35,6 +36,19 @@
#address-cells = <1>;
#size-cells = <1>;
};
+
+ leds {
+ status = "okay";
+ compatible = "gpio-leds";
+
+ led1 {
+ gpios = <&port4 10 GPIO_ACTIVE_LOW>;
+ };
+
+ led2 {
+ gpios = <&port4 11 GPIO_ACTIVE_LOW>;
+ };
+ };
};
&pinctrl {
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-03-22 14:30 +0100 |
| Subject | Re: [PATCH v2 7/7] arm: dts: genmai: Add user led device nodes |
| Message-ID | <tnOuS-32T-21@gated-at.bofh.it> |
| In reply to | #1604745 |
On Mon, Mar 20, 2017 at 5:14 PM, Jacopo Mondi <jacopo+renesas@jmondi.org> wrote:
> Add device nodes for user leds on Genmai board.
>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
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
[toc] | [prev] | [next] | [standalone]
| From | Jacopo Mondi <jacopo+renesas@jmondi.org> |
|---|---|
| Date | 2017-03-20 17:50 +0100 |
| Subject | [PATCH v2 1/7] pinctrl: Renesas RZ/A1 pin and gpio controller |
| Message-ID | <tn8Fk-7tv-17@gated-at.bofh.it> |
| In reply to | #1604741 |
Add combined gpio and pin controller driver for Renesas RZ/A1
r7s72100 SoC.
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
drivers/pinctrl/Kconfig | 10 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/pinctrl-rza1.c | 963 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 974 insertions(+)
create mode 100644 drivers/pinctrl/pinctrl-rza1.c
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 8f8c2af..c9b55b9 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -163,6 +163,16 @@ config PINCTRL_ROCKCHIP
select GENERIC_IRQ_CHIP
select MFD_SYSCON
+config PINCTRL_RZA1
+ bool "Renesas RZ/A1 gpio and pinctrl driver"
+ depends on OF
+ depends on ARCH_R7S72100 || COMPILE_TEST
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select GENERIC_PINCONF
+ help
+ This selects pinctrl driver for Renesas RZ/A1 platforms.
+
config PINCTRL_SINGLE
tristate "One-register-per-pin type device tree based pinctrl driver"
depends on OF
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index a251f43..0c2328d2 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o
obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o
obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
+obj-$(CONFIG_PINCTRL_RZA1) += pinctrl-rza1.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_SIRF) += sirf/
obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o
diff --git a/drivers/pinctrl/pinctrl-rza1.c b/drivers/pinctrl/pinctrl-rza1.c
new file mode 100644
index 0000000..d2f50ab
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-rza1.c
@@ -0,0 +1,963 @@
+/*
+ * Combined GPIO and pin controller support for Renesas RZ/A1 (r7s72100) SoC
+ *
+ * Copyright (C) 2017 Jacopo Mondi
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/*
+ * This pincontroller/gpio combined driver support Renesas devices of RZ/A1
+ * family.
+ * This includes SoCs which are sub- or super- sets of this particular line,
+ * as RZ/A1H (r7s721000), RZ/A1M (r7s721001) and RZ/A1L (r7s721002) are.
+ */
+
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/gpio/driver.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/slab.h>
+
+#include "core.h"
+#include "devicetree.h"
+#include "pinmux.h"
+
+#define DRIVER_NAME "pinctrl-rza1"
+
+#define RZA1_PINMUX_OF_ARGS 2
+
+#define P_REG 0x0000
+#define PPR_REG 0x0200
+#define PM_REG 0x0300
+#define PMC_REG 0x0400
+#define PFC_REG 0x0500
+#define PFCE_REG 0x0600
+#define PFCEA_REG 0x0a00
+#define PIBC_REG 0x4000
+#define PBDC_REG 0x4100
+#define PIPC_REG 0x4200
+#define RZA1_ADDR(mem, reg, port) ((mem) + (reg) + ((port) * 4))
+
+#define RZA1_NPORTS 12
+#define RZA1_PINS_PER_PORT 16
+#define RZA1_NPINS (RZA1_PINS_PER_PORT * RZA1_NPORTS)
+#define RZA1_PIN_TO_PORT(pin) ((pin) / RZA1_PINS_PER_PORT)
+#define RZA1_PIN_TO_OFFSET(pin) ((pin) % RZA1_PINS_PER_PORT)
+
+/*
+ * Be careful here: the pin configuration subnodes in device tree enumerates
+ * alternate functions from 1 to 8; subtract 1 before using macros so to match
+ * registers configuration which expects numbers from 0 to 7 instead.
+ */
+#define MUX_FUNC_OFFS 3
+#define MUX_FUNC_MASK (BIT(MUX_FUNC_OFFS) - 1)
+#define MUX_FUNC_PFC_MASK BIT(0)
+#define MUX_FUNC_PFCE_MASK BIT(1)
+#define MUX_FUNC_PFCEA_MASK BIT(2)
+#define MUX_CONF_BIDIR BIT(0)
+#define MUX_CONF_SWIO_INPUT BIT(1)
+#define MUX_CONF_SWIO_OUTPUT BIT(2)
+
+/**
+ * rza1_pin_conf - describes a pin position, id, mux config and output value
+ *
+ * Use uint32_t to match types used in of_device nodes argument lists.
+ *
+ * @id: the pin identifier from 0 to RZA1_NPINS
+ * @port: the port where pin sits on
+ * @offset: pin offset in the port
+ * @mux: alternate function configuration settings
+ * @value: output value to set the pin to
+ */
+struct rza1_pin_conf {
+ uint32_t id;
+ uint32_t port;
+ uint32_t offset;
+ uint32_t mux_conf;
+ uint32_t value;
+};
+
+/**
+ * rza1_port - describes a pin port
+ *
+ * This is mostly useful to lock register writes per-bank and not globally.
+ *
+ * @lock: protect access to HW registers
+ * @id: port number
+ * @base: logical address base
+ * @pins: pins sitting on this port
+ */
+struct rza1_port {
+ spinlock_t lock;
+ unsigned int id;
+ void __iomem *base;
+ struct pinctrl_pin_desc *pins;
+};
+
+/**
+ * rza1_pinctrl - RZ pincontroller device
+ *
+ * @dev: parent device structure
+ * @mutex: protect [pinctrl|pinmux]_generic functions
+ * @base: logical address base
+ * @nports: number of pin controller ports
+ * @ports: pin controller banks
+ * @ngpiochips: number of gpio chips
+ * @gpio_ranges: gpio ranges for pinctrl core
+ * @pins: pin array for pinctrl core
+ * @desc: pincontroller desc for pinctrl core
+ * @pctl: pinctrl device
+ */
+struct rza1_pinctrl {
+ struct device *dev;
+
+ struct mutex mutex;
+
+ void __iomem *base;
+
+ unsigned int nport;
+ struct rza1_port *ports;
+
+ unsigned int ngpiochips;
+
+ struct pinctrl_gpio_range *gpio_ranges;
+ struct pinctrl_pin_desc *pins;
+ struct pinctrl_desc desc;
+ struct pinctrl_dev *pctl;
+};
+
+/* ----------------------------------------------------------------------------
+ * RZ/A1 SoC operations
+ */
+
+/**
+ * rza1_set_bit() - un-locked set/clear a single bit in pin configuration
+ * registers
+ */
+static inline void rza1_set_bit(const struct rza1_port *port,
+ unsigned int reg, unsigned int offset,
+ bool set)
+{
+ void __iomem *mem = RZA1_ADDR(port->base, reg, port->id);
+ u16 val = ioread16(mem);
+
+ if (set)
+ val |= BIT(offset);
+ else
+ val &= ~BIT(offset);
+
+ iowrite16(val, mem);
+}
+
+static inline int rza1_get_bit(struct rza1_port *port,
+ unsigned int reg, unsigned int offset)
+{
+ void __iomem *mem = RZA1_ADDR(port->base, reg, port->id);
+
+ return ioread16(mem) & BIT(offset);
+}
+
+/**
+ * rza1_pin_reset() - reset a pin to default initial state
+ *
+ * Reset pin state disabling input buffer and bi-directional control,
+ * and configure it as input port.
+ * Note that pin is now configured with direction as input but with input
+ * buffer disabled. This implies the pin value cannot be read in this state.
+ *
+ * @port: port where pin sits on
+ * @offset: pin offset
+ */
+static void rza1_pin_reset(struct rza1_port *port,
+ unsigned int offset)
+{
+ spin_lock(&port->lock);
+ rza1_set_bit(port, PIBC_REG, offset, 0);
+ rza1_set_bit(port, PBDC_REG, offset, 0);
+
+ rza1_set_bit(port, PM_REG, offset, 1);
+ rza1_set_bit(port, PMC_REG, offset, 0);
+ rza1_set_bit(port, PIPC_REG, offset, 0);
+ spin_unlock(&port->lock);
+}
+
+static inline int rza1_pin_get_direction(struct rza1_port *port,
+ int offset)
+{
+ int input;
+
+ spin_lock(&port->lock);
+ input = rza1_get_bit(port, PM_REG, offset);
+ spin_unlock(&port->lock);
+
+ return input;
+}
+
+/**
+ * rza1_pin_set_direction() - set I/O direction on a pin in port mode
+ *
+ * When running in output port mode keep PBDC enabled to allow reading the
+ * pin value from PPR.
+ *
+ * @port: port where pin sits on
+ * @offset: pin offset
+ * @input: input enable/disable flag
+ */
+static inline void rza1_pin_set_direction(struct rza1_port *port,
+ unsigned int offset,
+ bool input)
+{
+ spin_lock(&port->lock);
+
+ rza1_set_bit(port, PIBC_REG, offset, 1);
+ if (input) {
+ rza1_set_bit(port, PM_REG, offset, 1);
+ rza1_set_bit(port, PBDC_REG, offset, 0);
+ } else {
+ rza1_set_bit(port, PM_REG, offset, 0);
+ rza1_set_bit(port, PBDC_REG, offset, 1);
+ }
+
+ spin_unlock(&port->lock);
+}
+
+static inline void rza1_pin_set(struct rza1_port *port,
+ unsigned int offset, unsigned int value)
+{
+ spin_lock(&port->lock);
+ rza1_set_bit(port, P_REG, offset, !!value);
+ spin_unlock(&port->lock);
+}
+
+static inline int rza1_pin_get(struct rza1_port *port, unsigned int offset)
+{
+ int val;
+
+ spin_lock(&port->lock);
+ val = rza1_get_bit(port, PPR_REG, offset);
+ spin_unlock(&port->lock);
+
+ return val;
+}
+
+/**
+ * rza1_pin_conf_validate() - make sure a single bit it set in mux_conf mask
+ */
+static inline int rza1_pin_conf_validate(u8 mux_conf)
+{
+ do {
+ if (mux_conf & BIT(0))
+ break;
+ } while ((mux_conf >>= 1));
+
+ return (mux_conf >> 1);
+}
+
+/**
+ * rza1_alternate_function_conf() - configure pin in alternate function mode
+ *
+ * @pinctrl: RZ/A1 pin controller device
+ * @pin_conf: single pin configuration descriptor
+ */
+static int rza1_alternate_function_conf(struct rza1_pinctrl *rza1_pctl,
+ struct rza1_pin_conf *pin_conf)
+{
+ unsigned int offset = pin_conf->offset;
+ struct rza1_port *port = &rza1_pctl->ports[pin_conf->port];
+ u8 mux_mode = (pin_conf->mux_conf - 1) & MUX_FUNC_MASK;
+ u8 mux_conf = pin_conf->mux_conf >> MUX_FUNC_OFFS;
+ bool bidir_en = !!(mux_conf & MUX_CONF_BIDIR);
+ bool swio_in = !!(mux_conf & MUX_CONF_SWIO_INPUT);
+ bool swio_out = !!(mux_conf & MUX_CONF_SWIO_OUTPUT);
+
+ if (rza1_pin_conf_validate(mux_conf)) {
+ dev_err(rza1_pctl->dev,
+ "Invalid pin configuration for pin %u:%u",
+ port->id, offset);
+ return -EINVAL;
+ }
+
+ rza1_pin_reset(port, offset);
+
+ if (bidir_en)
+ rza1_set_bit(port, PBDC_REG, offset, 1);
+
+ /*
+ * Enable alternate function mode and select it.
+ *
+ * ----------------------------------------------------
+ * Alternate mode selection table:
+ *
+ * PMC PFC PFCE PFCAE mux_mode
+ * 1 0 0 0 0
+ * 1 1 0 0 1
+ * 1 0 1 0 2
+ * 1 1 1 0 3
+ * 1 0 0 1 4
+ * 1 1 0 1 5
+ * 1 0 1 1 6
+ * 1 1 1 1 7
+ * ----------------------------------------------------
+ */
+ rza1_set_bit(port, PFC_REG, offset, mux_mode & MUX_FUNC_PFC_MASK);
+ rza1_set_bit(port, PFCE_REG, offset, mux_mode & MUX_FUNC_PFCE_MASK);
+ rza1_set_bit(port, PFCEA_REG, offset, mux_mode & MUX_FUNC_PFCEA_MASK);
+
+ /*
+ * All alternate functions except a few (4) need PIPCn = 1.
+ * If PIPCn has to stay disabled (SW IO mode), configure PMn according
+ * to I/O direction specified by pin configuration -after- PMC has been
+ * set to one.
+ */
+ if (!(swio_in || swio_out))
+ rza1_set_bit(port, PIPC_REG, offset, 1);
+
+ rza1_set_bit(port, PMC_REG, offset, 1);
+ rza1_set_bit(port, PM_REG, offset, swio_in);
+
+ return 0;
+}
+
+/* ----------------------------------------------------------------------------
+ * pinctrl operations
+ */
+
+/**
+ * rza1_dt_node_to_map() - map a node to a function/group map
+ *
+ * Functions and groups are collected and registered to pinctrl_generic
+ * during DT parsing routine.
+ *
+ * @pctldev: pin controller device
+ * @np: device tree node to parse
+ * @map: pointer to pin map (output)
+ * @num_maps: number of collected maps (output)
+ */
+static int rza1_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **map,
+ unsigned int *num_maps)
+{
+ struct rza1_pinctrl *rza1_pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct group_desc *grp;
+ unsigned int grp_sel;
+
+ /*
+ * Find the group of this node and check if we need create
+ * config maps for pins.
+ */
+ grp_sel = pinctrl_get_group_selector(pctldev, np->name);
+ if (grp_sel < 0) {
+ dev_err(rza1_pctl->dev, "unable to find group for node %s\n",
+ np->name);
+ return -EINVAL;
+ }
+
+ grp = pinctrl_generic_get_group(pctldev, grp_sel);
+ if (!grp) {
+ dev_err(rza1_pctl->dev, "unable to find group for node %s\n",
+ np->name);
+ return -EINVAL;
+ }
+
+ *num_maps = 0;
+ *map = kzalloc(sizeof(**map), GFP_KERNEL);
+ if (!*map)
+ return -ENOMEM;
+
+ (*map)->type = PIN_MAP_TYPE_MUX_GROUP;
+ (*map)->data.mux.group = np->name;
+ (*map)->data.mux.function = np->name;
+ *num_maps = 1;
+
+ return 0;
+}
+
+static void rza1_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned int num_maps)
+{
+ kfree(map);
+}
+
+static const struct pinctrl_ops rza1_pinctrl_ops = {
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
+ .dt_node_to_map = rza1_dt_node_to_map,
+ .dt_free_map = rza1_dt_free_map,
+};
+
+/* ----------------------------------------------------------------------------
+ * gpio operations
+ */
+
+/**
+ * rza1_gpio_request() - configure pin in port mode
+ *
+ * Configure a pin as gpio (port mode).
+ * After reset, the pin is in input mode with input buffer disabled.
+ * To use the pin as input or output, set_direction shall be called first
+ *
+ * @chip: gpio chip where the gpio sits on
+ * @gpio: gpio offset
+ */
+static int rza1_gpio_request(struct gpio_chip *chip, unsigned int gpio)
+{
+ struct rza1_port *port = gpiochip_get_data(chip);
+
+ rza1_pin_reset(port, gpio);
+
+ return 0;
+}
+
+/**
+ * rza1_gpio_disable_free() - reset a pin
+ *
+ * Surprisingly, disable_free a gpio, is equivalent to request it.
+ * Reset pin to port mode, with input buffer disabled. This overwrites all
+ * port direction settings applied with set_direction
+ *
+ * @chip: gpio chip where the gpio sits on
+ * @gpio: gpio offset
+ */
+static void rza1_gpio_free(struct gpio_chip *chip, unsigned int gpio)
+{
+ struct rza1_port *port = gpiochip_get_data(chip);
+
+ rza1_pin_reset(port, gpio);
+}
+
+static int rza1_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ struct rza1_port *port = gpiochip_get_data(chip);
+
+ return rza1_pin_get_direction(port, offset);
+}
+
+static int rza1_gpio_direction_input(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct rza1_port *port = gpiochip_get_data(chip);
+
+ rza1_pin_set_direction(port, offset, true);
+
+ return 0;
+}
+
+static int rza1_gpio_direction_output(struct gpio_chip *chip,
+ unsigned int offset,
+ int value)
+{
+ struct rza1_port *port = gpiochip_get_data(chip);
+
+ /* Set value before driving pin direction */
+ rza1_pin_set(port, offset, value);
+ rza1_pin_set_direction(port, offset, false);
+
+ return 0;
+}
+
+/**
+ * rza1_gpio_get() - read a gpio pin value
+ *
+ * Read gpio pin value through PPR register.
+ * Requires bi-directional mode to work when reading value of a pin
+ * in output mode
+ *
+ * @chip: gpio chip where the gpio sits on
+ * @gpio: gpio offset
+ */
+static int rza1_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct rza1_port *port = gpiochip_get_data(chip);
+
+ return rza1_pin_get(port, offset);
+}
+
+static void rza1_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ struct rza1_port *port = gpiochip_get_data(chip);
+
+ rza1_pin_set(port, offset, value);
+}
+
+struct gpio_chip rza1_gpiochip_template = {
+ .request = rza1_gpio_request,
+ .free = rza1_gpio_free,
+ .get_direction = rza1_gpio_get_direction,
+ .direction_input = rza1_gpio_direction_input,
+ .direction_output = rza1_gpio_direction_output,
+ .get = rza1_gpio_get,
+ .set = rza1_gpio_set,
+};
+
+/* ----------------------------------------------------------------------------
+ * pinmux operations
+ */
+
+/**
+ * rza1_pinmux_set() - retrieve pins from a group and apply them mux settings
+ *
+ * @pctldev: pin controller device
+ * @selector: function selector
+ * @group: group selector
+ */
+static int rza1_pinmux_set(struct pinctrl_dev *pctldev, unsigned int selector,
+ unsigned int group)
+{
+ int i;
+ struct group_desc *grp;
+ struct function_desc *func;
+ struct rza1_pin_conf *pin_confs;
+ struct rza1_pinctrl *rza1_pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ grp = pinctrl_generic_get_group(pctldev, group);
+ if (!grp)
+ return -EINVAL;
+
+ func = pinmux_generic_get_function(pctldev, selector);
+ if (!func)
+ return -EINVAL;
+
+ pin_confs = (struct rza1_pin_conf *)func->data;
+ for (i = 0; i < grp->num_pins; ++i) {
+ int ret;
+
+ ret = rza1_alternate_function_conf(rza1_pctl, &pin_confs[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+struct pinmux_ops rza1_pinmux_ops = {
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
+ .set_mux = rza1_pinmux_set,
+ .strict = true,
+};
+
+/* ----------------------------------------------------------------------------
+ * RZ/A1 pin controller driver operations
+ */
+
+static unsigned int rza1_count_gpio_chips(struct device_node *np)
+{
+ unsigned int count = 0;
+ struct device_node *child;
+
+ for_each_child_of_node(np, child) {
+ if (!of_property_read_bool(child, "gpio-controller"))
+ continue;
+
+ count++;
+ }
+
+ return count;
+}
+
+/**
+ * rza1_parse_pmx_function() - parse and register a pin mux function
+ *
+ * Pins for RZ SoC pin controller described by "renesas-pins" property.
+ *
+ * First argument in the list identifies the pin, while the second one
+ * describes the requested alternate function number and additional
+ * configuration parameter to be applied to the selected function.
+ *
+ * @rza1_pctl: RZ/A1 pin controller device
+ * @np: of pmx sub-node
+ */
+static int rza1_parse_pmx_function(struct rza1_pinctrl *rza1_pctl,
+ struct device_node *np)
+{
+ int ret;
+ int of_pins;
+ unsigned int i;
+ unsigned int *grpins;
+ const char *grpname;
+ const char **fngrps;
+ struct rza1_pin_conf *pin_confs;
+ struct pinctrl_dev *pctldev = rza1_pctl->pctl;
+ char const *prop_name = "renesas,pins";
+
+ of_pins = pinctrl_count_index_with_args(np, prop_name);
+ if (of_pins <= 0) {
+ dev_err(rza1_pctl->dev, "Missing %s property\n", prop_name);
+ return -ENOENT;
+ }
+
+ /*
+ * Functions are made of 1 group only;
+ * in facts, functions and groups are identical for this pin controller
+ * except that functions carry an array of per-pin configurations
+ * settings.
+ */
+ pin_confs = devm_kcalloc(rza1_pctl->dev, of_pins, sizeof(*pin_confs),
+ GFP_KERNEL);
+ grpins = devm_kcalloc(rza1_pctl->dev, of_pins, sizeof(*grpins),
+ GFP_KERNEL);
+ fngrps = devm_kzalloc(rza1_pctl->dev, sizeof(*fngrps), GFP_KERNEL);
+
+ if (!pin_confs || !grpins || !fngrps)
+ return -ENOMEM;
+
+ /* Collect pin positions and mux settings to store them in function */
+ for (i = 0; i < of_pins; ++i) {
+ struct rza1_pin_conf *pin_conf = &pin_confs[i];
+ struct of_phandle_args of_pins_args;
+
+ ret = pinctrl_parse_index_with_args(np, prop_name, i,
+ &of_pins_args);
+ if (ret)
+ return ret;
+
+ if (of_pins_args.args_count < RZA1_PINMUX_OF_ARGS) {
+ dev_err(rza1_pctl->dev,
+ "Wrong arguments number for %s property\n",
+ prop_name);
+ return -EINVAL;
+ }
+
+ /*
+ * This new pins configuration will be associated with a new
+ * function, and later used to set-up pin muxing
+ */
+ pin_conf->id = of_pins_args.args[0];
+ pin_conf->port = RZA1_PIN_TO_PORT(pin_conf->id);
+ pin_conf->offset = RZA1_PIN_TO_OFFSET(pin_conf->id);
+ pin_conf->mux_conf = of_pins_args.args[1];
+
+ if (pin_conf->port >= RZA1_NPORTS ||
+ pin_conf->offset >= RZA1_PINS_PER_PORT) {
+ dev_err(rza1_pctl->dev,
+ "Wrong port %u pin %u for %s property\n",
+ pin_conf->port, pin_conf->offset, prop_name);
+ return -EINVAL;
+ }
+
+ grpins[i] = pin_conf->id;
+ }
+
+ grpname = np->name;
+ fngrps[0] = grpname;
+
+ mutex_lock(&rza1_pctl->mutex);
+ ret = pinctrl_generic_add_group(pctldev, grpname, grpins, of_pins,
+ NULL);
+ if (ret) {
+ mutex_unlock(&rza1_pctl->mutex);
+ return ret;
+ }
+
+ ret = pinmux_generic_add_function(pctldev, grpname, fngrps, 1,
+ pin_confs);
+ if (ret)
+ goto remove_group;
+ mutex_unlock(&rza1_pctl->mutex);
+
+ dev_info(rza1_pctl->dev, "Parsed function and group %s with %d pins\n",
+ grpname, of_pins);
+
+ return 0;
+
+remove_group:
+ dev_info(rza1_pctl->dev, "Unable to parse function and group %s\n",
+ grpname);
+ pinctrl_generic_remove_last_group(pctldev);
+ mutex_unlock(&rza1_pctl->mutex);
+
+ return ret;
+}
+
+/**
+ * rza1_remove_pmx_functions() - un-register pmx functions and groups
+ *
+ * @rza1_pctl: RZ/A1 pin controller device
+ */
+static void rza1_remove_pmx_functions(struct rza1_pinctrl *rza1_pctl)
+{
+ struct pinctrl_dev *pctldev = rza1_pctl->pctl;
+
+ mutex_lock(&rza1_pctl->mutex);
+ pinmux_generic_free_functions(pctldev);
+ mutex_unlock(&rza1_pctl->mutex);
+}
+
+/**
+ * rza1_parse_gpiochip() - parse and register a gpio chip and pin range
+ *
+ * The gpio controller subnode shall provide a "gpio-ranges" list property as
+ * defined by gpio device tree binding documentation.
+ * Gpio chips and pin ranges are here collected, but ranges are registered
+ * later, after pin controller has been registered too. Only gpiochips are
+ * registered here.
+ *
+ * @rza1_pctl: RZ/A1 pin controller device
+ * @np: of gpio-controller node
+ * @chip: gpio chip to register to gpiolib
+ * @range: pin range to register to pinctrl core
+ */
+static int rza1_parse_gpiochip(struct rza1_pinctrl *rza1_pctl,
+ struct device_node *np,
+ struct gpio_chip *chip,
+ struct pinctrl_gpio_range *range)
+{
+ int ret;
+ u32 pinctrl_base;
+ unsigned int gpioport;
+ struct of_phandle_args of_args;
+ const char *list_name = "gpio-ranges";
+
+ of_parse_phandle_with_fixed_args(np, list_name, 3, 0, &of_args);
+
+ /*
+ * Find out on which port this gpio-chip maps to inspecting the second
+ * argument of "gpio-ranges" property.
+ */
+ pinctrl_base = of_args.args[1];
+ gpioport = RZA1_PIN_TO_PORT(pinctrl_base);
+ if (gpioport > RZA1_NPORTS) {
+ dev_err(rza1_pctl->dev,
+ "Invalid values in property %s\n", list_name);
+ return -EINVAL;
+ }
+
+ *chip = rza1_gpiochip_template;
+ chip->base = -1;
+ chip->label = kasprintf(GFP_KERNEL, "%s-%d", np->name, gpioport);
+ chip->ngpio = of_args.args[2];
+ chip->of_node = np;
+ chip->parent = rza1_pctl->dev;
+
+ range->id = gpioport;
+ range->name = kasprintf(GFP_KERNEL, "%s-%d", np->name, gpioport);
+ range->pin_base = range->base = pinctrl_base;
+ range->npins = of_args.args[2];
+ range->gc = chip;
+
+ ret = devm_gpiochip_add_data(rza1_pctl->dev, chip,
+ &rza1_pctl->ports[gpioport]);
+ if (ret)
+ return ret;
+
+ dev_info(rza1_pctl->dev, "Parsed gpiochip %s with %d pins\n",
+ chip->label, chip->ngpio);
+
+ return 0;
+}
+
+/**
+ * rza1_parse_dt() - parse DT to collect gpiochips and pmx functions
+ *
+ * @rza1_pctl: RZ/A1 pin controller device
+ */
+static int rza1_parse_dt(struct rza1_pinctrl *rza1_pctl)
+{
+ int ret;
+ unsigned int npmxfuncs;
+ unsigned int ngpiochips;
+ unsigned int i;
+ struct gpio_chip *gpio_chips;
+ struct pinctrl_gpio_range *gpio_ranges;
+ struct device_node *np = rza1_pctl->dev->of_node;
+ struct device_node *child;
+
+ ngpiochips = rza1_count_gpio_chips(np);
+ if (ngpiochips) {
+ dev_info(rza1_pctl->dev, "Registering %u gpio chips\n",
+ ngpiochips);
+
+ gpio_chips = devm_kcalloc(rza1_pctl->dev, ngpiochips,
+ sizeof(*gpio_chips), GFP_KERNEL);
+ gpio_ranges = devm_kcalloc(rza1_pctl->dev, ngpiochips,
+ sizeof(*gpio_ranges), GFP_KERNEL);
+ if (!gpio_chips || !gpio_ranges)
+ return -ENOMEM;
+ } else {
+ dev_dbg(rza1_pctl->dev, "No gpiochip registered\n");
+ gpio_ranges = NULL;
+ }
+
+ rza1_pctl->gpio_ranges = gpio_ranges;
+
+ i = 0;
+ npmxfuncs = 0;
+ for_each_child_of_node(np, child) {
+ if (of_property_read_bool(child, "gpio-controller")) {
+ /* Never get here if ngpiochips == 0 */
+ ret = rza1_parse_gpiochip(rza1_pctl, child,
+ &gpio_chips[i],
+ &gpio_ranges[i]);
+ if (ret)
+ goto gpio_pmx_unregister;
+
+ ++i;
+ } else {
+ ret = rza1_parse_pmx_function(rza1_pctl, child);
+ if (ret)
+ goto gpio_pmx_unregister;
+
+ ++npmxfuncs;
+ }
+ }
+
+ rza1_pctl->ngpiochips = i;
+
+ dev_info(rza1_pctl->dev,
+ "Registered %u gpio controllers and %u pin mux functions\n",
+ rza1_pctl->ngpiochips, npmxfuncs);
+
+ return 0;
+
+gpio_pmx_unregister:
+ for (; i > 0; i--)
+ devm_gpiochip_remove(rza1_pctl->dev, &gpio_chips[i - 1]);
+
+ rza1_remove_pmx_functions(rza1_pctl);
+
+ return ret;
+}
+
+/**
+ * rza1_pinctrl_register() - Enumerate pins, ports, gpiochips and functions and
+ * register to pinctrl and gpio cores
+ *
+ * @rza1_pctl: RZ/A1 pin controller device
+ */
+static int rza1_pinctrl_register(struct rza1_pinctrl *rza1_pctl)
+{
+ int ret;
+ unsigned int i;
+ struct rza1_port *ports;
+ struct pinctrl_pin_desc *pins;
+
+ pins = devm_kcalloc(rza1_pctl->dev, RZA1_NPINS, sizeof(*pins),
+ GFP_KERNEL);
+ ports = devm_kcalloc(rza1_pctl->dev, RZA1_NPORTS, sizeof(*ports),
+ GFP_KERNEL);
+ if (!pins || !ports)
+ return -ENOMEM;
+
+ rza1_pctl->pins = pins;
+ rza1_pctl->desc.pins = pins;
+ rza1_pctl->desc.npins = RZA1_NPINS;
+ rza1_pctl->ports = ports;
+
+ for (i = 0; i < RZA1_NPINS; ++i) {
+ unsigned int port = RZA1_PIN_TO_PORT(i);
+ unsigned int offset = RZA1_PIN_TO_OFFSET(i);
+
+ pins[i].number = i;
+ pins[i].name = kasprintf(GFP_KERNEL, "P%u-%u", port, offset);
+
+ if (i % RZA1_PINS_PER_PORT == 0) {
+ /*
+ * Setup ports;
+ * they provide per-port lock and logical base address.
+ */
+ unsigned int port_id = RZA1_PIN_TO_PORT(i);
+
+ ports[port_id].id = port_id;
+ ports[port_id].base = rza1_pctl->base;
+ ports[port_id].pins = &pins[i];
+ spin_lock_init(&ports[port_id].lock);
+ }
+ }
+
+ ret = devm_pinctrl_register_and_init(rza1_pctl->dev, &rza1_pctl->desc,
+ rza1_pctl, &rza1_pctl->pctl);
+ if (ret) {
+ dev_err(rza1_pctl->dev,
+ "RZ/A1 pin controller registration failed\n");
+ return ret;
+ }
+
+ ret = rza1_parse_dt(rza1_pctl);
+ if (ret) {
+ dev_err(rza1_pctl->dev, "RZ/A1 DT parsing failed\n");
+ return ret;
+ }
+
+ for (i = 0; i < rza1_pctl->ngpiochips; i++)
+ pinctrl_add_gpio_range(rza1_pctl->pctl,
+ &rza1_pctl->gpio_ranges[i]);
+
+ return 0;
+}
+
+static int rza1_pinctrl_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource *res;
+ struct rza1_pinctrl *rza1_pctl;
+
+ rza1_pctl = devm_kzalloc(&pdev->dev, sizeof(*rza1_pctl), GFP_KERNEL);
+ if (!rza1_pctl)
+ return -ENOMEM;
+
+ rza1_pctl->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (ret)
+ return -ENODEV;
+
+ rza1_pctl->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(rza1_pctl->base))
+ return PTR_ERR(rza1_pctl->base);
+
+ mutex_init(&rza1_pctl->mutex);
+
+ platform_set_drvdata(pdev, rza1_pctl);
+
+ rza1_pctl->desc.name = DRIVER_NAME;
+ rza1_pctl->desc.pctlops = &rza1_pinctrl_ops;
+ rza1_pctl->desc.pmxops = &rza1_pinmux_ops;
+ rza1_pctl->desc.owner = THIS_MODULE;
+
+ ret = rza1_pinctrl_register(rza1_pctl);
+ if (ret)
+ return ret;
+
+ dev_info(&pdev->dev,
+ "RZ/A1 pin controller and gpio successfully registered\n");
+
+ return 0;
+}
+
+static const struct of_device_id rza1_pinctrl_of_match[] = {
+ { .compatible = "renesas,r7s72100-ports", },
+ { }
+};
+
+static struct platform_driver rza1_pinctrl_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = rza1_pinctrl_of_match,
+ },
+ .probe = rza1_pinctrl_probe,
+};
+
+static int __init rza1_pinctrl_init(void)
+{
+ return platform_driver_register(&rza1_pinctrl_driver);
+}
+core_initcall(rza1_pinctrl_init);
+
+MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org");
+MODULE_DESCRIPTION("Pin and gpio controller driver for Reneas RZ/A1 SoC");
+MODULE_LICENSE("GPL v2");
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-03-22 11:30 +0100 |
| Subject | Re: [PATCH v2 1/7] pinctrl: Renesas RZ/A1 pin and gpio controller |
| Message-ID | <tnLGG-Ta-19@gated-at.bofh.it> |
| In reply to | #1604777 |
Hi Jacopo,
On Mon, Mar 20, 2017 at 5:14 PM, Jacopo Mondi <jacopo+renesas@jmondi.org> wrote:
> Add combined gpio and pin controller driver for Renesas RZ/A1
> r7s72100 SoC.
>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Thanks for your patch!
> --- /dev/null
> +++ b/drivers/pinctrl/pinctrl-rza1.c
> +/*
> + * This pincontroller/gpio combined driver support Renesas devices of RZ/A1
> + * family.
> + * This includes SoCs which are sub- or super- sets of this particular line,
> + * as RZ/A1H (r7s721000), RZ/A1M (r7s721001) and RZ/A1L (r7s721002) are.
RZ/A1M = r7s721010, RZ/A1L = r7s721020
> +#define RZA1_ADDR(mem, reg, port) ((mem) + (reg) + ((port) * 4))
> +
> +#define RZA1_NPORTS 12
> +#define RZA1_PINS_PER_PORT 16
> +#define RZA1_NPINS (RZA1_PINS_PER_PORT * RZA1_NPORTS)
> +#define RZA1_PIN_TO_PORT(pin) ((pin) / RZA1_PINS_PER_PORT)
> +#define RZA1_PIN_TO_OFFSET(pin) ((pin) % RZA1_PINS_PER_PORT)
> +
> +/*
> + * Be careful here: the pin configuration subnodes in device tree enumerates
enumerate
> + * alternate functions from 1 to 8; subtract 1 before using macros so to match
> + * registers configuration which expects numbers from 0 to 7 instead.
register configuration
> + */
> +#define MUX_FUNC_OFFS 3
> +#define MUX_FUNC_MASK (BIT(MUX_FUNC_OFFS) - 1)
> +#define MUX_FUNC_PFC_MASK BIT(0)
> +#define MUX_FUNC_PFCE_MASK BIT(1)
> +#define MUX_FUNC_PFCEA_MASK BIT(2)
> +#define MUX_CONF_BIDIR BIT(0)
> +#define MUX_CONF_SWIO_INPUT BIT(1)
> +#define MUX_CONF_SWIO_OUTPUT BIT(2)
> +
> +/**
> + * rza1_pin_conf - describes a pin position, id, mux config and output value
> + *
> + * Use uint32_t to match types used in of_device nodes argument lists.
> + *
> + * @id: the pin identifier from 0 to RZA1_NPINS
> + * @port: the port where pin sits on
> + * @offset: pin offset in the port
> + * @mux: alternate function configuration settings
> + * @value: output value to set the pin to
> + */
> +struct rza1_pin_conf {
> + uint32_t id;
> + uint32_t port;
> + uint32_t offset;
> + uint32_t mux_conf;
> + uint32_t value;
In the kernel, we tend to use u32 instead of uint32_t.
But many of these fields can be smaller than 32 bits, right, saving some
memory (important when running with built-in RAM only).
> +/**
> + * rza1_pinctrl - RZ pincontroller device
> + *
> + * @dev: parent device structure
> + * @mutex: protect [pinctrl|pinmux]_generic functions
> + * @base: logical address base
> + * @nports: number of pin controller ports
> + * @ports: pin controller banks
> + * @ngpiochips: number of gpio chips
> + * @gpio_ranges: gpio ranges for pinctrl core
> + * @pins: pin array for pinctrl core
> + * @desc: pincontroller desc for pinctrl core
> + * @pctl: pinctrl device
> + */
> +struct rza1_pinctrl {
> + struct device *dev;
> +
> + struct mutex mutex;
> +
> + void __iomem *base;
> +
> + unsigned int nport;
> + struct rza1_port *ports;
> +
> + unsigned int ngpiochips;
> +
> + struct pinctrl_gpio_range *gpio_ranges;
> + struct pinctrl_pin_desc *pins;
> + struct pinctrl_desc desc;
> + struct pinctrl_dev *pctl;
It's a good idea not to mix pointers and integers, as the pointers will
be 64-bit on 64-bit platforms, leading to gaps due to alignment rules.
Not super-important here, as (for now) this driver is meant for 32-bit SoCs.
> +/**
> + * rza1_set_bit() - un-locked set/clear a single bit in pin configuration
> + * registers
> + */
> +static inline void rza1_set_bit(const struct rza1_port *port,
> + unsigned int reg, unsigned int offset,
> + bool set)
I think "reg" and "set" still fit on the previous lines (many more cases
in other functions).
I'd call "offset" "bit" (and "reg" "offset"?)
> +{
> + void __iomem *mem = RZA1_ADDR(port->base, reg, port->id);
I think this would be easier to read without using the RZA1_ADDR() macro.
> + u16 val = ioread16(mem);
> +
> + if (set)
> + val |= BIT(offset);
> + else
> + val &= ~BIT(offset);
> +
> + iowrite16(val, mem);
> +}
> +
> +static inline int rza1_get_bit(struct rza1_port *port,
> + unsigned int reg, unsigned int offset)
> +{
> + void __iomem *mem = RZA1_ADDR(port->base, reg, port->id);
> +
> + return ioread16(mem) & BIT(offset);
Same comments as for rza1_set_bit().
> +}
> +
> +/**
> + * rza1_pin_reset() - reset a pin to default initial state
> + *
> + * Reset pin state disabling input buffer and bi-directional control,
> + * and configure it as input port.
> + * Note that pin is now configured with direction as input but with input
> + * buffer disabled. This implies the pin value cannot be read in this state.
> + *
> + * @port: port where pin sits on
> + * @offset: pin offset
> + */
> +static void rza1_pin_reset(struct rza1_port *port,
> + unsigned int offset)
The above fits on a single line.
"pin" instead of "offset"?
> +{
> + spin_lock(&port->lock);
spin_lock_irqsave()? (everywhere)
> + rza1_set_bit(port, PIBC_REG, offset, 0);
> + rza1_set_bit(port, PBDC_REG, offset, 0);
> +
> + rza1_set_bit(port, PM_REG, offset, 1);
> + rza1_set_bit(port, PMC_REG, offset, 0);
> + rza1_set_bit(port, PIPC_REG, offset, 0);
> + spin_unlock(&port->lock);
spin_unlock_irqrestore()? (everywhere)
> +}
> +
> +static inline int rza1_pin_get_direction(struct rza1_port *port,
> + int offset)
The above fits on a single line.
"pin" instead of "offset" (many more below)?
> +/**
> + * rza1_pin_conf_validate() - make sure a single bit it set in mux_conf mask
is set
> + */
> +static inline int rza1_pin_conf_validate(u8 mux_conf)
> +{
> + do {
> + if (mux_conf & BIT(0))
> + break;
> + } while ((mux_conf >>= 1));
> +
> + return (mux_conf >> 1);
Please study <linux/bitops.h> to find a better way to do this ;-)
> +/**
> + * rza1_gpio_get() - read a gpio pin value
> + *
> + * Read gpio pin value through PPR register.
> + * Requires bi-directional mode to work when reading value of a pin
the value
> + * in output mode
> +/**
> + * rza1_pinmux_set() - retrieve pins from a group and apply them mux settings
their
> + *
> + * @pctldev: pin controller device
> + * @selector: function selector
> + * @group: group selector
> + */
> +static int rza1_pinmux_set(struct pinctrl_dev *pctldev, unsigned int selector,
> + unsigned int group)
> +{
> + int i;
> + struct group_desc *grp;
> + struct function_desc *func;
> + struct rza1_pin_conf *pin_confs;
> + struct rza1_pinctrl *rza1_pctl = pinctrl_dev_get_drvdata(pctldev);
Reverse Christmas tree ordering (longest line first)?
> +/**
> + * rza1_parse_pmx_function() - parse and register a pin mux function
> + *
> + * Pins for RZ SoC pin controller described by "renesas-pins" property.
> + *
> + * First argument in the list identifies the pin, while the second one
> + * describes the requested alternate function number and additional
> + * configuration parameter to be applied to the selected function.
> + *
> + * @rza1_pctl: RZ/A1 pin controller device
> + * @np: of pmx sub-node
> + */
> +static int rza1_parse_pmx_function(struct rza1_pinctrl *rza1_pctl,
> + struct device_node *np)
> +{
> + int ret;
> + int of_pins;
npins?
> + unsigned int i;
> + unsigned int *grpins;
> + const char *grpname;
> + const char **fngrps;
> + struct rza1_pin_conf *pin_confs;
> + struct pinctrl_dev *pctldev = rza1_pctl->pctl;
> + char const *prop_name = "renesas,pins";
const char *prop_name
Reverse Christmas tree ordering (longest line first)? (more below)
> +
> + of_pins = pinctrl_count_index_with_args(np, prop_name);
> + if (of_pins <= 0) {
> + dev_err(rza1_pctl->dev, "Missing %s property\n", prop_name);
> + return -ENOENT;
> + }
> +
> + /*
> + * Functions are made of 1 group only;
> + * in facts, functions and groups are identical for this pin controller
in fact
> + * except that functions carry an array of per-pin configurations
configuration
> + * settings.
> + */
> + pin_confs = devm_kcalloc(rza1_pctl->dev, of_pins, sizeof(*pin_confs),
> + GFP_KERNEL);
> + grpins = devm_kcalloc(rza1_pctl->dev, of_pins, sizeof(*grpins),
> + GFP_KERNEL);
> + fngrps = devm_kzalloc(rza1_pctl->dev, sizeof(*fngrps), GFP_KERNEL);
> +
> + if (!pin_confs || !grpins || !fngrps)
> + return -ENOMEM;
> +
> + /* Collect pin positions and mux settings to store them in function */
> + for (i = 0; i < of_pins; ++i) {
> + struct rza1_pin_conf *pin_conf = &pin_confs[i];
> + struct of_phandle_args of_pins_args;
> +
> + ret = pinctrl_parse_index_with_args(np, prop_name, i,
> + &of_pins_args);
> + if (ret)
> + return ret;
> +
> + if (of_pins_args.args_count < RZA1_PINMUX_OF_ARGS) {
> + dev_err(rza1_pctl->dev,
> + "Wrong arguments number for %s property\n",
number of arguments
> +/**
> + * rza1_parse_gpiochip() - parse and register a gpio chip and pin range
> + *
> + * The gpio controller subnode shall provide a "gpio-ranges" list property as
> + * defined by gpio device tree binding documentation.
> + * Gpio chips and pin ranges are here collected, but ranges are registered
> + * later, after pin controller has been registered too. Only gpiochips are
after the pin controller
> + * registered here.
> + *
> + * @rza1_pctl: RZ/A1 pin controller device
> + * @np: of gpio-controller node
> + * @chip: gpio chip to register to gpiolib
> + * @range: pin range to register to pinctrl core
> + */
> +static int rza1_parse_gpiochip(struct rza1_pinctrl *rza1_pctl,
> + struct device_node *np,
> + struct gpio_chip *chip,
> + struct pinctrl_gpio_range *range)
> +{
> + int ret;
> + u32 pinctrl_base;
> + unsigned int gpioport;
> + struct of_phandle_args of_args;
> + const char *list_name = "gpio-ranges";
> +
> + of_parse_phandle_with_fixed_args(np, list_name, 3, 0, &of_args);
This function can fail.
> +
> + /*
> + * Find out on which port this gpio-chip maps to inspecting the second
by inspecting
> + * argument of "gpio-ranges" property.
the "gpio-ranges" property.
> + */
> + pinctrl_base = of_args.args[1];
> + gpioport = RZA1_PIN_TO_PORT(pinctrl_base);
> + if (gpioport > RZA1_NPORTS) {
> + dev_err(rza1_pctl->dev,
> + "Invalid values in property %s\n", list_name);
> + return -EINVAL;
> + }
> +
> + *chip = rza1_gpiochip_template;
> + chip->base = -1;
> + chip->label = kasprintf(GFP_KERNEL, "%s-%d", np->name, gpioport);
devm_kasprintf()?
"%s-%u"
> + chip->ngpio = of_args.args[2];
> + chip->of_node = np;
> + chip->parent = rza1_pctl->dev;
> +
> + range->id = gpioport;
> + range->name = kasprintf(GFP_KERNEL, "%s-%d", np->name, gpioport);
Reuse chip->label?
> +/**
> + * rza1_pinctrl_register() - Enumerate pins, ports, gpiochips and functions and
> + * register to pinctrl and gpio cores
> + *
> + * @rza1_pctl: RZ/A1 pin controller device
> + */
> +static int rza1_pinctrl_register(struct rza1_pinctrl *rza1_pctl)
> +{
> + for (i = 0; i < RZA1_NPINS; ++i) {
> + unsigned int port = RZA1_PIN_TO_PORT(i);
> + unsigned int offset = RZA1_PIN_TO_OFFSET(i);
> +
> + pins[i].number = i;
> + pins[i].name = kasprintf(GFP_KERNEL, "P%u-%u", port, offset);
devm_kasprintf()
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
[toc] | [prev] | [next] | [standalone]
| From | jacopo <jacopo@jmondi.org> |
|---|---|
| Date | 2017-03-23 15:30 +0100 |
| Subject | Re: [PATCH v2 1/7] pinctrl: Renesas RZ/A1 pin and gpio controller |
| Message-ID | <tobUu-3mq-11@gated-at.bofh.it> |
| In reply to | #1606331 |
Hi Geert,
thanks for detailed review
On Wed, Mar 22, 2017 at 11:26:58AM +0100, Geert Uytterhoeven wrote:
> Hi Jacopo,
>
> On Mon, Mar 20, 2017 at 5:14 PM, Jacopo Mondi <jacopo+renesas@jmondi.org> wrote:
> > Add combined gpio and pin controller driver for Renesas RZ/A1
> > r7s72100 SoC.
> >
> > Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
>
> Thanks for your patch!
>
> > --- /dev/null
> > +++ b/drivers/pinctrl/pinctrl-rza1.c
>
> > +/*
> > + * This pincontroller/gpio combined driver support Renesas devices of RZ/A1
> > + * family.
> > + * This includes SoCs which are sub- or super- sets of this particular line,
> > + * as RZ/A1H (r7s721000), RZ/A1M (r7s721001) and RZ/A1L (r7s721002) are.
>
> RZ/A1M = r7s721010, RZ/A1L = r7s721020
>
> > +#define RZA1_ADDR(mem, reg, port) ((mem) + (reg) + ((port) * 4))
>
>
> > +
> > +#define RZA1_NPORTS 12
> > +#define RZA1_PINS_PER_PORT 16
> > +#define RZA1_NPINS (RZA1_PINS_PER_PORT * RZA1_NPORTS)
> > +#define RZA1_PIN_TO_PORT(pin) ((pin) / RZA1_PINS_PER_PORT)
> > +#define RZA1_PIN_TO_OFFSET(pin) ((pin) % RZA1_PINS_PER_PORT)
> > +
> > +/*
> > + * Be careful here: the pin configuration subnodes in device tree enumerates
>
> enumerate
>
> > + * alternate functions from 1 to 8; subtract 1 before using macros so to match
> > + * registers configuration which expects numbers from 0 to 7 instead.
>
> register configuration
>
> > + */
> > +#define MUX_FUNC_OFFS 3
> > +#define MUX_FUNC_MASK (BIT(MUX_FUNC_OFFS) - 1)
> > +#define MUX_FUNC_PFC_MASK BIT(0)
> > +#define MUX_FUNC_PFCE_MASK BIT(1)
> > +#define MUX_FUNC_PFCEA_MASK BIT(2)
> > +#define MUX_CONF_BIDIR BIT(0)
> > +#define MUX_CONF_SWIO_INPUT BIT(1)
> > +#define MUX_CONF_SWIO_OUTPUT BIT(2)
> > +
> > +/**
> > + * rza1_pin_conf - describes a pin position, id, mux config and output value
> > + *
> > + * Use uint32_t to match types used in of_device nodes argument lists.
> > + *
> > + * @id: the pin identifier from 0 to RZA1_NPINS
> > + * @port: the port where pin sits on
> > + * @offset: pin offset in the port
> > + * @mux: alternate function configuration settings
> > + * @value: output value to set the pin to
> > + */
> > +struct rza1_pin_conf {
> > + uint32_t id;
> > + uint32_t port;
> > + uint32_t offset;
> > + uint32_t mux_conf;
> > + uint32_t value;
>
> In the kernel, we tend to use u32 instead of uint32_t.
> But many of these fields can be smaller than 32 bits, right, saving some
> memory (important when running with built-in RAM only).
>
I'll move these to u8 (and u16 where appropriate) and fix all the
above grammar comments
> > +/**
> > + * rza1_pinctrl - RZ pincontroller device
> > + *
> > + * @dev: parent device structure
> > + * @mutex: protect [pinctrl|pinmux]_generic functions
> > + * @base: logical address base
> > + * @nports: number of pin controller ports
> > + * @ports: pin controller banks
> > + * @ngpiochips: number of gpio chips
> > + * @gpio_ranges: gpio ranges for pinctrl core
> > + * @pins: pin array for pinctrl core
> > + * @desc: pincontroller desc for pinctrl core
> > + * @pctl: pinctrl device
> > + */
> > +struct rza1_pinctrl {
> > + struct device *dev;
> > +
> > + struct mutex mutex;
> > +
> > + void __iomem *base;
> > +
> > + unsigned int nport;
> > + struct rza1_port *ports;
> > +
> > + unsigned int ngpiochips;
> > +
> > + struct pinctrl_gpio_range *gpio_ranges;
> > + struct pinctrl_pin_desc *pins;
> > + struct pinctrl_desc desc;
> > + struct pinctrl_dev *pctl;
>
> It's a good idea not to mix pointers and integers, as the pointers will
> be 64-bit on 64-bit platforms, leading to gaps due to alignment rules.
> Not super-important here, as (for now) this driver is meant for 32-bit SoCs.
>
I grouped this variables "logically", and even if I understand your
concerns, there will be a single "struct rza1_pinctrl" per driver
instance, so I hope we can tollerate some padding bytes in favour of more
clearness. Also, as you said, there are no 64-bits RZ platforms atm.
> > +/**
> > + * rza1_set_bit() - un-locked set/clear a single bit in pin configuration
> > + * registers
> > + */
> > +static inline void rza1_set_bit(const struct rza1_port *port,
> > + unsigned int reg, unsigned int offset,
> > + bool set)
>
> I think "reg" and "set" still fit on the previous lines (many more cases
> in other functions).
>
> I'd call "offset" "bit" (and "reg" "offset"?)
I'll s/offset/bit and s/offset/pin where appropriate
>
> > +{
> > + void __iomem *mem = RZA1_ADDR(port->base, reg, port->id);
>
> I think this would be easier to read without using the RZA1_ADDR() macro.
>
Don't know... I can change this if you prefer... there's nothing nasty
hidden behind this macro...
> > + u16 val = ioread16(mem);
> > +
> > + if (set)
> > + val |= BIT(offset);
> > + else
> > + val &= ~BIT(offset);
> > +
> > + iowrite16(val, mem);
> > +}
> > +
> > +static inline int rza1_get_bit(struct rza1_port *port,
> > + unsigned int reg, unsigned int offset)
> > +{
> > + void __iomem *mem = RZA1_ADDR(port->base, reg, port->id);
> > +
> > + return ioread16(mem) & BIT(offset);
>
> Same comments as for rza1_set_bit().
>
> > +}
> > +
> > +/**
> > + * rza1_pin_reset() - reset a pin to default initial state
> > + *
> > + * Reset pin state disabling input buffer and bi-directional control,
> > + * and configure it as input port.
> > + * Note that pin is now configured with direction as input but with input
> > + * buffer disabled. This implies the pin value cannot be read in this state.
> > + *
> > + * @port: port where pin sits on
> > + * @offset: pin offset
> > + */
> > +static void rza1_pin_reset(struct rza1_port *port,
> > + unsigned int offset)
>
> The above fits on a single line.
>
> "pin" instead of "offset"?
>
> > +{
> > + spin_lock(&port->lock);
>
> spin_lock_irqsave()? (everywhere)
>
Quoting spinlock.txt:
----
If you have a case where you have to protect a data structure across
several CPU's and you want to use spinlocks you can potentially use
cheaper versions of the spinlocks. IFF you know that the spinlocks are
never used in interrupt handlers, you can use the non-irq versions:
spin_lock(&lock);
...
spin_unlock(&lock);
----
And there's nothing preventing an interrupt handling routine to
set/change a gpio value, so I'll change these to the _irqsave version, thanks.
> > + rza1_set_bit(port, PIBC_REG, offset, 0);
> > + rza1_set_bit(port, PBDC_REG, offset, 0);
> > +
> > + rza1_set_bit(port, PM_REG, offset, 1);
> > + rza1_set_bit(port, PMC_REG, offset, 0);
> > + rza1_set_bit(port, PIPC_REG, offset, 0);
> > + spin_unlock(&port->lock);
>
> spin_unlock_irqrestore()? (everywhere)
>
> > +}
> > +
> > +static inline int rza1_pin_get_direction(struct rza1_port *port,
> > + int offset)
>
> The above fits on a single line.
>
> "pin" instead of "offset" (many more below)?
>
> > +/**
> > + * rza1_pin_conf_validate() - make sure a single bit it set in mux_conf mask
>
> is set
>
> > + */
> > +static inline int rza1_pin_conf_validate(u8 mux_conf)
> > +{
> > + do {
> > + if (mux_conf & BIT(0))
> > + break;
> > + } while ((mux_conf >>= 1));
> > +
> > + return (mux_conf >> 1);
>
> Please study <linux/bitops.h> to find a better way to do this ;-)
>
Did my homework and I'm thinking of replacing this function with
something like:
if (ffs(mask) != fls(mask))) { }
Is this what you were suggesting?
> > +/**
> > + * rza1_gpio_get() - read a gpio pin value
> > + *
> > + * Read gpio pin value through PPR register.
> > + * Requires bi-directional mode to work when reading value of a pin
>
> the value
>
> > + * in output mode
>
>
> > +/**
> > + * rza1_pinmux_set() - retrieve pins from a group and apply them mux settings
>
> their
>
> > + *
> > + * @pctldev: pin controller device
> > + * @selector: function selector
> > + * @group: group selector
> > + */
> > +static int rza1_pinmux_set(struct pinctrl_dev *pctldev, unsigned int selector,
> > + unsigned int group)
> > +{
> > + int i;
> > + struct group_desc *grp;
> > + struct function_desc *func;
> > + struct rza1_pin_conf *pin_confs;
> > + struct rza1_pinctrl *rza1_pctl = pinctrl_dev_get_drvdata(pctldev);
>
> Reverse Christmas tree ordering (longest line first)?
>
>
>
> > +/**
> > + * rza1_parse_pmx_function() - parse and register a pin mux function
> > + *
> > + * Pins for RZ SoC pin controller described by "renesas-pins" property.
> > + *
> > + * First argument in the list identifies the pin, while the second one
> > + * describes the requested alternate function number and additional
> > + * configuration parameter to be applied to the selected function.
> > + *
> > + * @rza1_pctl: RZ/A1 pin controller device
> > + * @np: of pmx sub-node
> > + */
> > +static int rza1_parse_pmx_function(struct rza1_pinctrl *rza1_pctl,
> > + struct device_node *np)
> > +{
> > + int ret;
> > + int of_pins;
>
> npins?
>
> > + unsigned int i;
> > + unsigned int *grpins;
> > + const char *grpname;
> > + const char **fngrps;
> > + struct rza1_pin_conf *pin_confs;
> > + struct pinctrl_dev *pctldev = rza1_pctl->pctl;
> > + char const *prop_name = "renesas,pins";
>
> const char *prop_name
>
> Reverse Christmas tree ordering (longest line first)? (more below)
or const char const * to make sure also the content is never changed. But
that's an overkill maybe?
Thanks
j
>
> > +
> > + of_pins = pinctrl_count_index_with_args(np, prop_name);
> > + if (of_pins <= 0) {
> > + dev_err(rza1_pctl->dev, "Missing %s property\n", prop_name);
> > + return -ENOENT;
> > + }
> > +
> > + /*
> > + * Functions are made of 1 group only;
> > + * in facts, functions and groups are identical for this pin controller
>
> in fact
>
> > + * except that functions carry an array of per-pin configurations
>
> configuration
>
> > + * settings.
> > + */
> > + pin_confs = devm_kcalloc(rza1_pctl->dev, of_pins, sizeof(*pin_confs),
> > + GFP_KERNEL);
> > + grpins = devm_kcalloc(rza1_pctl->dev, of_pins, sizeof(*grpins),
> > + GFP_KERNEL);
> > + fngrps = devm_kzalloc(rza1_pctl->dev, sizeof(*fngrps), GFP_KERNEL);
> > +
> > + if (!pin_confs || !grpins || !fngrps)
> > + return -ENOMEM;
> > +
> > + /* Collect pin positions and mux settings to store them in function */
> > + for (i = 0; i < of_pins; ++i) {
> > + struct rza1_pin_conf *pin_conf = &pin_confs[i];
> > + struct of_phandle_args of_pins_args;
> > +
> > + ret = pinctrl_parse_index_with_args(np, prop_name, i,
> > + &of_pins_args);
> > + if (ret)
> > + return ret;
> > +
> > + if (of_pins_args.args_count < RZA1_PINMUX_OF_ARGS) {
> > + dev_err(rza1_pctl->dev,
> > + "Wrong arguments number for %s property\n",
>
> number of arguments
>
>
> > +/**
> > + * rza1_parse_gpiochip() - parse and register a gpio chip and pin range
> > + *
> > + * The gpio controller subnode shall provide a "gpio-ranges" list property as
> > + * defined by gpio device tree binding documentation.
> > + * Gpio chips and pin ranges are here collected, but ranges are registered
> > + * later, after pin controller has been registered too. Only gpiochips are
>
> after the pin controller
>
> > + * registered here.
> > + *
> > + * @rza1_pctl: RZ/A1 pin controller device
> > + * @np: of gpio-controller node
> > + * @chip: gpio chip to register to gpiolib
> > + * @range: pin range to register to pinctrl core
> > + */
> > +static int rza1_parse_gpiochip(struct rza1_pinctrl *rza1_pctl,
> > + struct device_node *np,
> > + struct gpio_chip *chip,
> > + struct pinctrl_gpio_range *range)
> > +{
> > + int ret;
> > + u32 pinctrl_base;
> > + unsigned int gpioport;
> > + struct of_phandle_args of_args;
> > + const char *list_name = "gpio-ranges";
> > +
> > + of_parse_phandle_with_fixed_args(np, list_name, 3, 0, &of_args);
>
> This function can fail.
>
> > +
> > + /*
> > + * Find out on which port this gpio-chip maps to inspecting the second
>
> by inspecting
>
> > + * argument of "gpio-ranges" property.
>
> the "gpio-ranges" property.
>
> > + */
> > + pinctrl_base = of_args.args[1];
> > + gpioport = RZA1_PIN_TO_PORT(pinctrl_base);
> > + if (gpioport > RZA1_NPORTS) {
> > + dev_err(rza1_pctl->dev,
> > + "Invalid values in property %s\n", list_name);
> > + return -EINVAL;
> > + }
> > +
> > + *chip = rza1_gpiochip_template;
> > + chip->base = -1;
> > + chip->label = kasprintf(GFP_KERNEL, "%s-%d", np->name, gpioport);
>
> devm_kasprintf()?
>
> "%s-%u"
>
> > + chip->ngpio = of_args.args[2];
> > + chip->of_node = np;
> > + chip->parent = rza1_pctl->dev;
> > +
> > + range->id = gpioport;
> > + range->name = kasprintf(GFP_KERNEL, "%s-%d", np->name, gpioport);
>
> Reuse chip->label?
>
>
> > +/**
> > + * rza1_pinctrl_register() - Enumerate pins, ports, gpiochips and functions and
> > + * register to pinctrl and gpio cores
> > + *
> > + * @rza1_pctl: RZ/A1 pin controller device
> > + */
> > +static int rza1_pinctrl_register(struct rza1_pinctrl *rza1_pctl)
> > +{
>
> > + for (i = 0; i < RZA1_NPINS; ++i) {
> > + unsigned int port = RZA1_PIN_TO_PORT(i);
> > + unsigned int offset = RZA1_PIN_TO_OFFSET(i);
> > +
> > + pins[i].number = i;
> > + pins[i].name = kasprintf(GFP_KERNEL, "P%u-%u", port, offset);
>
> devm_kasprintf()
>
> 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
[toc] | [prev] | [next] | [standalone]
| From | Jacopo Mondi <jacopo+renesas@jmondi.org> |
|---|---|
| Date | 2017-03-20 17:50 +0100 |
| Subject | [PATCH v2 4/7] arm: dts: r7s72100: Add pin controller node |
| Message-ID | <tn8Fl-7tv-35@gated-at.bofh.it> |
| In reply to | #1604741 |
Add pin controller node with 12 gpio controller sub-nodes to
r7s72100 dtsi.
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
arch/arm/boot/dts/r7s72100.dtsi | 80 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 80 insertions(+)
diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/r7s72100.dtsi
index 614ba79..9eb8751f 100644
--- a/arch/arm/boot/dts/r7s72100.dtsi
+++ b/arch/arm/boot/dts/r7s72100.dtsi
@@ -183,6 +183,86 @@
};
};
+ pinctrl: pinctrl@fcfe3000 {
+ compatible = "renesas,r7s72100-ports";
+
+ #pinctrl-cells = <1>;
+
+ reg = <0xfcfe3000 0x4248>;
+
+ port0: gpio-0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 0 6>;
+ };
+
+ port1: gpio-1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 16 16>;
+ };
+
+ port2: gpio-2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 32 16>;
+ };
+
+ port3: gpio-3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 48 16>;
+ };
+
+ port4: gpio-4 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 64 16>;
+ };
+
+ port5: gpio-5 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 80 11>;
+ };
+
+ port6: gpio-6 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 96 16>;
+ };
+
+ port7: gpio-7 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 112 16>;
+ };
+
+ port8: gpio-8 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 128 16>;
+ };
+
+ port9: gpio-9 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 144 8>;
+ };
+
+ port10: gpio-10 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 160 16>;
+ };
+
+ port11: gpio-11 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 176 16>;
+ };
+ };
+
scif0: serial@e8007000 {
compatible = "renesas,scif-r7s72100", "renesas,scif";
reg = <0xe8007000 64>;
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-03-22 14:20 +0100 |
| Subject | Re: [PATCH v2 4/7] arm: dts: r7s72100: Add pin controller node |
| Message-ID | <tnOlc-2UB-17@gated-at.bofh.it> |
| In reply to | #1604780 |
Hi Jacopo,
On Mon, Mar 20, 2017 at 5:14 PM, Jacopo Mondi <jacopo+renesas@jmondi.org> wrote:
> Add pin controller node with 12 gpio controller sub-nodes to
> r7s72100 dtsi.
>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
> --- a/arch/arm/boot/dts/r7s72100.dtsi
> +++ b/arch/arm/boot/dts/r7s72100.dtsi
> @@ -183,6 +183,86 @@
> };
> };
>
> + pinctrl: pinctrl@fcfe3000 {
> + compatible = "renesas,r7s72100-ports";
> +
> + #pinctrl-cells = <1>;
> +
> + reg = <0xfcfe3000 0x4248>;
How did you get to 0x4248? I had expected 0x4230.
Not that it matters much, Linux rounds it up to a multiple of PAGE_SIZE anyway.
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
[toc] | [prev] | [next] | [standalone]
| From | jacopo <jacopo@jmondi.org> |
|---|---|
| Date | 2017-03-23 17:20 +0100 |
| Subject | Re: [PATCH v2 4/7] arm: dts: r7s72100: Add pin controller node |
| Message-ID | <todCV-4FK-9@gated-at.bofh.it> |
| In reply to | #1606463 |
Hi Geert,
On Wed, Mar 22, 2017 at 02:12:04PM +0100, Geert Uytterhoeven wrote:
> Hi Jacopo,
>
> On Mon, Mar 20, 2017 at 5:14 PM, Jacopo Mondi <jacopo+renesas@jmondi.org> wrote:
> > Add pin controller node with 12 gpio controller sub-nodes to
> > r7s72100 dtsi.
> >
> > Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
>
> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
>
> > --- a/arch/arm/boot/dts/r7s72100.dtsi
> > +++ b/arch/arm/boot/dts/r7s72100.dtsi
> > @@ -183,6 +183,86 @@
> > };
> > };
> >
> > + pinctrl: pinctrl@fcfe3000 {
> > + compatible = "renesas,r7s72100-ports";
> > +
> > + #pinctrl-cells = <1>;
> > +
> > + reg = <0xfcfe3000 0x4248>;
>
> How did you get to 0x4248? I had expected 0x4230.
> Not that it matters much, Linux rounds it up to a multiple of PAGE_SIZE anyway.
>
I guess I probably confused hex and dec values, as the correct
calculation here would have been (4200 + C * 4)
That 4248 value is what you get with (4200 + 12 * 4) so I probably
typed 12 in the calculator instead of C :)
I'll change this even if it does not make any difference..
> 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
[toc] | [prev] | [next] | [standalone]
| From | Jacopo Mondi <jacopo+renesas@jmondi.org> |
|---|---|
| Date | 2017-03-20 18:00 +0100 |
| Subject | [PATCH v2 3/7] arm: dts: dt-bindings: Add Renesas RZ pinctrl header |
| Message-ID | <tn8P0-7wZ-13@gated-at.bofh.it> |
| In reply to | #1604741 |
Add dt-bindings for Renesas r7s72100 pin controller header file. Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org> --- include/dt-bindings/pinctrl/r7s72100-pinctrl.h | 36 ++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 include/dt-bindings/pinctrl/r7s72100-pinctrl.h diff --git a/include/dt-bindings/pinctrl/r7s72100-pinctrl.h b/include/dt-bindings/pinctrl/r7s72100-pinctrl.h new file mode 100644 index 0000000..98852d3 --- /dev/null +++ b/include/dt-bindings/pinctrl/r7s72100-pinctrl.h @@ -0,0 +1,36 @@ +/* + * Defines macros and constants for Renesas RZ/A1 pin controller pin + * muxing functions. + */ +#ifndef __DT_BINDINGS_PINCTRL_RENESAS_RZA1_H +#define __DT_BINDINGS_PINCTRL_RENESAS_RZA1_H + +#define RZA1_PINS_PER_PORT 16 + +/* Create the pin index from it's bank and position numbers */ +#define PIN(b, p) ((b) * RZA1_PINS_PER_PORT + (p)) + +/* + * Flags to apply to alternate function configuration + * All of the following are mutually exclusive. + */ + +/* + * Pin is bi-directional. + * Alternate function that need both input/outpu functionalities shall + * be configured as bidirectional. + * Eg. SDA/SCL pins of an I2c interface. + */ +#define BI_DIR (1 << 3) + +/* + * Flags used to ask software drive the pin I/O direction overriding the + * alternate function configuration. + * Some alternate function requires software to force I/O direction of a pin, + * ovverriding the designated one. + * Reference to the HW manual to know when this flag shall be used. + */ +#define SWIO_IN (1 << 4) +#define SWIO_OUT (1 << 5) + +#endif -- 2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-03-22 11:40 +0100 |
| Subject | Re: [PATCH v2 3/7] arm: dts: dt-bindings: Add Renesas RZ pinctrl header |
| Message-ID | <tnLQn-Xe-31@gated-at.bofh.it> |
| In reply to | #1604791 |
On Mon, Mar 20, 2017 at 5:14 PM, Jacopo Mondi <jacopo+renesas@jmondi.org> wrote:
> Add dt-bindings for Renesas r7s72100 pin controller header file.
>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> ---
> include/dt-bindings/pinctrl/r7s72100-pinctrl.h | 36 ++++++++++++++++++++++++++
> 1 file changed, 36 insertions(+)
> create mode 100644 include/dt-bindings/pinctrl/r7s72100-pinctrl.h
>
> diff --git a/include/dt-bindings/pinctrl/r7s72100-pinctrl.h b/include/dt-bindings/pinctrl/r7s72100-pinctrl.h
> new file mode 100644
> index 0000000..98852d3
> --- /dev/null
> +++ b/include/dt-bindings/pinctrl/r7s72100-pinctrl.h
> @@ -0,0 +1,36 @@
> +/*
> + * Defines macros and constants for Renesas RZ/A1 pin controller pin
> + * muxing functions.
> + */
> +#ifndef __DT_BINDINGS_PINCTRL_RENESAS_RZA1_H
> +#define __DT_BINDINGS_PINCTRL_RENESAS_RZA1_H
> +
> +#define RZA1_PINS_PER_PORT 16
> +
> +/* Create the pin index from it's bank and position numbers */
its bank
> +#define PIN(b, p) ((b) * RZA1_PINS_PER_PORT + (p))
> +
> +/*
> + * Flags to apply to alternate function configuration
> + * All of the following are mutually exclusive.
> + */
> +
> +/*
> + * Pin is bi-directional.
> + * Alternate function that need both input/outpu functionalities shall
An alternate function that needs ... output
> + * be configured as bidirectional.
> + * Eg. SDA/SCL pins of an I2c interface.
> + */
> +#define BI_DIR (1 << 3)
> +
> +/*
> + * Flags used to ask software drive the pin I/O direction overriding the
to drive
> + * alternate function configuration.
> + * Some alternate function requires software to force I/O direction of a pin,
functions require
> + * ovverriding the designated one.
overriding
> + * Reference to the HW manual to know when this flag shall be used.
Refer
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
[toc] | [prev] | [next] | [standalone]
| From | Jacopo Mondi <jacopo+renesas@jmondi.org> |
|---|---|
| Date | 2017-03-20 18:00 +0100 |
| Subject | [PATCH v2 5/7] arm: dts: genmai: Add SCIF2 pin group |
| Message-ID | <tn8P1-7wZ-33@gated-at.bofh.it> |
| In reply to | #1604741 |
Add pin configuration subnode for SCIF2 serial debug interface.
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
arch/arm/boot/dts/r7s72100-genmai.dts | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm/boot/dts/r7s72100-genmai.dts b/arch/arm/boot/dts/r7s72100-genmai.dts
index 118a8e2..569c86a 100644
--- a/arch/arm/boot/dts/r7s72100-genmai.dts
+++ b/arch/arm/boot/dts/r7s72100-genmai.dts
@@ -11,6 +11,7 @@
/dts-v1/;
#include "r7s72100.dtsi"
+#include <dt-bindings/pinctrl/r7s72100-pinctrl.h>
/ {
model = "Genmai";
@@ -36,6 +37,15 @@
};
};
+&pinctrl {
+
+ scif2_pins: serial2 {
+ /* P3_0 as TxD2; P3_2 as RxD2 */
+ renesas,pins = <PIN(3, 0) 6>,
+ <PIN(3, 2) 4>;
+ };
+};
+
&extal_clk {
clock-frequency = <13330000>;
};
@@ -60,6 +70,9 @@
};
&scif2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&scif2_pins>;
+
status = "okay";
};
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-03-22 14:20 +0100 |
| Subject | Re: [PATCH v2 5/7] arm: dts: genmai: Add SCIF2 pin group |
| Message-ID | <tnOlb-2UB-3@gated-at.bofh.it> |
| In reply to | #1604800 |
On Mon, Mar 20, 2017 at 5:14 PM, Jacopo Mondi <jacopo+renesas@jmondi.org> wrote:
> Add pin configuration subnode for SCIF2 serial debug interface.
>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
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
[toc] | [prev] | [next] | [standalone]
| From | Jacopo Mondi <jacopo+renesas@jmondi.org> |
|---|---|
| Date | 2017-03-20 18:30 +0100 |
| Subject | [PATCH v2 2/7] dt-bindings: pinctrl: Add RZ/A1 bindings doc |
| Message-ID | <tn9i1-7Yx-15@gated-at.bofh.it> |
| In reply to | #1604741 |
Add device tree bindings documentation for Renesas RZ/A1 gpio and pin
controller.
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
.../bindings/pinctrl/renesas,rza1-pinctrl.txt | 144 +++++++++++++++++++++
1 file changed, 144 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt
diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt
new file mode 100644
index 0000000..0474860
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt
@@ -0,0 +1,144 @@
+Renesas RZ/A1 combined Pin and GPIO controller
+
+Renesas SoCs of RZ/A1 family feature a combined Pin and GPIO controller
+hardware controller, named "Ports" in the hardware reference manual.
+Pin multiplexing and GPIO configuration is performed on a per-pin basis
+writing configuration values to per-port register sets.
+Each "port" features up to 16 pins, each of them configurable for GPIO
+function (port mode) or in alternate function mode.
+Up to 8 different alternate function modes exist for each single pin.
+
+Pin controller node
+-------------------
+
+Required properties:
+ - compatible
+ this shall be "renesas,r7s72100-ports".
+
+ - #pinctrl-cells
+ as defined by pinctrl-bindings.txt, this is the number
+ of cells (in addition to pin index) required to configure a single pin.
+ Shall be set to 1.
+
+ - reg
+ address base and length of the memory area where pin controller
+ hardware is mapped to.
+
+Example:
+Pin controller node for RZ/A1H SoC (r7s72100)
+
+pinctrl: pinctrl@fcfe3000 {
+ compatible = "renesas,r7s72100-ports";
+
+ #pinctrl-cells = <1>;
+
+ reg = <0xfcfe3000 0x4248>;
+};
+
+Sub-nodes
+---------
+
+The child nodes of the pin controller node describe a pin multiplexing
+function or a gpio controller alternatively.
+
+- Pin multiplexing sub-nodes:
+ A pin multiplexing sub-node describes how to configure a set of
+ (or a single) pin in some desired alternate function mode.
+ A single sub-node may define several pin configurations groups.
+
+ Required properties:
+ - renesas,pins
+ describes an array of pin multiplexing configurations.
+ When a pin has to be configured in alternate function mode, use this
+ property to identify the pin by its global index, and provide its
+ alternate function configuration description along with it.
+ When multiple pins are required to be configured as part of the same
+ alternate function (odds are single-pin alternate functions exist) they
+ shall be specified as members of the same argument list of a single
+ "renesas-pins" property.
+ Helper macros to ease calculating the pin index from its position
+ (port where it sits on and pin offset), and alternate function
+ configuration options are provided in pin controller header file at:
+ include/dt-bindings/pinctrl/r7s72100-pinctrl.h
+
+ Example:
+ A serial communication interface with a TX output pin and a RX input pin.
+
+ &pinctrl {
+ scif2_pins: serial2 {
+ renesas,pins = <PIN(3, 0) 6>,
+ <PIN(3, 2) 4>;
+ };
+ }
+
+ Pin #0 on port #3 is configured in alternate function #6.
+ Pin #2 on port #3 is configured in alternate function #4.
+
+ Example 2:
+ I2c master: both SDA and SCL pins need bi-directional operations
+
+ &pinctrl {
+ i2c2_pins: i2c2 {
+ renesas,pins = <PIN(1, 4) (1 | BI_DIR)>,
+ <PIN(1, 5) (1 | BI_DIR)>;
+ };
+ }
+
+ Pin #4 on port #1 is configured in alternate function #1.
+ Pin #5 on port #1 is configured in alternate function #1.
+ Both need to work in bi-directional mode.
+
+ Example 3:
+ Multi-function timer input and output compare pins.
+ The hardware manual prescribes this pins to have input/output direction
+ specified by software. Configure TIOC0A as input and TIOC0B as output.
+
+ &pinctrl {
+ tioc0_pins: tioc0 {
+ renesas,pins = <PIN(4, 0) (2 | SWIO_IN)>,
+ <PIN(4, 1) (2 | SWIO_OUT)>;
+ };
+ }
+
+ Pin #0 on port #4 is configured in alternate function #2 with IO direction
+ specified by software as input.
+ Pin #1 on port #4 is configured in alternate function #1 with IO direction
+ specified by software as output.
+
+- GPIO controller sub-nodes:
+ Each port of r7s72100 pin controller hardware is itself a gpio controller.
+ Different SoCs have different number of available pins per port, but
+ generally speaking, each of them can be configured in GPIO ("port") mode
+ on this hardware.
+ Describe gpio-controllers using sub-nodes with the following properties.
+
+ Required properties:
+ - gpio-controller
+ empty property as defined by gpio bindings documentation.
+ - #gpio-cells
+ number of cells required to identify and configure a GPIO.
+ Shall be 2.
+ - gpio-ranges
+ Describes a gpio controller specifying its specific pin base, the pin
+ base in the global pin numbering space, and the number of controlled
+ pins, as defined by gpio bindings documentation. Refer to this file
+ for a more detailed description.
+
+ Example:
+ A gpio controller node, controlling 16 pins indexed from 0.
+ The gpio controller base in the global pin indexing space is pin 48, thus
+ pins [0 - 15] on this controller map to pins [48 - 63] in the global pin
+ indexing space.
+
+ port3: gpio-3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 48 16>;
+ };
+
+ A device node willing to use pins controlled by this gpio controller, shall
+ refer to it as follows:
+
+ led1 {
+ gpios = <&port3 10 GPIO_ACTIVE_LOW>;
+ };
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-03-22 11:40 +0100 |
| Subject | Re: [PATCH v2 2/7] dt-bindings: pinctrl: Add RZ/A1 bindings doc |
| Message-ID | <tnLQm-Xe-27@gated-at.bofh.it> |
| In reply to | #1604828 |
Hi Jacopo,
On Mon, Mar 20, 2017 at 5:14 PM, Jacopo Mondi <jacopo+renesas@jmondi.org> wrote:
> Add device tree bindings documentation for Renesas RZ/A1 gpio and pin
for the Renesas ...
> controller.
>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> ---
> .../bindings/pinctrl/renesas,rza1-pinctrl.txt | 144 +++++++++++++++++++++
> 1 file changed, 144 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt
>
> diff --git a/Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt
> new file mode 100644
> index 0000000..0474860
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt
> @@ -0,0 +1,144 @@
> +Renesas RZ/A1 combined Pin and GPIO controller
> +
> +Renesas SoCs of RZ/A1 family feature a combined Pin and GPIO controller
the RZ/A1 family
> +hardware controller, named "Ports" in the hardware reference manual.
bogus "hardware controller"
> +Sub-nodes
> +---------
> +
> +The child nodes of the pin controller node describe a pin multiplexing
> +function or a gpio controller alternatively.
> +
> +- Pin multiplexing sub-nodes:
> + A pin multiplexing sub-node describes how to configure a set of
> + (or a single) pin in some desired alternate function mode.
> + A single sub-node may define several pin configurations groups.
> +
> + Required properties:
> + - renesas,pins
Just "pins"?
> + describes an array of pin multiplexing configurations.
> + When a pin has to be configured in alternate function mode, use this
> + property to identify the pin by its global index, and provide its
> + alternate function configuration description along with it.
> + When multiple pins are required to be configured as part of the same
> + alternate function (odds are single-pin alternate functions exist) they
> + shall be specified as members of the same argument list of a single
> + "renesas-pins" property.
> + Helper macros to ease calculating the pin index from its position
> + (port where it sits on and pin offset), and alternate function
> + configuration options are provided in pin controller header file at:
the pin ... file
> + include/dt-bindings/pinctrl/r7s72100-pinctrl.h
Hence I'd include that file in this patch, as it's part of the bindings.
> + Example:
> + A serial communication interface with a TX output pin and a RX input pin.
an RX
> +
> + &pinctrl {
> + scif2_pins: serial2 {
> + renesas,pins = <PIN(3, 0) 6>,
> + <PIN(3, 2) 4>;
Single line?
> + };
> + }
> +
> + Pin #0 on port #3 is configured in alternate function #6.
> + Pin #2 on port #3 is configured in alternate function #4.
as alternate function
> +
> + Example 2:
> + I2c master: both SDA and SCL pins need bi-directional operations
> +
> + &pinctrl {
> + i2c2_pins: i2c2 {
> + renesas,pins = <PIN(1, 4) (1 | BI_DIR)>,
> + <PIN(1, 5) (1 | BI_DIR)>;
> + };
> + }
> +
> + Pin #4 on port #1 is configured in alternate function #1.
> + Pin #5 on port #1 is configured in alternate function #1.
as alternate function
> + Both need to work in bi-directional mode.
> +
> + Example 3:
> + Multi-function timer input and output compare pins.
> + The hardware manual prescribes this pins to have input/output direction
> + specified by software. Configure TIOC0A as input and TIOC0B as output.
> +
> + &pinctrl {
> + tioc0_pins: tioc0 {
> + renesas,pins = <PIN(4, 0) (2 | SWIO_IN)>,
> + <PIN(4, 1) (2 | SWIO_OUT)>;
> + };
> + }
> +
> + Pin #0 on port #4 is configured in alternate function #2 with IO direction
> + specified by software as input.
> + Pin #1 on port #4 is configured in alternate function #1 with IO direction
> + specified by software as output.
as alternate function
> +- GPIO controller sub-nodes:
> + Each port of r7s72100 pin controller hardware is itself a gpio controller.
the r7s72100 pin controller hardware
> + Different SoCs have different number of available pins per port, but
numbers of
> + generally speaking, each of them can be configured in GPIO ("port") mode
> + on this hardware.
> + Describe gpio-controllers using sub-nodes with the following properties.
> +
> + Required properties:
> + - gpio-controller
> + empty property as defined by gpio bindings documentation.
the gpio bindings documentation
> + - #gpio-cells
> + number of cells required to identify and configure a GPIO.
> + Shall be 2.
> + - gpio-ranges
> + Describes a gpio controller specifying its specific pin base, the pin
> + base in the global pin numbering space, and the number of controlled
> + pins, as defined by gpio bindings documentation. Refer to this file
the gpio bindings documentation
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
[toc] | [prev] | [next] | [standalone]
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-03-22 14:30 +0100 |
| Subject | Re: [PATCH v2 2/7] dt-bindings: pinctrl: Add RZ/A1 bindings doc |
| Message-ID | <tnOuS-32T-29@gated-at.bofh.it> |
| In reply to | #1606341 |
On Wed, Mar 22, 2017 at 11:33 AM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> On Mon, Mar 20, 2017 at 5:14 PM, Jacopo Mondi <jacopo+renesas@jmondi.org> wrote:
>> Add device tree bindings documentation for Renesas RZ/A1 gpio and pin
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt
ulating the pin index from its position
>> + (port where it sits on and pin offset), and alternate function
>> + configuration options are provided in pin controller header file at:
>
> the pin ... file
>
>> + include/dt-bindings/pinctrl/r7s72100-pinctrl.h
>
> Hence I'd include that file in this patch, as it's part of the bindings.
Ah, that would create a hard dependency between the DTS files and the
DT bindings, which typically go in through different trees.
As the driver replicates the definitions from the header, the include file
can go in with the DTS updates.
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
[toc] | [prev] | [next] | [standalone]
| From | jacopo <jacopo@jmondi.org> |
|---|---|
| Date | 2017-03-22 16:40 +0100 |
| Subject | Re: [PATCH v2 2/7] dt-bindings: pinctrl: Add RZ/A1 bindings doc |
| Message-ID | <tnQwG-4GP-7@gated-at.bofh.it> |
| In reply to | #1606471 |
Hi Geert,
thanks for reviews
On Wed, Mar 22, 2017 at 02:20:08PM +0100, Geert Uytterhoeven wrote:
> On Wed, Mar 22, 2017 at 11:33 AM, Geert Uytterhoeven
> <geert@linux-m68k.org> wrote:
> > On Mon, Mar 20, 2017 at 5:14 PM, Jacopo Mondi <jacopo+renesas@jmondi.org> wrote:
> >> Add device tree bindings documentation for Renesas RZ/A1 gpio and pin
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt
>
> ulating the pin index from its position
> >> + (port where it sits on and pin offset), and alternate function
> >> + configuration options are provided in pin controller header file at:
> >
> > the pin ... file
> >
> >> + include/dt-bindings/pinctrl/r7s72100-pinctrl.h
> >
> > Hence I'd include that file in this patch, as it's part of the bindings.
>
> Ah, that would create a hard dependency between the DTS files and the
> DT bindings, which typically go in through different trees.
> As the driver replicates the definitions from the header, the include file
> can go in with the DTS updates.
>
Sorry, got confused by multiple reviews here..
Are you suggesting to squash [03/07] in [04/07] here?
Thanks
j
> 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
[toc] | [prev] | [next] | [standalone]
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-03-22 17:00 +0100 |
| Subject | Re: [PATCH v2 2/7] dt-bindings: pinctrl: Add RZ/A1 bindings doc |
| Message-ID | <tnQQ2-4OP-47@gated-at.bofh.it> |
| In reply to | #1606666 |
Hi Jacopo,
On Wed, Mar 22, 2017 at 4:36 PM, jacopo <jacopo@jmondi.org> wrote:
> On Wed, Mar 22, 2017 at 02:20:08PM +0100, Geert Uytterhoeven wrote:
>> On Wed, Mar 22, 2017 at 11:33 AM, Geert Uytterhoeven
>> <geert@linux-m68k.org> wrote:
>> > On Mon, Mar 20, 2017 at 5:14 PM, Jacopo Mondi <jacopo+renesas@jmondi.org> wrote:
>> >> Add device tree bindings documentation for Renesas RZ/A1 gpio and pin
>> >> --- /dev/null
>> >> +++ b/Documentation/devicetree/bindings/pinctrl/renesas,rza1-pinctrl.txt
>>
>> ulating the pin index from its position
>> >> + (port where it sits on and pin offset), and alternate function
>> >> + configuration options are provided in pin controller header file at:
>> >
>> > the pin ... file
>> >
>> >> + include/dt-bindings/pinctrl/r7s72100-pinctrl.h
>> >
>> > Hence I'd include that file in this patch, as it's part of the bindings.
>>
>> Ah, that would create a hard dependency between the DTS files and the
>> DT bindings, which typically go in through different trees.
>> As the driver replicates the definitions from the header, the include file
>> can go in with the DTS updates.
>>
>
> Sorry, got confused by multiple reviews here..
> Are you suggesting to squash [03/07] in [04/07] here?
No, I suggested to squash [03/07] into [02/07].
But upon second thought, that's not such a good idea, as it creates an
additional dependency.
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
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web