Hi Jacopo, On Monday, February 20, 2017, Jacopo Mondi wrote: > > Add combined gpio and pin controller driver for Renesas RZ/A1 > r7s72100 SoC. > > Signed-off-by: Jacopo Mondi <jacopo+renesas@xxxxxxxxxx> > --- > drivers/pinctrl/Kconfig | 10 + > drivers/pinctrl/Makefile | 1 + > drivers/pinctrl/pinctrl-rza1.c | 1026 > ++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 1037 insertions(+) > create mode 100644 drivers/pinctrl/pinctrl-rza1.c > > diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig > index 8f8c2af..61310ac 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 r7s72100 RZ/A1 gpio and pinctrl driver" You can drop the "r7s72100" and just say RZ/A1. > +/** > + * 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. > + * When in alternate mode disable that (if not explicitly required) not > to > + * interfere with the alternate function mode. > + * > + * @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); > + if (input) > + rza1_set_bit(port, PIBC_REG, offset, 1); > + else { > + rza1_set_bit(port, PM_REG, offset, 0); > + rza1_set_bit(port, PBDC_REG, offset, 1); > + } > + spin_unlock(&port->lock); When input==true, you only set PIBC_REG. Otherwise you only set PM_REG and PBDC_REG. This would imply that this function will only ever get called once for a pin and never get called a second time with a different direction...meaning it would not really change a pin from output to input. I would assume that you would need to change this function to set those 3 registers either one way or the other. I would suggest: PIBC_REG = 1 /* always gets set for GPIO mode */ input: PM_REG = 1 PBDC_REG = 0 output: PM_REG = 0 PBDC_REG = 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 swio_en = !!(mux_conf & MUX_CONF_SWIO); > + bool input_en = !!(mux_conf & MUX_CONF_INPUT_ENABLE); > + > + rza1_pin_reset(port, offset); > + > + /* > + * When configuring pin with Software Controlled IO mode in > alternate > + * mode, do not enable bi-directional control to avoid driving Pn > + * value to the pin input. > + * When working in direct IO mode (aka alternate function drives the > + * pin direction), enable bi-directional control for input pins in > + * order to enable the pin's input buffer as a consequence. > + */ > + if ((!swio_en && input_en) || (swio_en && !input_en)) > + rza1_set_bit(port, PBDC_REG, offset, 1); Maybe just set PBDC_REG at the end of the function with everything else. See below... > + > + /* > + * 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_en) > + rza1_set_bit(port, PIPC_REG, offset, 1); > + > + rza1_set_bit(port, PMC_REG, offset, 1); > + > + if (swio_en) > + rza1_set_bit(port, PM_REG, offset, input_en); I would suggest something like this: if (bidir) rza1_set_bit(port, PBDC_REG, offset, 1); else { rza1_set_bit(port, PBDC_REG, offset, 0); rza1_set_bit(port, PM_REG, offset, swio_in); } rza1_set_bit(port, PMC_REG, offset, 1); > + > + return 0; > +} Chris