Skip to content

Commit 7271b4a

Browse files
Julien Massotaaillet
authored andcommitted
drivers: pinctrl: Add R-Car Gen4 support
Renesas R-Car Gen4 is different from Gen3 regarding pinmux. While Gen3 had only one base address to manage all pins, Gen4 has one set of pinmux registers per GPIO banks. We could expose one pinmux register per GPIO controllers, but that would break potential compatibility with Linux Device tree. Instead create a reg_base array to parse all reg base from device tree and identify proper base address based on the pin definition. This imply to add a pfc_base parameter to most of the pfc_rcar function. Signed-off-by: Julien Massot <[email protected]> Signed-off-by: Pierre Marzin <[email protected]> Signed-off-by: Aymeric Aillet <[email protected]>
1 parent afca374 commit 7271b4a

File tree

10 files changed

+275
-137
lines changed

10 files changed

+275
-137
lines changed

drivers/pinctrl/pfc_rcar.c

Lines changed: 61 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021 IoT.bzh
2+
* Copyright (c) 2021-2023 IoT.bzh
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*
@@ -10,13 +10,24 @@
1010
#include <zephyr/arch/cpu.h>
1111
#include <zephyr/devicetree.h>
1212
#include <zephyr/drivers/pinctrl.h>
13+
#include <rcar_pfc_defs.h>
1314
#include <soc.h>
1415
#include <zephyr/sys/util.h>
1516

16-
#define PFC_REG_BASE DT_INST_REG_ADDR(0)
1717
#define PFC_RCAR_PMMR 0x0
18-
#define PFC_RCAR_GPSR 0x100
19-
#define PFC_RCAR_IPSR 0x200
18+
19+
/* Gen3 only has one base address, Gen4 has one per GPIO controller */
20+
#if defined(CONFIG_SOC_SERIES_RCAR_GEN3)
21+
static const uint32_t reg_base[] = {DT_INST_REG_ADDR(0)};
22+
#elif defined(CONFIG_SOC_SERIES_RCAR_GEN4)
23+
/* swap both arguments */
24+
#define PFC_REG_ADDRESS(idx, node_id) DT_REG_ADDR_BY_IDX(node_id, idx)
25+
static const uint32_t reg_base[] = {
26+
LISTIFY(DT_NUM_REGS(DT_DRV_INST(0)), PFC_REG_ADDRESS, (,), DT_DRV_INST(0))
27+
};
28+
#else
29+
#error Unsupported SoC Series
30+
#endif
2031

2132
/*
2233
* Each drive step is either encoded in 2 or 3 bits.
@@ -30,37 +41,45 @@
3041
/* Some registers such as IPSR GPSR or DRVCTRL are protected and
3142
* must be preceded to a write to PMMR with the inverse value.
3243
*/
33-
static void pfc_rcar_write(uint32_t offs, uint32_t val)
44+
static void pfc_rcar_write(uint32_t pfc_base, uint32_t offs, uint32_t val)
3445
{
35-
sys_write32(~val, PFC_REG_BASE + PFC_RCAR_PMMR);
36-
sys_write32(val, PFC_REG_BASE + offs);
46+
sys_write32(~val, pfc_base + PFC_RCAR_PMMR);
47+
sys_write32(val, pfc_base + offs);
3748
}
3849

3950
/* Set the pin either in gpio or peripheral */
40-
static void pfc_rcar_set_gpsr(uint16_t pin, bool peripheral)
51+
static void pfc_rcar_set_gpsr(uint32_t pfc_base,
52+
uint16_t pin, bool peripheral)
4153
{
54+
#if defined(CONFIG_SOC_SERIES_RCAR_GEN3)
55+
/* On Gen3 we have multiple GPSR at one base address */
4256
uint8_t bank = pin / 32;
57+
#elif defined(CONFIG_SOC_SERIES_RCAR_GEN4)
58+
/* On Gen4 we have one GPSR at multiple base address */
59+
uint8_t bank = 0;
60+
#endif
4361
uint8_t bit = pin % 32;
44-
uint32_t val = sys_read32(PFC_REG_BASE + PFC_RCAR_GPSR +
62+
uint32_t val = sys_read32(pfc_base + PFC_RCAR_GPSR +
4563
bank * sizeof(uint32_t));
4664

4765
if (peripheral) {
4866
val |= BIT(bit);
4967
} else {
5068
val &= ~BIT(bit);
5169
}
52-
pfc_rcar_write(PFC_RCAR_GPSR + bank * sizeof(uint32_t), val);
70+
pfc_rcar_write(pfc_base, PFC_RCAR_GPSR + bank * sizeof(uint32_t), val);
5371
}
5472

5573
/* Set peripheral function */
56-
static void pfc_rcar_set_ipsr(const struct rcar_pin_func *rcar_func)
74+
static void pfc_rcar_set_ipsr(uint32_t pfc_base,
75+
const struct rcar_pin_func *rcar_func)
5776
{
5877
uint16_t reg_offs = PFC_RCAR_IPSR + rcar_func->bank * sizeof(uint32_t);
59-
uint32_t val = sys_read32(PFC_REG_BASE + reg_offs);
78+
uint32_t val = sys_read32(pfc_base + reg_offs);
6079

6180
val &= ~(0xFU << rcar_func->shift);
6281
val |= (rcar_func->func << rcar_func->shift);
63-
pfc_rcar_write(reg_offs, val);
82+
pfc_rcar_write(pfc_base, reg_offs, val);
6483
}
6584

6685
static uint32_t pfc_rcar_get_drive_reg(uint16_t pin, uint8_t *offset,
@@ -87,7 +106,8 @@ static uint32_t pfc_rcar_get_drive_reg(uint16_t pin, uint8_t *offset,
87106
* using DRVCTRLx registers, some pins have 8 steps (3 bits size encoded)
88107
* some have 4 steps (2 bits size encoded).
89108
*/
90-
static int pfc_rcar_set_drive_strength(uint16_t pin, uint8_t strength)
109+
static int pfc_rcar_set_drive_strength(uint32_t pfc_base, uint16_t pin,
110+
uint8_t strength)
91111
{
92112
uint8_t offset, size, step;
93113
uint32_t reg, val;
@@ -107,11 +127,11 @@ static int pfc_rcar_set_drive_strength(uint16_t pin, uint8_t strength)
107127
*/
108128
strength = (strength / step) - 1U;
109129
/* clear previous drive strength value */
110-
val = sys_read32(PFC_REG_BASE + reg);
130+
val = sys_read32(pfc_base + reg);
111131
val &= ~GENMASK(offset + size - 1U, offset);
112132
val |= strength << offset;
113133

114-
pfc_rcar_write(reg, val);
134+
pfc_rcar_write(pfc_base, reg, val);
115135

116136
return 0;
117137
}
@@ -135,7 +155,7 @@ static const struct pfc_bias_reg *pfc_rcar_get_bias_reg(uint16_t pin,
135155
return NULL;
136156
}
137157

138-
int pfc_rcar_set_bias(uint16_t pin, uint16_t flags)
158+
int pfc_rcar_set_bias(uint32_t pfc_base, uint16_t pin, uint16_t flags)
139159
{
140160
uint32_t val;
141161
uint8_t bit;
@@ -146,53 +166,66 @@ int pfc_rcar_set_bias(uint16_t pin, uint16_t flags)
146166
}
147167

148168
/* pull enable/disable*/
149-
val = sys_read32(PFC_REG_BASE + bias_reg->puen);
169+
val = sys_read32(pfc_base + bias_reg->puen);
150170
if ((flags & RCAR_PIN_FLAGS_PUEN) == 0U) {
151-
sys_write32(val & ~BIT(bit), PFC_REG_BASE + bias_reg->puen);
171+
sys_write32(val & ~BIT(bit), pfc_base + bias_reg->puen);
152172
return 0;
153173
}
154-
sys_write32(val | BIT(bit), PFC_REG_BASE + bias_reg->puen);
174+
sys_write32(val | BIT(bit), pfc_base + bias_reg->puen);
155175

156176
/* pull - up/down */
157-
val = sys_read32(PFC_REG_BASE + bias_reg->pud);
177+
val = sys_read32(pfc_base + bias_reg->pud);
158178
if (flags & RCAR_PIN_FLAGS_PUD) {
159-
sys_write32(val | BIT(bit), PFC_REG_BASE + bias_reg->pud);
179+
sys_write32(val | BIT(bit), pfc_base + bias_reg->pud);
160180
} else {
161-
sys_write32(val & ~BIT(bit), PFC_REG_BASE + bias_reg->pud);
181+
sys_write32(val & ~BIT(bit), pfc_base + bias_reg->pud);
162182
}
163183
return 0;
164184
}
165185

166186
int pinctrl_configure_pin(const pinctrl_soc_pin_t *pin)
167187
{
168188
int ret = 0;
189+
uint8_t reg_index;
190+
uint32_t pfc_base;
191+
192+
ret = pfc_rcar_get_reg_index(pin->pin, &reg_index);
193+
if (ret) {
194+
return ret;
195+
}
196+
197+
if (reg_index >= ARRAY_SIZE(reg_base)) {
198+
return -EINVAL;
199+
}
200+
201+
pfc_base = reg_base[reg_index];
169202

170203
/* Set pin as GPIO if capable */
171204
if (RCAR_IS_GP_PIN(pin->pin)) {
172-
pfc_rcar_set_gpsr(pin->pin, false);
205+
pfc_rcar_set_gpsr(pfc_base, pin->pin, false);
173206
} else if ((pin->flags & RCAR_PIN_FLAGS_FUNC_SET) == 0U) {
174207
/* A function must be set for non GPIO capable pin */
175208
return -EINVAL;
176209
}
177210

178211
/* Select function for pin */
179212
if ((pin->flags & RCAR_PIN_FLAGS_FUNC_SET) != 0U) {
180-
pfc_rcar_set_ipsr(&pin->func);
213+
pfc_rcar_set_ipsr(pfc_base, &pin->func);
181214

182215
if (RCAR_IS_GP_PIN(pin->pin)) {
183-
pfc_rcar_set_gpsr(pin->pin, true);
216+
pfc_rcar_set_gpsr(pfc_base, pin->pin, true);
184217
}
185218

186219
if ((pin->flags & RCAR_PIN_FLAGS_PULL_SET) != 0U) {
187-
ret = pfc_rcar_set_bias(pin->pin, pin->flags);
220+
ret = pfc_rcar_set_bias(pfc_base, pin->pin, pin->flags);
188221
if (ret < 0) {
189222
return ret;
190223
}
191224
}
192225
}
193226

194227
if (pin->drive_strength != 0U) {
195-
ret = pfc_rcar_set_drive_strength(pin->pin,
228+
ret = pfc_rcar_set_drive_strength(pfc_base, pin->pin,
196229
pin->drive_strength);
197230
}
198231

include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-rcar-common.h

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021 IoT.bzh
2+
* Copyright (c) 2021-2023 IoT.bzh
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -40,4 +40,36 @@
4040
*/
4141
#define RCAR_NOGP_PIN(pin) (PIN_NOGPSR_START + pin)
4242

43+
/* Renesas Gen4 has IPSR registers at different base address
44+
* reg is here an index for the base address.
45+
* Each base address has 4 IPSR banks.
46+
*/
47+
#define IPnSR(bank, reg, shift, func) \
48+
IPSR(((reg) << 4U) | (bank), shift, func)
49+
50+
#define IP0SR0(shift, func) IPnSR(0, 0, shift, func)
51+
#define IP1SR0(shift, func) IPnSR(1, 0, shift, func)
52+
#define IP2SR0(shift, func) IPnSR(2, 0, shift, func)
53+
#define IP3SR0(shift, func) IPnSR(3, 0, shift, func)
54+
#define IP0SR1(shift, func) IPnSR(0, 1, shift, func)
55+
#define IP1SR1(shift, func) IPnSR(1, 1, shift, func)
56+
#define IP2SR1(shift, func) IPnSR(2, 1, shift, func)
57+
#define IP3SR1(shift, func) IPnSR(3, 1, shift, func)
58+
#define IP0SR2(shift, func) IPnSR(0, 2, shift, func)
59+
#define IP1SR2(shift, func) IPnSR(1, 2, shift, func)
60+
#define IP2SR2(shift, func) IPnSR(2, 2, shift, func)
61+
#define IP3SR2(shift, func) IPnSR(3, 2, shift, func)
62+
#define IP0SR3(shift, func) IPnSR(0, 3, shift, func)
63+
#define IP1SR3(shift, func) IPnSR(1, 3, shift, func)
64+
#define IP2SR3(shift, func) IPnSR(2, 3, shift, func)
65+
#define IP3SR3(shift, func) IPnSR(3, 3, shift, func)
66+
#define IP0SR4(shift, func) IPnSR(0, 4, shift, func)
67+
#define IP1SR4(shift, func) IPnSR(1, 4, shift, func)
68+
#define IP2SR4(shift, func) IPnSR(2, 4, shift, func)
69+
#define IP3SR4(shift, func) IPnSR(3, 4, shift, func)
70+
#define IP0SR5(shift, func) IPnSR(0, 5, shift, func)
71+
#define IP1SR5(shift, func) IPnSR(1, 5, shift, func)
72+
#define IP2SR5(shift, func) IPnSR(2, 5, shift, func)
73+
#define IP3SR5(shift, func) IPnSR(3, 5, shift, func)
74+
4375
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_RCAR_COMMON_H_ */
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# SPDX-License-Identifier: Apache-2.0
22

33
add_subdirectory(${SOC_SERIES})
4+
zephyr_include_directories(common)
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright (c) 2023 IoT.bzh
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
*/
7+
8+
#ifndef ZEPHYR_SOC_ARM_RENESAS_RCAR_COMMON_PINCTRL_SOC_H_
9+
#define ZEPHYR_SOC_ARM_RENESAS_RCAR_COMMON_PINCTRL_SOC_H_
10+
11+
#include <zephyr/devicetree.h>
12+
#include <zephyr/dt-bindings/pinctrl/renesas/pinctrl-rcar-common.h>
13+
#include <stdint.h>
14+
#include <zephyr/sys/util_macro.h>
15+
16+
struct rcar_pin_func {
17+
uint8_t bank:5; /* bank number 0 - 18 */
18+
uint8_t shift:5; /* bit shift 0 - 28 */
19+
uint8_t func:4; /* choice from 0x0 to 0xF */
20+
};
21+
/** Pull-up, pull-down, or bias disable is requested */
22+
#define RCAR_PIN_FLAGS_PULL_SET BIT(0)
23+
/** Performs on/off control of the pull resistors */
24+
#define RCAR_PIN_FLAGS_PUEN BIT(1)
25+
/** Select pull-up resistor if set pull-down otherwise */
26+
#define RCAR_PIN_FLAGS_PUD BIT(2)
27+
/** Alternate function for the pin is requested */
28+
#define RCAR_PIN_FLAGS_FUNC_SET BIT(3)
29+
30+
#define RCAR_PIN_PULL_UP (RCAR_PIN_FLAGS_PULL_SET | RCAR_PIN_FLAGS_PUEN | RCAR_PIN_FLAGS_PUD)
31+
#define RCAR_PIN_PULL_DOWN (RCAR_PIN_FLAGS_PULL_SET | RCAR_PIN_FLAGS_PUEN)
32+
#define RCAR_PIN_PULL_DISABLE RCAR_PIN_FLAGS_PULL_SET
33+
34+
/** Type for R-Car pin. */
35+
typedef struct pinctrl_soc_pin {
36+
uint16_t pin;
37+
struct rcar_pin_func func;
38+
uint8_t flags;
39+
uint8_t drive_strength;
40+
} pinctrl_soc_pin_t;
41+
42+
#define RCAR_IPSR(node_id) DT_PROP_BY_IDX(node_id, pin, 1)
43+
#define RCAR_HAS_IPSR(node_id) DT_PROP_HAS_IDX(node_id, pin, 1)
44+
45+
/* Offsets are defined in dt-bindings pinctrl-rcar-common.h */
46+
#define RCAR_PIN_FUNC(node_id) \
47+
{ \
48+
((RCAR_IPSR(node_id) >> 10U) & 0x1FU), \
49+
((RCAR_IPSR(node_id) >> 4U) & 0x1FU), \
50+
((RCAR_IPSR(node_id) & 0xFU)) \
51+
}
52+
53+
#define RCAR_PIN_FLAGS(node_id) \
54+
DT_PROP(node_id, bias_pull_up) * RCAR_PIN_PULL_UP | \
55+
DT_PROP(node_id, bias_pull_down) * RCAR_PIN_PULL_DOWN | \
56+
DT_PROP(node_id, bias_disable) * RCAR_PIN_PULL_DISABLE | \
57+
RCAR_HAS_IPSR(node_id) * RCAR_PIN_FLAGS_FUNC_SET
58+
59+
#define RCAR_DT_PIN(node_id) \
60+
{ \
61+
.pin = DT_PROP_BY_IDX(node_id, pin, 0), \
62+
.func = COND_CODE_1(RCAR_HAS_IPSR(node_id), \
63+
(RCAR_PIN_FUNC(node_id)), (0)), \
64+
.flags = RCAR_PIN_FLAGS(node_id), \
65+
.drive_strength = \
66+
COND_CODE_1(DT_NODE_HAS_PROP(node_id, drive_strength), \
67+
(DT_PROP(node_id, drive_strength)), (0)), \
68+
},
69+
70+
/**
71+
* @brief Utility macro to initialize each pin.
72+
*
73+
* @param node_id Node identifier.
74+
* @param state_prop State property name.
75+
* @param idx State property entry index.
76+
*/
77+
#define Z_PINCTRL_STATE_PIN_INIT(node_id, state_prop, idx) \
78+
RCAR_DT_PIN(DT_PROP_BY_IDX(node_id, state_prop, idx))
79+
80+
/**
81+
* @brief Utility macro to initialize state pins contained in a given property.
82+
*
83+
* @param node_id Node identifier.
84+
* @param prop Property name describing state pins.
85+
*/
86+
#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \
87+
{ DT_FOREACH_PROP_ELEM(node_id, prop, Z_PINCTRL_STATE_PIN_INIT) }
88+
89+
struct pfc_drive_reg_field {
90+
uint16_t pin;
91+
uint8_t offset;
92+
uint8_t size;
93+
};
94+
95+
struct pfc_drive_reg {
96+
uint32_t reg;
97+
const struct pfc_drive_reg_field fields[8];
98+
};
99+
100+
struct pfc_bias_reg {
101+
uint32_t puen; /** Pull-enable or pull-up control register */
102+
uint32_t pud; /** Pull-up/down or pull-down control register */
103+
const uint16_t pins[32];
104+
};
105+
106+
const struct pfc_bias_reg *pfc_rcar_get_bias_regs(void);
107+
const struct pfc_drive_reg *pfc_rcar_get_drive_regs(void);
108+
109+
/**
110+
* @brief set the register index for a given pin
111+
*
112+
* @param the pin
113+
* @param pointer for the resulting register index
114+
* @return 0 if the register index is found, negative
115+
* errno otherwise.
116+
*/
117+
int pfc_rcar_get_reg_index(uint8_t pin, uint8_t *reg_index);
118+
119+
/**
120+
* @brief Utility macro to check if a pin is GPIO capable
121+
*
122+
* @param pin
123+
* @return true if pin is GPIO capable false otherwise
124+
*/
125+
#define RCAR_IS_GP_PIN(pin) (pin < PIN_NOGPSR_START)
126+
127+
#endif /* ZEPHYR_SOC_ARM_RENESAS_RCAR_COMMON_PINCTRL_SOC_H_ */

0 commit comments

Comments
 (0)