Skip to content

Commit

Permalink
soc: arm: renesas_rcar: add pinmux driver
Browse files Browse the repository at this point in the history
Allow to set an alternate function for a given pin configuration,
GPSR register allow to set a pin to GPIO or peripheral, IPSR allows
to choose an alternate function.

Other pin configurations such as pull-up are not supported at the
moment, but could be added later if useful.

Signed-off-by: Julien Massot <julien.massot@iot.bzh>
  • Loading branch information
Julien Massot authored and aaillet committed Oct 21, 2021
1 parent 7d17585 commit febbeee
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 0 deletions.
1 change: 1 addition & 0 deletions soc/arm/renesas_rcar/gen3/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@

zephyr_sources(
soc.c
pinmux_rcar.c
)
7 changes: 7 additions & 0 deletions soc/arm/renesas_rcar/gen3/Kconfig.series
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,12 @@ config SOC_SERIES_RCAR_GEN3
select CPU_HAS_DCLS
select SOC_FAMILY_RCAR
select CLOCK_CONTROL_RCAR_CPG_MSSR if CLOCK_CONTROL
select PINMUX_RCAR if PINMUX
help
Enable support for Renesas RCar Gen3 SoC series

config PINMUX_RCAR
bool "Renesas RCar Gen3 pinmux driver"
depends on SOC_SERIES_RCAR_GEN3
help
Enable the Renesas RCar Gen3 pinmux driver.
67 changes: 67 additions & 0 deletions soc/arm/renesas_rcar/gen3/pinmux-rcar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2021 IoT.bzh
*
* SPDX-License-Identifier: Apache-2.0
*
*/

#ifndef _PINMUX_RCAR__H_
#define _PINMUX_RCAR__H_
#include <stdint.h>
#include <stdbool.h>
#include <devicetree.h>
#include <sys/util.h>

struct rcar_pin {
/* select pin function */
uint8_t ipsr_bank; /* bank number 0 - 18 */
uint8_t ipsr_shift; /* bit shift 0 - 28 */
uint8_t ipsr_val; /* choice from 0x0 to 0xF */
/* Select gpio or function */
uint8_t gpsr_bank; /* bank number 0 - 7 */
uint8_t gpsr_num; /* pin index < 32 */
bool gpsr_val; /* gpio:false, peripheral:true */
};

void pinmux_rcar_set_pingroup(const struct rcar_pin *pins, size_t num_pins);

/* Get PIN associated with pinctrl-0 pin at index 'i' */
#define RCAR_IPSR(node_id, i) \
DT_PROP_BY_IDX(DT_PINCTRL_0(node_id, i), renesas_rcar_pins, 0)

/* Get PIN associated with pinctrl-0 pin at index 'i' */
#define RCAR_GPSR(node_id, i) \
DT_PROP_BY_IDX(DT_PINCTRL_0(node_id, i), renesas_rcar_pins, 1)

#define RCAR_DT_PIN(node_id, idx) \
{ \
((RCAR_IPSR(node_id, idx) >> 10) & 0x1F), \
(((RCAR_IPSR(node_id, idx) >> 4) & 0x7) * 4), \
((RCAR_IPSR(node_id, idx) & 0xF)), \
((RCAR_GPSR(node_id, idx) >> 7) & 0x7), \
((RCAR_GPSR(node_id, idx) >> 1) & 0x1F), \
((RCAR_GPSR(node_id, idx) & 0x1)), \
}

#define RCAR_DT_INST_PIN(inst, idx) \
RCAR_DT_PIN(DT_DRV_INST(inst), idx)

/* Get the number of pins for pinctrl-0 */
#define RCAR_DT_NUM_PINS(node_id) DT_NUM_PINCTRLS_BY_IDX(node_id, 0)

#define RCAR_DT_INST_NUM_PINS(inst) \
RCAR_DT_NUM_PINS(DT_DRV_INST(inst))

/* internal macro to structure things for use with UTIL_LISTIFY */
#define RCAR_DT_PIN_ELEM(idx, node_id) RCAR_DT_PIN(node_id, idx),

/* Construct an array intializer for rcar_pin for a device instance */
#define RCAR_DT_PINS(node_id) \
{ UTIL_LISTIFY(RCAR_DT_NUM_PINS(node_id), \
RCAR_DT_PIN_ELEM, node_id) \
}

#define RCAR_DT_INST_PINS(inst) \
RCAR_DT_PINS(DT_DRV_INST(inst))

#endif /* _PINMUX_RCAR__H_ */
62 changes: 62 additions & 0 deletions soc/arm/renesas_rcar/gen3/pinmux_rcar.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2021 IoT.bzh
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT renesas_rcar_pinmux

#include <devicetree.h>
#include <soc.h>
#include <device.h>

#define PINMUX_REG_BASE DT_INST_REG_ADDR(0)
#define PINMUX_RCAR_PMMR 0x0
#define PINMUX_RCAR_GPSR 0x100
#define PINMUX_RCAR_IPSR 0x200

/* Any write to IPSR or GPSR must be precede to a write to PMMR with
* the inverse value.
*/
static void pinmux_rcar_write(uint32_t offs, uint32_t val)
{
sys_write32(~val, PINMUX_REG_BASE + PINMUX_RCAR_PMMR);
sys_write32(val, PINMUX_REG_BASE + offs);
}

/* Set the pin either in gpio or peripheral */
static void pinmux_rcar_set_gpsr(uint8_t bank, uint8_t pos, bool peripheral)
{
uint32_t reg = sys_read32(PINMUX_REG_BASE + PINMUX_RCAR_GPSR +
bank * sizeof(uint32_t));

if (peripheral) {
reg |= BIT(pos);
} else {
reg &= ~BIT(pos);
}
pinmux_rcar_write(PINMUX_RCAR_GPSR + bank * sizeof(uint32_t), reg);
}

/* Set peripheral function */
static void pinmux_rcar_set_ipsr(uint8_t bank, uint8_t shift, uint8_t val)
{
uint32_t reg = sys_read32(PINMUX_REG_BASE + PINMUX_RCAR_IPSR +
bank * sizeof(uint32_t));

reg &= ~(0xF << shift);
reg |= (val << shift);
pinmux_rcar_write(PINMUX_RCAR_IPSR + bank * sizeof(uint32_t), reg);
}

void pinmux_rcar_set_pingroup(const struct rcar_pin *pins, size_t num_pins)
{
size_t i;

for (i = 0; i < num_pins; i++, pins++) {
pinmux_rcar_set_gpsr(pins->gpsr_bank, pins->gpsr_num,
pins->gpsr_val);
pinmux_rcar_set_ipsr(pins->ipsr_bank, pins->ipsr_shift,
pins->ipsr_val);
}
}
2 changes: 2 additions & 0 deletions soc/arm/renesas_rcar/gen3/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@
#define __GIC_PRESENT 0
#define __TIM_PRESENT 0

#include "pinmux-rcar.h"

#endif /* _SOC__H_ */

0 comments on commit febbeee

Please sign in to comment.